From 534df91349710aa7e20a858ddd68a71ae6450995 Mon Sep 17 00:00:00 2001 From: adishaa Date: Fri, 16 Jan 2026 07:00:13 -0800 Subject: [PATCH 01/10] feat: Add Feature Store Support to V3 --- .../sagemaker/mlops/feature_store/__init__.py | 129 ++++ .../mlops/feature_store/athena_query.py | 112 +++ .../mlops/feature_store/dataset_builder.py | 725 ++++++++++++++++++ .../mlops/feature_store/feature_definition.py | 107 +++ .../mlops/feature_store/feature_utils.py | 488 ++++++++++++ .../feature_store/ingestion_manager_pandas.py | 321 ++++++++ .../sagemaker/mlops/feature_store/inputs.py | 60 ++ 7 files changed, 1942 insertions(+) create mode 100644 sagemaker-mlops/src/sagemaker/mlops/feature_store/__init__.py create mode 100644 sagemaker-mlops/src/sagemaker/mlops/feature_store/athena_query.py create mode 100644 sagemaker-mlops/src/sagemaker/mlops/feature_store/dataset_builder.py create mode 100644 sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_definition.py create mode 100644 sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_utils.py create mode 100644 sagemaker-mlops/src/sagemaker/mlops/feature_store/ingestion_manager_pandas.py create mode 100644 sagemaker-mlops/src/sagemaker/mlops/feature_store/inputs.py diff --git a/sagemaker-mlops/src/sagemaker/mlops/feature_store/__init__.py b/sagemaker-mlops/src/sagemaker/mlops/feature_store/__init__.py new file mode 100644 index 0000000000..ee8cd7d1a3 --- /dev/null +++ b/sagemaker-mlops/src/sagemaker/mlops/feature_store/__init__.py @@ -0,0 +1,129 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 +"""SageMaker FeatureStore V3 - powered by sagemaker-core.""" + +# Resources from core +from sagemaker_core.main.resources import FeatureGroup, FeatureMetadata +from sagemaker_core.main.resources import FeatureStore + +# Shapes from core (Pydantic - no to_dict() needed) +from sagemaker_core.main.shapes import ( + DataCatalogConfig, + FeatureParameter, + FeatureValue, + Filter, + OfflineStoreConfig, + OnlineStoreConfig, + OnlineStoreSecurityConfig, + S3StorageConfig, + SearchExpression, + ThroughputConfig, + TtlDuration, +) + +# Enums (local - core uses strings) +from sagemaker.mlops.feature_store.inputs import ( + DeletionModeEnum, + ExpirationTimeResponseEnum, + FilterOperatorEnum, + OnlineStoreStorageTypeEnum, + ResourceEnum, + SearchOperatorEnum, + SortOrderEnum, + TableFormatEnum, + TargetStoreEnum, + ThroughputModeEnum, +) + +# Feature Definition helpers (local) +from sagemaker.mlops.feature_store.feature_definition import ( + FeatureDefinition, + FeatureTypeEnum, + CollectionTypeEnum, + FractionalFeatureDefinition, + IntegralFeatureDefinition, + StringFeatureDefinition, + ListCollectionType, + SetCollectionType, + VectorCollectionType, +) + +# Utility functions (local) +from sagemaker.mlops.feature_store.feature_utils import ( + as_hive_ddl, + create_athena_query, + create_dataset, + get_session_from_role, + ingest_dataframe, + load_feature_definitions_from_dataframe, +) + +# Classes (local) +from sagemaker.mlops.feature_store.athena_query import AthenaQuery +from sagemaker.mlops.feature_store.dataset_builder import ( + DatasetBuilder, + FeatureGroupToBeMerged, + JoinComparatorEnum, + JoinTypeEnum, + TableType, +) +from sagemaker.mlops.feature_store.ingestion_manager_pandas import ( + IngestionError, + IngestionManagerPandas, +) + +__all__ = [ + # Resources + "FeatureGroup", + "FeatureMetadata", + "FeatureStore", + # Shapes + "DataCatalogConfig", + "FeatureParameter", + "FeatureValue", + "Filter", + "OfflineStoreConfig", + "OnlineStoreConfig", + "OnlineStoreSecurityConfig", + "S3StorageConfig", + "SearchExpression", + "ThroughputConfig", + "TtlDuration", + # Enums + "DeletionModeEnum", + "ExpirationTimeResponseEnum", + "FilterOperatorEnum", + "OnlineStoreStorageTypeEnum", + "ResourceEnum", + "SearchOperatorEnum", + "SortOrderEnum", + "TableFormatEnum", + "TargetStoreEnum", + "ThroughputModeEnum", + # Feature Definitions + "FeatureDefinition", + "FeatureTypeEnum", + "CollectionTypeEnum", + "FractionalFeatureDefinition", + "IntegralFeatureDefinition", + "StringFeatureDefinition", + "ListCollectionType", + "SetCollectionType", + "VectorCollectionType", + # Utility functions + "as_hive_ddl", + "create_athena_query", + "create_dataset", + "get_session_from_role", + "ingest_dataframe", + "load_feature_definitions_from_dataframe", + # Classes + "AthenaQuery", + "DatasetBuilder", + "FeatureGroupToBeMerged", + "IngestionError", + "IngestionManagerPandas", + "JoinComparatorEnum", + "JoinTypeEnum", + "TableType", +] diff --git a/sagemaker-mlops/src/sagemaker/mlops/feature_store/athena_query.py b/sagemaker-mlops/src/sagemaker/mlops/feature_store/athena_query.py new file mode 100644 index 0000000000..123b3c4305 --- /dev/null +++ b/sagemaker-mlops/src/sagemaker/mlops/feature_store/athena_query.py @@ -0,0 +1,112 @@ +import os +import tempfile +from dataclasses import dataclass, field +from typing import Any, Dict +from urllib.parse import urlparse +import pandas as pd +from pandas import DataFrame + +from sagemaker.mlops.feature_store.feature_utils import ( + start_query_execution, + get_query_execution, + wait_for_athena_query, + download_athena_query_result, +) + +from sagemaker.core.helper.session_helper import Session + +@dataclass +class AthenaQuery: + """Class to manage querying of feature store data with AWS Athena. + + This class instantiates a AthenaQuery object that is used to retrieve data from feature store + via standard SQL queries. + + Attributes: + catalog (str): name of the data catalog. + database (str): name of the database. + table_name (str): name of the table. + sagemaker_session (Session): instance of the Session class to perform boto calls. + """ + + catalog: str + database: str + table_name: str + sagemaker_session: Session + _current_query_execution_id: str = field(default=None, init=False) + _result_bucket: str = field(default=None, init=False) + _result_file_prefix: str = field(default=None, init=False) + + def run( + self, query_string: str, output_location: str, kms_key: str = None, workgroup: str = None + ) -> str: + """Execute a SQL query given a query string, output location and kms key. + + This method executes the SQL query using Athena and outputs the results to output_location + and returns the execution id of the query. + + Args: + query_string: SQL query string. + output_location: S3 URI of the query result. + kms_key: KMS key id. If set, will be used to encrypt the query result file. + workgroup (str): The name of the workgroup in which the query is being started. + + Returns: + Execution id of the query. + """ + response = start_query_execution( + session=self.sagemaker_session, + catalog=self.catalog, + database=self.database, + query_string=query_string, + output_location=output_location, + kms_key=kms_key, + workgroup=workgroup, + ) + + self._current_query_execution_id = response["QueryExecutionId"] + parsed_result = urlparse(output_location, allow_fragments=False) + self._result_bucket = parsed_result.netloc + self._result_file_prefix = parsed_result.path.strip("/") + return self._current_query_execution_id + + def wait(self): + """Wait for the current query to finish.""" + wait_for_athena_query(self.sagemaker_session, self._current_query_execution_id) + + def get_query_execution(self) -> Dict[str, Any]: + """Get execution status of the current query. + + Returns: + Response dict from Athena. + """ + return get_query_execution(self.sagemaker_session, self._current_query_execution_id) + + def as_dataframe(self, **kwargs) -> DataFrame: + """Download the result of the current query and load it into a DataFrame. + + Args: + **kwargs (object): key arguments used for the method pandas.read_csv to be able to + have a better tuning on data. For more info read: + https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html + + Returns: + A pandas DataFrame contains the query result. + """ + state = self.get_query_execution()["QueryExecution"]["Status"]["State"] + if state != "SUCCEEDED": + if state in ("QUEUED", "RUNNING"): + raise RuntimeError(f"Query {self._current_query_execution_id} still executing.") + raise RuntimeError(f"Query {self._current_query_execution_id} failed.") + + output_file = os.path.join(tempfile.gettempdir(), f"{self._current_query_execution_id}.csv") + download_athena_query_result( + session=self.sagemaker_session, + bucket=self._result_bucket, + prefix=self._result_file_prefix, + query_execution_id=self._current_query_execution_id, + filename=output_file, + ) + kwargs.pop("delimiter", None) + return pd.read_csv(output_file, delimiter=",", **kwargs) + diff --git a/sagemaker-mlops/src/sagemaker/mlops/feature_store/dataset_builder.py b/sagemaker-mlops/src/sagemaker/mlops/feature_store/dataset_builder.py new file mode 100644 index 0000000000..f5450663a6 --- /dev/null +++ b/sagemaker-mlops/src/sagemaker/mlops/feature_store/dataset_builder.py @@ -0,0 +1,725 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 +"""Dataset Builder for FeatureStore.""" +from dataclasses import dataclass, field +from enum import Enum +from typing import Any, Dict, List, Union +import datetime + +import pandas as pd + +from sagemaker.core.helper.session_helper import Session +from sagemaker.mlops.feature_store import FeatureGroup +from sagemaker.mlops.feature_store.feature_definition import FeatureDefinition, FeatureTypeEnum +from sagemaker.mlops.feature_store.feature_utils import ( + upload_dataframe_to_s3, + download_csv_from_s3, + run_athena_query, +) + +_DEFAULT_CATALOG = "AwsDataCatalog" +_DEFAULT_DATABASE = "sagemaker_featurestore" + +_DTYPE_TO_FEATURE_TYPE = { + "object": "String", "string": "String", + "int64": "Integral", "int32": "Integral", + "float64": "Fractional", "float32": "Fractional", +} + +_DTYPE_TO_ATHENA_TYPE = { + "object": "STRING", "int64": "INT", "float64": "DOUBLE", + "bool": "BOOLEAN", "datetime64[ns]": "TIMESTAMP", +} + + +class TableType(Enum): + FEATURE_GROUP = "FeatureGroup" + DATA_FRAME = "DataFrame" + + +class JoinTypeEnum(Enum): + INNER_JOIN = "JOIN" + LEFT_JOIN = "LEFT JOIN" + RIGHT_JOIN = "RIGHT JOIN" + FULL_JOIN = "FULL JOIN" + CROSS_JOIN = "CROSS JOIN" + + +class JoinComparatorEnum(Enum): + EQUALS = "=" + GREATER_THAN = ">" + GREATER_THAN_OR_EQUAL_TO = ">=" + LESS_THAN = "<" + LESS_THAN_OR_EQUAL_TO = "<=" + NOT_EQUAL_TO = "<>" + + +@dataclass +class FeatureGroupToBeMerged: + """FeatureGroup metadata which will be used for SQL join. + + This class instantiates a FeatureGroupToBeMerged object that comprises a list of feature names, + a list of feature names which will be included in SQL query, a database, an Athena table name, + a feature name of record identifier, a feature name of event time identifier and a feature name + of base which is the target join key. + + Attributes: + features (List[str]): A list of strings representing feature names of this FeatureGroup. + included_feature_names (List[str]): A list of strings representing features to be + included in the SQL join. + projected_feature_names (List[str]): A list of strings representing features to be + included for final projection in output. + catalog (str): A string representing the catalog. + database (str): A string representing the database. + table_name (str): A string representing the Athena table name of this FeatureGroup. + record_identifier_feature_name (str): A string representing the record identifier feature. + event_time_identifier_feature (FeatureDefinition): A FeatureDefinition representing the + event time identifier feature. + target_feature_name_in_base (str): A string representing the feature name in base which will + be used as target join key (default: None). + table_type (TableType): A TableType representing the type of table if it is Feature Group or + Panda Data Frame (default: None). + feature_name_in_target (str): A string representing the feature name in the target feature + group that will be compared to the target feature in the base feature group. + If None is provided, the record identifier feature will be used in the + SQL join. (default: None). + join_comparator (JoinComparatorEnum): A JoinComparatorEnum representing the comparator + used when joining the target feature in the base feature group and the feature + in the target feature group. (default: JoinComparatorEnum.EQUALS). + join_type (JoinTypeEnum): A JoinTypeEnum representing the type of join between + the base and target feature groups. (default: JoinTypeEnum.INNER_JOIN). + """ + features: List[str] + included_feature_names: List[str] + projected_feature_names: List[str] + catalog: str + database: str + table_name: str + record_identifier_feature_name: str + event_time_identifier_feature: FeatureDefinition + target_feature_name_in_base: str = None + table_type: TableType = None + feature_name_in_target: str = None + join_comparator: JoinComparatorEnum = JoinComparatorEnum.EQUALS + join_type: JoinTypeEnum = JoinTypeEnum.INNER_JOIN + + +def construct_feature_group_to_be_merged( + target_feature_group: FeatureGroup, + included_feature_names: List[str], + target_feature_name_in_base: str = None, + feature_name_in_target: str = None, + join_comparator: JoinComparatorEnum = JoinComparatorEnum.EQUALS, + join_type: JoinTypeEnum = JoinTypeEnum.INNER_JOIN, +) -> FeatureGroupToBeMerged: + """Construct a FeatureGroupToBeMerged object by provided parameters. + + Args: + target_feature_group (FeatureGroup): A FeatureGroup object. + included_feature_names (List[str]): A list of strings representing features to be + included in the output. + target_feature_name_in_base (str): A string representing the feature name in base which + will be used as target join key (default: None). + feature_name_in_target (str): A string representing the feature name in the target feature + group that will be compared to the target feature in the base feature group. + If None is provided, the record identifier feature will be used in the + SQL join. (default: None). + join_comparator (JoinComparatorEnum): A JoinComparatorEnum representing the comparator + used when joining the target feature in the base feature group and the feature + in the target feature group. (default: JoinComparatorEnum.EQUALS). + join_type (JoinTypeEnum): A JoinTypeEnum representing the type of join between + the base and target feature groups. (default: JoinTypeEnum.INNER_JOIN). + + Returns: + A FeatureGroupToBeMerged object. + + Raises: + RuntimeError: No metastore is configured with the FeatureGroup. + ValueError: Invalid feature name(s) in included_feature_names. + """ + fg = FeatureGroup.get(feature_group_name=target_feature_group.feature_group_name) + + if not fg.offline_store_config or not fg.offline_store_config.data_catalog_config: + raise RuntimeError(f"No metastore configured for FeatureGroup {fg.feature_group_name}.") + + catalog_config = fg.offline_store_config.data_catalog_config + disable_glue = catalog_config.disable_glue_table_creation or False + + features = [fd.feature_name for fd in fg.feature_definitions] + record_id = fg.record_identifier_feature_name + event_time_name = fg.event_time_feature_name + event_time_type = next( + (fd.feature_type for fd in fg.feature_definitions if fd.feature_name == event_time_name), + None + ) + + if feature_name_in_target and feature_name_in_target not in features: + raise ValueError(f"Feature {feature_name_in_target} not found in {fg.feature_group_name}") + + for feat in included_feature_names or []: + if feat not in features: + raise ValueError(f"Feature {feat} not found in {fg.feature_group_name}") + + if not included_feature_names: + included_feature_names = features.copy() + projected_feature_names = features.copy() + else: + projected_feature_names = included_feature_names.copy() + if record_id not in included_feature_names: + included_feature_names.append(record_id) + if event_time_name not in included_feature_names: + included_feature_names.append(event_time_name) + + return FeatureGroupToBeMerged( + features=features, + included_feature_names=included_feature_names, + projected_feature_names=projected_feature_names, + catalog=catalog_config.catalog if disable_glue else _DEFAULT_CATALOG, + database=catalog_config.database, + table_name=catalog_config.table_name, + record_identifier_feature_name=record_id, + event_time_identifier_feature=FeatureDefinition(event_time_name, FeatureTypeEnum(event_time_type)), + target_feature_name_in_base=target_feature_name_in_base, + table_type=TableType.FEATURE_GROUP, + feature_name_in_target=feature_name_in_target, + join_comparator=join_comparator, + join_type=join_type, + ) + + +@dataclass +class DatasetBuilder: + """DatasetBuilder definition. + + This class instantiates a DatasetBuilder object that comprises a base, a list of feature names, + an output path and a KMS key ID. + + Attributes: + _sagemaker_session (Session): Session instance to perform boto calls. + _base (Union[FeatureGroup, DataFrame]): A base which can be either a FeatureGroup or a + pandas.DataFrame and will be used to merge other FeatureGroups and generate a Dataset. + _output_path (str): An S3 URI which stores the output .csv file. + _record_identifier_feature_name (str): A string representing the record identifier feature + if base is a DataFrame (default: None). + _event_time_identifier_feature_name (str): A string representing the event time identifier + feature if base is a DataFrame (default: None). + _included_feature_names (List[str]): A list of strings representing features to be + included in the output. If not set, all features will be included in the output. + (default: None). + _kms_key_id (str): A KMS key id. If set, will be used to encrypt the result file + (default: None). + _point_in_time_accurate_join (bool): A boolean representing if point-in-time join + is applied to the resulting dataframe when calling "to_dataframe". + When set to True, users can retrieve data using "row-level time travel" + according to the event times provided to the DatasetBuilder. This requires that the + entity dataframe with event times is submitted as the base in the constructor + (default: False). + _include_duplicated_records (bool): A boolean representing whether the resulting dataframe + when calling "to_dataframe" should include duplicated records (default: False). + _include_deleted_records (bool): A boolean representing whether the resulting + dataframe when calling "to_dataframe" should include deleted records (default: False). + _number_of_recent_records (int): An integer representing how many records will be + returned for each record identifier (default: 1). + _number_of_records (int): An integer representing the number of records that should be + returned in the resulting dataframe when calling "to_dataframe" (default: None). + _write_time_ending_timestamp (datetime.datetime): A datetime that represents the latest + write time for a record to be included in the resulting dataset. Records with a + newer write time will be omitted from the resulting dataset. (default: None). + _event_time_starting_timestamp (datetime.datetime): A datetime that represents the earliest + event time for a record to be included in the resulting dataset. Records + with an older event time will be omitted from the resulting dataset. (default: None). + _event_time_ending_timestamp (datetime.datetime): A datetime that represents the latest + event time for a record to be included in the resulting dataset. Records + with a newer event time will be omitted from the resulting dataset. (default: None). + _feature_groups_to_be_merged (List[FeatureGroupToBeMerged]): A list of + FeatureGroupToBeMerged which will be joined to base (default: []). + _event_time_identifier_feature_type (FeatureTypeEnum): A FeatureTypeEnum representing the + type of event time identifier feature (default: None). + """ + + _sagemaker_session: Session + _base: Union[FeatureGroup, pd.DataFrame] + _output_path: str + _record_identifier_feature_name: str = None + _event_time_identifier_feature_name: str = None + _included_feature_names: List[str] = None + _kms_key_id: str = None + _event_time_identifier_feature_type: FeatureTypeEnum = None + + _point_in_time_accurate_join: bool = field(default=False, init=False) + _include_duplicated_records: bool = field(default=False, init=False) + _include_deleted_records: bool = field(default=False, init=False) + _number_of_recent_records: int = field(default=None, init=False) + _number_of_records: int = field(default=None, init=False) + _write_time_ending_timestamp: datetime.datetime = field(default=None, init=False) + _event_time_starting_timestamp: datetime.datetime = field(default=None, init=False) + _event_time_ending_timestamp: datetime.datetime = field(default=None, init=False) + _feature_groups_to_be_merged: List[FeatureGroupToBeMerged] = field(default_factory=list, init=False) + + def with_feature_group( + self, + feature_group: FeatureGroup, + target_feature_name_in_base: str = None, + included_feature_names: List[str] = None, + feature_name_in_target: str = None, + join_comparator: JoinComparatorEnum = JoinComparatorEnum.EQUALS, + join_type: JoinTypeEnum = JoinTypeEnum.INNER_JOIN, + ) -> "DatasetBuilder": + """Join FeatureGroup with base. + + Args: + feature_group (FeatureGroup): A target FeatureGroup which will be joined to base. + target_feature_name_in_base (str): A string representing the feature name in base which + will be used as a join key (default: None). + included_feature_names (List[str]): A list of strings representing features to be + included in the output (default: None). + feature_name_in_target (str): A string representing the feature name in the target + feature group that will be compared to the target feature in the base feature group. + If None is provided, the record identifier feature will be used in the + SQL join. (default: None). + join_comparator (JoinComparatorEnum): A JoinComparatorEnum representing the comparator + used when joining the target feature in the base feature group and the feature + in the target feature group. (default: JoinComparatorEnum.EQUALS). + join_type (JoinTypeEnum): A JoinTypeEnum representing the type of join between + the base and target feature groups. (default: JoinTypeEnum.INNER_JOIN). + + Returns: + This DatasetBuilder object. + """ + self._feature_groups_to_be_merged.append( + construct_feature_group_to_be_merged( + feature_group, included_feature_names, target_feature_name_in_base, + feature_name_in_target, join_comparator, join_type, + ) + ) + return self + + def point_in_time_accurate_join(self) -> "DatasetBuilder": + """Enable point-in-time accurate join. + + Returns: + This DatasetBuilder object. + """ + self._point_in_time_accurate_join = True + return self + + def include_duplicated_records(self) -> "DatasetBuilder": + """Include duplicated records in dataset. + + Returns: + This DatasetBuilder object. + """ + self._include_duplicated_records = True + return self + + def include_deleted_records(self) -> "DatasetBuilder": + """Include deleted records in dataset. + + Returns: + This DatasetBuilder object. + """ + self._include_deleted_records = True + return self + + def with_number_of_recent_records_by_record_identifier(self, n: int) -> "DatasetBuilder": + """Set number_of_recent_records field with provided input. + + Args: + n (int): An int that how many recent records will be returned for + each record identifier. + + Returns: + This DatasetBuilder object. + """ + self._number_of_recent_records = n + return self + + def with_number_of_records_from_query_results(self, n: int) -> "DatasetBuilder": + """Set number_of_records field with provided input. + + Args: + n (int): An int that how many records will be returned. + + Returns: + This DatasetBuilder object. + """ + self._number_of_records = n + return self + + def as_of(self, timestamp: datetime.datetime) -> "DatasetBuilder": + """Set write_time_ending_timestamp field with provided input. + + Args: + timestamp (datetime.datetime): A datetime that all records' write time in dataset will + be before it. + + Returns: + This DatasetBuilder object. + """ + self._write_time_ending_timestamp = timestamp + return self + + def with_event_time_range( + self, + starting_timestamp: datetime.datetime = None, + ending_timestamp: datetime.datetime = None, + ) -> "DatasetBuilder": + """Set event_time_starting_timestamp and event_time_ending_timestamp with provided inputs. + + Args: + starting_timestamp (datetime.datetime): A datetime that all records' event time in + dataset will be after it (default: None). + ending_timestamp (datetime.datetime): A datetime that all records' event time in dataset + will be before it (default: None). + + Returns: + This DatasetBuilder object. + """ + self._event_time_starting_timestamp = starting_timestamp + self._event_time_ending_timestamp = ending_timestamp + return self + + def to_csv_file(self) -> tuple[str, str]: + """Get query string and result in .csv format file. + + Returns: + The S3 path of the .csv file. + The query string executed. + """ + if isinstance(self._base, pd.DataFrame): + return self._to_csv_from_dataframe() + if isinstance(self._base, FeatureGroup): + return self._to_csv_from_feature_group() + raise ValueError("Base must be either a FeatureGroup or a DataFrame.") + + def to_dataframe(self) -> tuple[pd.DataFrame, str]: + """Get query string and result in pandas.DataFrame. + + Returns: + The pandas.DataFrame object. + The query string executed. + """ + csv_file, query_string = self.to_csv_file() + df = download_csv_from_s3(csv_file, self._sagemaker_session, self._kms_key_id) + if "row_recent" in df.columns: + df = df.drop("row_recent", axis="columns") + return df, query_string + + + def _to_csv_from_dataframe(self) -> tuple[str, str]: + s3_folder, temp_table_name = upload_dataframe_to_s3( + self._base, self._output_path, self._sagemaker_session, self._kms_key_id + ) + self._create_temp_table(temp_table_name, s3_folder) + + base_features = list(self._base.columns) + event_time_dtype = str(self._base[self._event_time_identifier_feature_name].dtypes) + self._event_time_identifier_feature_type = FeatureTypeEnum( + _DTYPE_TO_FEATURE_TYPE.get(event_time_dtype, "String") + ) + + included = self._included_feature_names or base_features + fg_to_merge = FeatureGroupToBeMerged( + features=base_features, + included_feature_names=included, + projected_feature_names=included, + catalog=_DEFAULT_CATALOG, + database=_DEFAULT_DATABASE, + table_name=temp_table_name, + record_identifier_feature_name=self._record_identifier_feature_name, + event_time_identifier_feature=FeatureDefinition( + self._event_time_identifier_feature_name, + self._event_time_identifier_feature_type, + ), + table_type=TableType.DATA_FRAME, + ) + + query_string = self._construct_query_string(fg_to_merge) + result = self._run_query(query_string, _DEFAULT_CATALOG, _DEFAULT_DATABASE) + return self._extract_result(result) + + def _to_csv_from_feature_group(self) -> tuple[str, str]: + base_fg = construct_feature_group_to_be_merged(self._base, self._included_feature_names) + self._record_identifier_feature_name = base_fg.record_identifier_feature_name + self._event_time_identifier_feature_name = base_fg.event_time_identifier_feature.feature_name + self._event_time_identifier_feature_type = base_fg.event_time_identifier_feature.feature_type + + query_string = self._construct_query_string(base_fg) + result = self._run_query(query_string, base_fg.catalog, base_fg.database) + return self._extract_result(result) + + def _extract_result(self, query_result: dict) -> tuple[str, str]: + execution = query_result.get("QueryExecution", {}) + return ( + execution.get("ResultConfiguration", {}).get("OutputLocation"), + execution.get("Query"), + ) + + def _run_query(self, query_string: str, catalog: str, database: str) -> Dict[str, Any]: + return run_athena_query( + session=self._sagemaker_session, + catalog=catalog, + database=database, + query_string=query_string, + output_location=self._output_path, + kms_key=self._kms_key_id, + ) + + def _create_temp_table(self, temp_table_name: str, s3_folder: str): + columns = ", ".join( + f"{col} {_DTYPE_TO_ATHENA_TYPE.get(str(self._base[col].dtypes), 'STRING')}" + for col in self._base.columns + ) + serde = '"separatorChar" = ",", "quoteChar" = "`", "escapeChar" = "\\\\"' + query = ( + f"CREATE EXTERNAL TABLE {temp_table_name} ({columns}) " + f"ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde' " + f"WITH SERDEPROPERTIES ({serde}) LOCATION '{s3_folder}';" + ) + self._run_query(query, _DEFAULT_CATALOG, _DEFAULT_DATABASE) + + + def _construct_query_string(self, base: FeatureGroupToBeMerged) -> str: + base_query = self._construct_table_query(base, "base") + query = f"WITH fg_base AS ({base_query})" + + for i, fg in enumerate(self._feature_groups_to_be_merged): + fg_query = self._construct_table_query(fg, str(i)) + query += f",\nfg_{i} AS ({fg_query})" + + selected = ", ".join(f"fg_base.{f}" for f in base.projected_feature_names) + selected_final = ", ".join(base.projected_feature_names) + + for i, fg in enumerate(self._feature_groups_to_be_merged): + selected += ", " + ", ".join( + f'fg_{i}."{f}" as "{f}.{i+1}"' for f in fg.projected_feature_names + ) + selected_final += ", " + ", ".join( + f'"{f}.{i+1}"' for f in fg.projected_feature_names + ) + + query += ( + f"\nSELECT {selected_final}\nFROM (\n" + f"SELECT {selected}, row_number() OVER (\n" + f'PARTITION BY fg_base."{base.record_identifier_feature_name}"\n' + f'ORDER BY fg_base."{base.event_time_identifier_feature.feature_name}" DESC' + ) + + join_strings = [] + for i, fg in enumerate(self._feature_groups_to_be_merged): + if not fg.target_feature_name_in_base: + fg.target_feature_name_in_base = self._record_identifier_feature_name + elif fg.target_feature_name_in_base not in base.features: + raise ValueError(f"Feature {fg.target_feature_name_in_base} not found in base") + query += f', fg_{i}."{fg.event_time_identifier_feature.feature_name}" DESC' + join_strings.append(self._construct_join_condition(fg, str(i))) + + recent_where = "" + if self._number_of_recent_records is not None and self._number_of_recent_records >= 0: + recent_where = f"WHERE row_recent <= {self._number_of_recent_records}" + + query += f"\n) AS row_recent\nFROM fg_base{''.join(join_strings)}\n)\n{recent_where}" + + if self._number_of_records is not None and self._number_of_records >= 0: + query += f"\nLIMIT {self._number_of_records}" + + return query + + def _construct_table_query(self, fg: FeatureGroupToBeMerged, suffix: str) -> str: + included = ", ".join(f'table_{suffix}."{f}"' for f in fg.included_feature_names) + included_with_write = included + if fg.table_type is TableType.FEATURE_GROUP: + included_with_write += f', table_{suffix}."write_time"' + + record_id = fg.record_identifier_feature_name + event_time = fg.event_time_identifier_feature.feature_name + + if self._include_duplicated_records and self._include_deleted_records: + return ( + f"SELECT {included}\n" + f'FROM "{fg.database}"."{fg.table_name}" table_{suffix}\n' + + self._construct_where_query_string(suffix, fg.event_time_identifier_feature, ["NOT is_deleted"]) + ) + + if fg.table_type is TableType.FEATURE_GROUP and self._include_deleted_records: + rank = f'ORDER BY origin_{suffix}."api_invocation_time" DESC, origin_{suffix}."write_time" DESC\n' + return ( + f"SELECT {included}\nFROM (\n" + f"SELECT *, row_number() OVER (\n" + f'PARTITION BY origin_{suffix}."{record_id}", origin_{suffix}."{event_time}"\n' + f"{rank}) AS row_{suffix}\n" + f'FROM "{fg.database}"."{fg.table_name}" origin_{suffix}\n' + f"WHERE NOT is_deleted) AS table_{suffix}\n" + + self._construct_where_query_string(suffix, fg.event_time_identifier_feature, [f"row_{suffix} = 1"]) + ) + + if fg.table_type is TableType.FEATURE_GROUP: + dedup = self._construct_dedup_query(fg, suffix) + deleted = self._construct_deleted_query(fg, suffix) + rank_cond = ( + f'OR (table_{suffix}."{event_time}" = deleted_{suffix}."{event_time}" ' + f'AND table_{suffix}."api_invocation_time" > deleted_{suffix}."api_invocation_time")\n' + f'OR (table_{suffix}."{event_time}" = deleted_{suffix}."{event_time}" ' + f'AND table_{suffix}."api_invocation_time" = deleted_{suffix}."api_invocation_time" ' + f'AND table_{suffix}."write_time" > deleted_{suffix}."write_time")\n' + ) + + if self._include_duplicated_records: + return ( + f"WITH {deleted}\n" + f"SELECT {included}\nFROM (\n" + f"SELECT {included_with_write}\n" + f'FROM "{fg.database}"."{fg.table_name}" table_{suffix}\n' + f"LEFT JOIN deleted_{suffix} ON table_{suffix}.\"{record_id}\" = deleted_{suffix}.\"{record_id}\"\n" + f'WHERE deleted_{suffix}."{record_id}" IS NULL\n' + f"UNION ALL\n" + f"SELECT {included_with_write}\nFROM deleted_{suffix}\n" + f'JOIN "{fg.database}"."{fg.table_name}" table_{suffix}\n' + f'ON table_{suffix}."{record_id}" = deleted_{suffix}."{record_id}"\n' + f'AND (table_{suffix}."{event_time}" > deleted_{suffix}."{event_time}"\n{rank_cond})\n' + f") AS table_{suffix}\n" + + self._construct_where_query_string(suffix, fg.event_time_identifier_feature, []) + ) + + return ( + f"WITH {dedup},\n{deleted}\n" + f"SELECT {included}\nFROM (\n" + f"SELECT {included_with_write}\nFROM table_{suffix}\n" + f"LEFT JOIN deleted_{suffix} ON table_{suffix}.\"{record_id}\" = deleted_{suffix}.\"{record_id}\"\n" + f'WHERE deleted_{suffix}."{record_id}" IS NULL\n' + f"UNION ALL\n" + f"SELECT {included_with_write}\nFROM deleted_{suffix}\n" + f"JOIN table_{suffix} ON table_{suffix}.\"{record_id}\" = deleted_{suffix}.\"{record_id}\"\n" + f'AND (table_{suffix}."{event_time}" > deleted_{suffix}."{event_time}"\n{rank_cond})\n' + f") AS table_{suffix}\n" + + self._construct_where_query_string(suffix, fg.event_time_identifier_feature, []) + ) + + dedup = self._construct_dedup_query(fg, suffix) + return ( + f"WITH {dedup}\n" + f"SELECT {included}\nFROM (\n" + f"SELECT {included_with_write}\nFROM table_{suffix}\n" + f") AS table_{suffix}\n" + + self._construct_where_query_string(suffix, fg.event_time_identifier_feature, []) + ) + + def _construct_dedup_query(self, fg: FeatureGroupToBeMerged, suffix: str) -> str: + record_id = fg.record_identifier_feature_name + event_time = fg.event_time_identifier_feature.feature_name + rank = "" + is_fg = fg.table_type is TableType.FEATURE_GROUP + + if is_fg: + rank = f'ORDER BY origin_{suffix}."api_invocation_time" DESC, origin_{suffix}."write_time" DESC\n' + + where_conds = [] + if is_fg and self._write_time_ending_timestamp: + where_conds.append(self._construct_write_time_condition(f"origin_{suffix}")) + where_conds.extend(self._construct_event_time_conditions(f"origin_{suffix}", fg.event_time_identifier_feature)) + where_str = f"WHERE {' AND '.join(where_conds)}\n" if where_conds else "" + + dedup_where = f"WHERE dedup_row_{suffix} = 1\n" if is_fg else "" + + return ( + f"table_{suffix} AS (\n" + f"SELECT *\nFROM (\n" + f"SELECT *, row_number() OVER (\n" + f'PARTITION BY origin_{suffix}."{record_id}", origin_{suffix}."{event_time}"\n' + f"{rank}) AS dedup_row_{suffix}\n" + f'FROM "{fg.database}"."{fg.table_name}" origin_{suffix}\n' + f"{where_str})\n{dedup_where})" + ) + + def _construct_deleted_query(self, fg: FeatureGroupToBeMerged, suffix: str) -> str: + record_id = fg.record_identifier_feature_name + event_time = fg.event_time_identifier_feature.feature_name + rank = f'ORDER BY origin_{suffix}."{event_time}" DESC' + + if fg.table_type is TableType.FEATURE_GROUP: + rank += f', origin_{suffix}."api_invocation_time" DESC, origin_{suffix}."write_time" DESC\n' + + write_cond = "" + if fg.table_type is TableType.FEATURE_GROUP and self._write_time_ending_timestamp: + write_cond = f" AND {self._construct_write_time_condition(f'origin_{suffix}')}\n" + + event_conds = "" + if self._event_time_starting_timestamp and self._event_time_ending_timestamp: + conds = self._construct_event_time_conditions(f"origin_{suffix}", fg.event_time_identifier_feature) + event_conds = "".join(f"AND {c}\n" for c in conds) + + return ( + f"deleted_{suffix} AS (\n" + f"SELECT *\nFROM (\n" + f"SELECT *, row_number() OVER (\n" + f'PARTITION BY origin_{suffix}."{record_id}"\n' + f"{rank}) AS deleted_row_{suffix}\n" + f'FROM "{fg.database}"."{fg.table_name}" origin_{suffix}\n' + f"WHERE is_deleted{write_cond}{event_conds})\n" + f"WHERE deleted_row_{suffix} = 1\n)" + ) + + def _construct_where_query_string( + self, suffix: str, event_time_feature: FeatureDefinition, conditions: List[str] + ) -> str: + self._validate_options() + + if isinstance(self._base, FeatureGroup) and self._write_time_ending_timestamp: + conditions.append(self._construct_write_time_condition(f"table_{suffix}")) + + conditions.extend(self._construct_event_time_conditions(f"table_{suffix}", event_time_feature)) + return f"WHERE {' AND '.join(conditions)}" if conditions else "" + + def _validate_options(self): + is_df_base = isinstance(self._base, pd.DataFrame) + no_joins = len(self._feature_groups_to_be_merged) == 0 + + if self._number_of_recent_records is not None and self._number_of_recent_records < 0: + raise ValueError("number_of_recent_records must be non-negative.") + if self._number_of_records is not None and self._number_of_records < 0: + raise ValueError("number_of_records must be non-negative.") + if is_df_base and no_joins: + if self._include_deleted_records: + raise ValueError("include_deleted_records() only works for FeatureGroup if no join.") + if self._include_duplicated_records: + raise ValueError("include_duplicated_records() only works for FeatureGroup if no join.") + if self._write_time_ending_timestamp: + raise ValueError("as_of() only works for FeatureGroup if no join.") + if self._point_in_time_accurate_join and no_joins: + raise ValueError("point_in_time_accurate_join() requires at least one join.") + + def _construct_event_time_conditions(self, table: str, event_time_feature: FeatureDefinition) -> List[str]: + cast_fn = "from_iso8601_timestamp" if event_time_feature.feature_type == FeatureTypeEnum.STRING else "from_unixtime" + conditions = [] + if self._event_time_starting_timestamp: + conditions.append( + f'{cast_fn}({table}."{event_time_feature.feature_name}") >= ' + f"from_unixtime({self._event_time_starting_timestamp.timestamp()})" + ) + if self._event_time_ending_timestamp: + conditions.append( + f'{cast_fn}({table}."{event_time_feature.feature_name}") <= ' + f"from_unixtime({self._event_time_ending_timestamp.timestamp()})" + ) + return conditions + + def _construct_write_time_condition(self, table: str) -> str: + ts = self._write_time_ending_timestamp.replace(microsecond=0) + return f'{table}."write_time" <= to_timestamp(\'{ts}\', \'yyyy-mm-dd hh24:mi:ss\')' + + def _construct_join_condition(self, fg: FeatureGroupToBeMerged, suffix: str) -> str: + target_feature = fg.feature_name_in_target or fg.record_identifier_feature_name + join = ( + f"\n{fg.join_type.value} fg_{suffix}\n" + f'ON fg_base."{fg.target_feature_name_in_base}" {fg.join_comparator.value} fg_{suffix}."{target_feature}"' + ) + + if self._point_in_time_accurate_join: + base_cast = "from_iso8601_timestamp" if self._event_time_identifier_feature_type == FeatureTypeEnum.STRING else "from_unixtime" + fg_cast = "from_iso8601_timestamp" if fg.event_time_identifier_feature.feature_type == FeatureTypeEnum.STRING else "from_unixtime" + join += ( + f'\nAND {base_cast}(fg_base."{self._event_time_identifier_feature_name}") >= ' + f'{fg_cast}(fg_{suffix}."{fg.event_time_identifier_feature.feature_name}")' + ) + + return join diff --git a/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_definition.py b/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_definition.py new file mode 100644 index 0000000000..32408e5585 --- /dev/null +++ b/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_definition.py @@ -0,0 +1,107 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. +"""Feature Definitions for FeatureStore.""" +from __future__ import absolute_import + +from enum import Enum +from typing import Optional, Union + +from sagemaker.core.shapes import ( + FeatureDefinition, + CollectionConfig, + VectorConfig, +) + +class FeatureTypeEnum(Enum): + """Feature data types: Fractional, Integral, or String.""" + + FRACTIONAL = "Fractional" + INTEGRAL = "Integral" + STRING = "String" + +class CollectionTypeEnum(Enum): + """Collection types: List, Set, or Vector.""" + + LIST = "List" + SET = "Set" + VECTOR = "Vector" + +class ListCollectionType: + """List collection type.""" + + collection_type = CollectionTypeEnum.LIST.value + collection_config = None + +class SetCollectionType: + """Set collection type.""" + + collection_type = CollectionTypeEnum.SET.value + collection_config = None + +class VectorCollectionType: + """Vector collection type with dimension.""" + + collection_type = CollectionTypeEnum.VECTOR.value + + def __init__(self, dimension: int): + self.collection_config = CollectionConfig( + vector_config=VectorConfig(dimension=dimension) + ) + +CollectionType = Union[ListCollectionType, SetCollectionType, VectorCollectionType] + +def _create_feature_definition( + feature_name: str, + feature_type: FeatureTypeEnum, + collection_type: Optional[CollectionType] = None, +) -> FeatureDefinition: + """Internal helper to create FeatureDefinition from collection type.""" + return FeatureDefinition( + feature_name=feature_name, + feature_type=feature_type.value, + collection_type=collection_type.collection_type if collection_type else None, + collection_config=collection_type.collection_config if collection_type else None, + ) + +def FractionalFeatureDefinition( + feature_name: str, + collection_type: Optional[CollectionType] = None, +) -> FeatureDefinition: + """Create a feature definition with Fractional type.""" + return _create_feature_definition(feature_name, FeatureTypeEnum.FRACTIONAL, collection_type) + +def IntegralFeatureDefinition( + feature_name: str, + collection_type: Optional[CollectionType] = None, +) -> FeatureDefinition: + """Create a feature definition with Integral type.""" + return _create_feature_definition(feature_name, FeatureTypeEnum.INTEGRAL, collection_type) + +def StringFeatureDefinition( + feature_name: str, + collection_type: Optional[CollectionType] = None, +) -> FeatureDefinition: + """Create a feature definition with String type.""" + return _create_feature_definition(feature_name, FeatureTypeEnum.STRING, collection_type) + +__all__ = [ + "FeatureDefinition", + "FeatureTypeEnum", + "CollectionTypeEnum", + "ListCollectionType", + "SetCollectionType", + "VectorCollectionType", + "FractionalFeatureDefinition", + "IntegralFeatureDefinition", + "StringFeatureDefinition", +] diff --git a/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_utils.py b/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_utils.py new file mode 100644 index 0000000000..f7f6523b8d --- /dev/null +++ b/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_utils.py @@ -0,0 +1,488 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 +"""Utilities for working with FeatureGroups and FeatureStores.""" +import logging +import os +import time +from typing import Any, Dict, Sequence, Union + +import boto3 +import pandas as pd +from pandas import DataFrame, Series + +from sagemaker.mlops.feature_store import FeatureGroup as CoreFeatureGroup, FeatureGroup +from sagemaker.core.helper.session_helper import Session +from sagemaker.core.s3.client import S3Uploader, S3Downloader +from sagemaker.mlops.feature_store.dataset_builder import DatasetBuilder +from sagemaker.mlops.feature_store.feature_definition import ( + FeatureDefinition, + FractionalFeatureDefinition, + IntegralFeatureDefinition, + ListCollectionType, + StringFeatureDefinition, +) +from sagemaker.mlops.feature_store.ingestion_manager_pandas import IngestionManagerPandas + +from sagemaker import utils + + +logger = logging.getLogger(__name__) + +# --- Constants --- + +_FEATURE_TYPE_TO_DDL_DATA_TYPE_MAP = { + "Integral": "INT", + "Fractional": "FLOAT", + "String": "STRING", +} + +_DTYPE_TO_FEATURE_TYPE_MAP = { + "object": "String", + "string": "String", + "int64": "Integral", + "float64": "Fractional", +} + +_INTEGER_TYPES = {"int_", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64"} +_FLOAT_TYPES = {"float_", "float16", "float32", "float64"} + + +def _get_athena_client(session: Session): + """Get Athena client from session.""" + return session.boto_session.client("athena", region_name=session.boto_region_name) + + +def _get_s3_client(session: Session): + """Get S3 client from session.""" + return session.boto_session.client("s3", region_name=session.boto_region_name) + + +def start_query_execution( + session: Session, + catalog: str, + database: str, + query_string: str, + output_location: str, + kms_key: str = None, + workgroup: str = None, +) -> Dict[str, str]: + """Start Athena query execution. + + Args: + session: Session instance for boto calls. + catalog: Name of the data catalog. + database: Name of the database. + query_string: SQL query string. + output_location: S3 URI for query results. + kms_key: KMS key for encryption (default: None). + workgroup: Athena workgroup name (default: None). + + Returns: + Response dict with QueryExecutionId. + """ + kwargs = { + "QueryString": query_string, + "QueryExecutionContext": {"Catalog": catalog, "Database": database}, + "ResultConfiguration": {"OutputLocation": output_location}, + } + if kms_key: + kwargs["ResultConfiguration"]["EncryptionConfiguration"] = { + "EncryptionOption": "SSE_KMS", + "KmsKey": kms_key, + } + if workgroup: + kwargs["WorkGroup"] = workgroup + return _get_athena_client(session).start_query_execution(**kwargs) + + +def get_query_execution(session: Session, query_execution_id: str) -> Dict[str, Any]: + """Get execution status of an Athena query. + + Args: + session: Session instance for boto calls. + query_execution_id: The query execution ID. + + Returns: + Response dict from Athena. + """ + return _get_athena_client(session).get_query_execution(QueryExecutionId=query_execution_id) + + +def wait_for_athena_query(session: Session, query_execution_id: str, poll: int = 5): + """Wait for Athena query to finish. + + Args: + session: Session instance for boto calls. + query_execution_id: The query execution ID. + poll: Polling interval in seconds (default: 5). + """ + while True: + state = get_query_execution(session, query_execution_id)["QueryExecution"]["Status"]["State"] + if state in ("SUCCEEDED", "FAILED"): + logger.info("Query %s %s.", query_execution_id, state.lower()) + break + logger.info("Query %s is being executed.", query_execution_id) + time.sleep(poll) + + +def run_athena_query( + session: Session, + catalog: str, + database: str, + query_string: str, + output_location: str, + kms_key: str = None, +) -> Dict[str, Any]: + """Execute Athena query, wait for completion, and return result. + + Args: + session: Session instance for boto calls. + catalog: Name of the data catalog. + database: Name of the database. + query_string: SQL query string. + output_location: S3 URI for query results. + kms_key: KMS key for encryption (default: None). + + Returns: + Query execution result dict. + + Raises: + RuntimeError: If query fails. + """ + response = start_query_execution( + session=session, + catalog=catalog, + database=database, + query_string=query_string, + output_location=output_location, + kms_key=kms_key, + ) + query_id = response["QueryExecutionId"] + wait_for_athena_query(session, query_id) + + result = get_query_execution(session, query_id) + if result["QueryExecution"]["Status"]["State"] != "SUCCEEDED": + raise RuntimeError(f"Athena query {query_id} failed.") + return result + + +def download_athena_query_result( + session: Session, + bucket: str, + prefix: str, + query_execution_id: str, + filename: str, +): + """Download query result file from S3. + + Args: + session: Session instance for boto calls. + bucket: S3 bucket name. + prefix: S3 key prefix. + query_execution_id: The query execution ID. + filename: Local filename to save to. + """ + _get_s3_client(session).download_file( + Bucket=bucket, + Key=f"{prefix}/{query_execution_id}.csv", + Filename=filename, + ) + + +def upload_dataframe_to_s3( + data_frame: DataFrame, + output_path: str, + session: Session, + kms_key: str = None, +) -> tuple[str, str]: + """Upload DataFrame to S3 as CSV. + + Args: + data_frame: DataFrame to upload. + output_path: S3 URI base path. + session: Session instance for boto calls. + kms_key: KMS key for encryption (default: None). + + Returns: + Tuple of (s3_folder, temp_table_name). + """ + + temp_id = utils.unique_name_from_base("dataframe-base") + local_file = f"{temp_id}.csv" + s3_folder = os.path.join(output_path, temp_id) + + data_frame.to_csv(local_file, index=False, header=False) + S3Uploader.upload( + local_path=local_file, + desired_s3_uri=s3_folder, + sagemaker_session=session, + kms_key=kms_key, + ) + os.remove(local_file) + + table_name = f'dataframe_{temp_id.replace("-", "_")}' + return s3_folder, table_name + + +def download_csv_from_s3( + s3_uri: str, + session: Session, + kms_key: str = None, +) -> DataFrame: + """Download CSV from S3 and return as DataFrame. + + Args: + s3_uri: S3 URI of the CSV file. + session: Session instance for boto calls. + kms_key: KMS key for decryption (default: None). + + Returns: + DataFrame with CSV contents. + """ + + S3Downloader.download( + s3_uri=s3_uri, + local_path="./", + kms_key=kms_key, + sagemaker_session=session, + ) + + local_file = s3_uri.split("/")[-1] + df = pd.read_csv(local_file) + os.remove(local_file) + + metadata_file = f"{local_file}.metadata" + if os.path.exists(metadata_file): + os.remove(metadata_file) + + return df + + +def get_session_from_role(region: str, assume_role: str = None) -> Session: + """Get a Session from a region and optional IAM role. + + Args: + region: AWS region name. + assume_role: IAM role ARN to assume (default: None). + + Returns: + Session instance. + """ + boto_session = boto3.Session(region_name=region) + + if assume_role: + sts = boto_session.client("sts", region_name=region) + credentials = sts.assume_role( + RoleArn=assume_role, + RoleSessionName="SagemakerExecution", + )["Credentials"] + + boto_session = boto3.Session( + region_name=region, + aws_access_key_id=credentials["AccessKeyId"], + aws_secret_access_key=credentials["SecretAccessKey"], + aws_session_token=credentials["SessionToken"], + ) + + return Session( + boto_session=boto_session, + sagemaker_client=boto_session.client("sagemaker"), + sagemaker_runtime_client=boto_session.client("sagemaker-runtime"), + sagemaker_featurestore_runtime_client=boto_session.client("sagemaker-featurestore-runtime"), + ) + + +# --- FeatureDefinition Functions --- + +def _is_collection_column(series: Series, sample_size: int = 1000) -> bool: + """Check if column contains list/set values.""" + sample = series.head(sample_size).dropna() + return sample.apply(lambda x: isinstance(x, (list, set))).any() + + +def _generate_feature_definition( + series: Series, + online_storage_type: str = None, +) -> FeatureDefinition: + """Generate a FeatureDefinition from a pandas Series.""" + dtype = str(series.dtype) + collection_type = None + + if online_storage_type == "InMemory" and _is_collection_column(series): + collection_type = ListCollectionType() + + if dtype in _INTEGER_TYPES: + return IntegralFeatureDefinition(series.name, collection_type) + if dtype in _FLOAT_TYPES: + return FractionalFeatureDefinition(series.name, collection_type) + return StringFeatureDefinition(series.name, collection_type) + + +def load_feature_definitions_from_dataframe( + data_frame: DataFrame, + online_storage_type: str = None, +) -> Sequence[FeatureDefinition]: + """Infer FeatureDefinitions from DataFrame dtypes. + + Column name is used as feature name. Feature type is inferred from the dtype + of the column. Integer dtypes are mapped to Integral feature type. Float dtypes + are mapped to Fractional feature type. All other dtypes are mapped to String. + + For IN_MEMORY online_storage_type, collection type columns within DataFrame + will be inferred as List instead of String. + + Args: + data_frame: DataFrame to infer features from. + online_storage_type: "Standard" or "InMemory" (default: None). + + Returns: + List of FeatureDefinition objects. + """ + return [ + _generate_feature_definition(data_frame[col], online_storage_type) + for col in data_frame.columns + ] + + +# --- FeatureGroup Functions --- + +def create_athena_query(feature_group_name: str, session: Session): + """Create an AthenaQuery for a FeatureGroup. + + Args: + feature_group_name: Name of the FeatureGroup. + session: Session instance for Athena boto calls. + + Returns: + AthenaQuery initialized with data catalog config. + + Raises: + RuntimeError: If no metastore is configured. + """ + from sagemaker.mlops.feature_store.athena_query import AthenaQuery + + fg = CoreFeatureGroup.get(feature_group_name=feature_group_name) + + if not fg.offline_store_config or not fg.offline_store_config.data_catalog_config: + raise RuntimeError("No metastore is configured with this feature group.") + + catalog_config = fg.offline_store_config.data_catalog_config + disable_glue = catalog_config.disable_glue_table_creation or False + + return AthenaQuery( + catalog=catalog_config.catalog if disable_glue else "AwsDataCatalog", + database=catalog_config.database, + table_name=catalog_config.table_name, + sagemaker_session=session, + ) + + +def as_hive_ddl( + feature_group_name: str, + database: str = "sagemaker_featurestore", + table_name: str = None, +) -> str: + """Generate Hive DDL for a FeatureGroup's offline store table. + + Schema of the table is generated based on the feature definitions. Columns are named + after feature name and data-type are inferred based on feature type. Integral feature + type is mapped to INT data-type. Fractional feature type is mapped to FLOAT data-type. + String feature type is mapped to STRING data-type. + + Args: + feature_group_name: Name of the FeatureGroup. + database: Hive database name (default: "sagemaker_featurestore"). + table_name: Hive table name (default: feature_group_name). + + Returns: + CREATE EXTERNAL TABLE DDL string. + """ + fg = CoreFeatureGroup.get(feature_group_name=feature_group_name) + table_name = table_name or feature_group_name + resolved_output_s3_uri = fg.offline_store_config.s3_storage_config.resolved_output_s3_uri + + ddl = f"CREATE EXTERNAL TABLE IF NOT EXISTS {database}.{table_name} (\n" + for fd in fg.feature_definitions: + ddl += f" {fd.feature_name} {_FEATURE_TYPE_TO_DDL_DATA_TYPE_MAP.get(fd.feature_type)}\n" + ddl += " write_time TIMESTAMP\n" + ddl += " event_time TIMESTAMP\n" + ddl += " is_deleted BOOLEAN\n" + ddl += ")\n" + ddl += ( + "ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'\n" + " STORED AS\n" + " INPUTFORMAT 'parquet.hive.DeprecatedParquetInputFormat'\n" + " OUTPUTFORMAT 'parquet.hive.DeprecatedParquetOutputFormat'\n" + f"LOCATION '{resolved_output_s3_uri}'" + ) + return ddl + + +def ingest_dataframe( + feature_group_name: str, + data_frame: DataFrame, + max_workers: int = 1, + max_processes: int = 1, + wait: bool = True, + timeout: Union[int, float] = None, +): + """Ingest a pandas DataFrame to a FeatureGroup. + + Args: + feature_group_name: Name of the FeatureGroup. + data_frame: DataFrame to ingest. + max_workers: Threads per process (default: 1). + max_processes: Number of processes (default: 1). + wait: Wait for ingestion to complete (default: True). + timeout: Timeout in seconds (default: None). + + Returns: + IngestionManagerPandas instance. + + Raises: + ValueError: If max_workers or max_processes <= 0. + """ + + if max_processes <= 0: + raise ValueError("max_processes must be greater than 0.") + if max_workers <= 0: + raise ValueError("max_workers must be greater than 0.") + + fg = CoreFeatureGroup.get(feature_group_name=feature_group_name) + feature_definitions = {fd.feature_name: fd.feature_type for fd in fg.feature_definitions} + + manager = IngestionManagerPandas( + feature_group_name=feature_group_name, + feature_definitions=feature_definitions, + max_workers=max_workers, + max_processes=max_processes, + ) + manager.run(data_frame=data_frame, wait=wait, timeout=timeout) + return manager + +def create_dataset( + base: Union[FeatureGroup, pd.DataFrame], + output_path: str, + session: Session, + record_identifier_feature_name: str = None, + event_time_identifier_feature_name: str = None, + included_feature_names: Sequence[str] = None, + kms_key_id: str = None, +) -> DatasetBuilder: + """Create a DatasetBuilder for generating a Dataset.""" + if isinstance(base, pd.DataFrame): + if not record_identifier_feature_name or not event_time_identifier_feature_name: + raise ValueError( + "record_identifier_feature_name and event_time_identifier_feature_name " + "are required when base is a DataFrame." + ) + return DatasetBuilder( + _sagemaker_session=session, + _base=base, + _output_path=output_path, + _record_identifier_feature_name=record_identifier_feature_name, + _event_time_identifier_feature_name=event_time_identifier_feature_name, + _included_feature_names=included_feature_names, + _kms_key_id=kms_key_id, + ) + diff --git a/sagemaker-mlops/src/sagemaker/mlops/feature_store/ingestion_manager_pandas.py b/sagemaker-mlops/src/sagemaker/mlops/feature_store/ingestion_manager_pandas.py new file mode 100644 index 0000000000..60d022dab1 --- /dev/null +++ b/sagemaker-mlops/src/sagemaker/mlops/feature_store/ingestion_manager_pandas.py @@ -0,0 +1,321 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 +"""Multi-threaded data ingestion for FeatureStore using SageMaker Core.""" +import logging +import math +import signal +from concurrent.futures import ThreadPoolExecutor, as_completed +from dataclasses import dataclass, field +from multiprocessing.pool import AsyncResult +from typing import Any, Dict, Iterable, List, Sequence, Union + +import pandas as pd +from pandas import DataFrame +from pandas.api.types import is_list_like +from pathos.multiprocessing import ProcessingPool + +from sagemaker.core.resources import FeatureGroup as CoreFeatureGroup +from sagemaker.core.shapes import FeatureValue + +logger = logging.getLogger(__name__) + + +class IngestionError(Exception): + """Exception raised for errors during ingestion. + + Attributes: + failed_rows: List of row indices that failed to ingest. + message: Error message. + """ + + def __init__(self, failed_rows: List[int], message: str): + self.failed_rows = failed_rows + self.message = message + super().__init__(self.message) + + +@dataclass +class IngestionManagerPandas: + """Class to manage the multi-threaded data ingestion process. + + This class will manage the data ingestion process which is multi-threaded. + + Attributes: + feature_group_name (str): name of the Feature Group. + feature_definitions (Dict[str, Dict[Any, Any]]): dictionary of feature definitions + where the key is the feature name and the value is the FeatureDefinition. + The FeatureDefinition contains the data type of the feature. + max_workers (int): number of threads to create. + max_processes (int): number of processes to create. Each process spawns + ``max_workers`` threads. + """ + + feature_group_name: str + feature_definitions: Dict[str, Dict[Any, Any]] + max_workers: int = 1 + max_processes: int = 1 + _async_result: AsyncResult = field(default=None, init=False) + _processing_pool: ProcessingPool = field(default=None, init=False) + _failed_indices: List[int] = field(default_factory=list, init=False) + + @property + def failed_rows(self) -> List[int]: + """Get rows that failed to ingest. + + Returns: + List of row indices that failed to be ingested. + """ + return self._failed_indices + + def run( + self, + data_frame: DataFrame, + target_stores: List[str] = None, + wait: bool = True, + timeout: Union[int, float] = None, + ): + """Start the ingestion process. + + Args: + data_frame (DataFrame): source DataFrame to be ingested. + target_stores (List[str]): list of target stores ("OnlineStore", "OfflineStore"). + If None, the default target store is used. + wait (bool): whether to wait for the ingestion to finish or not. + timeout (Union[int, float]): ``concurrent.futures.TimeoutError`` will be raised + if timeout is reached. + """ + if self.max_workers == 1 and self.max_processes == 1: + self._run_single_process_single_thread(data_frame=data_frame, target_stores=target_stores) + else: + self._run_multi_process(data_frame=data_frame, target_stores=target_stores, wait=wait, timeout=timeout) + + def wait(self, timeout: Union[int, float] = None): + """Wait for the ingestion process to finish. + + Args: + timeout (Union[int, float]): ``concurrent.futures.TimeoutError`` will be raised + if timeout is reached. + """ + try: + results = self._async_result.get(timeout=timeout) + except KeyboardInterrupt as e: + self._processing_pool.terminate() + self._processing_pool.close() + self._processing_pool.clear() + raise e + else: + self._processing_pool.close() + self._processing_pool.clear() + + self._failed_indices = [idx for failed in results for idx in failed] + + if self._failed_indices: + raise IngestionError( + self._failed_indices, + f"Failed to ingest some data into FeatureGroup {self.feature_group_name}", + ) + + def _run_single_process_single_thread( + self, + data_frame: DataFrame, + target_stores: List[str] = None, + ): + """Ingest utilizing a single process and a single thread.""" + logger.info("Started single-threaded ingestion for %d rows", len(data_frame)) + failed_rows = [] + + fg = CoreFeatureGroup(feature_group_name=self.feature_group_name) + + for row in data_frame.itertuples(): + self._ingest_row( + data_frame=data_frame, + row=row, + feature_group=fg, + feature_definitions=self.feature_definitions, + failed_rows=failed_rows, + target_stores=target_stores, + ) + + self._failed_indices = failed_rows + if self._failed_indices: + raise IngestionError( + self._failed_indices, + f"Failed to ingest some data into FeatureGroup {self.feature_group_name}", + ) + + def _run_multi_process( + self, + data_frame: DataFrame, + target_stores: List[str] = None, + wait: bool = True, + timeout: Union[int, float] = None, + ): + """Start the ingestion process with the specified number of processes.""" + batch_size = math.ceil(data_frame.shape[0] / self.max_processes) + + args = [] + for i in range(self.max_processes): + start_index = min(i * batch_size, data_frame.shape[0]) + end_index = min(i * batch_size + batch_size, data_frame.shape[0]) + args.append(( + self.max_workers, + self.feature_group_name, + self.feature_definitions, + data_frame[start_index:end_index], + target_stores, + start_index, + timeout, + )) + + def init_worker(): + signal.signal(signal.SIGINT, signal.SIG_IGN) + + self._processing_pool = ProcessingPool(self.max_processes, init_worker) + self._processing_pool.restart(force=True) + + self._async_result = self._processing_pool.amap( + lambda x: IngestionManagerPandas._run_multi_threaded(*x), + args, + ) + + if wait: + self.wait(timeout=timeout) + + @staticmethod + def _run_multi_threaded( + max_workers: int, + feature_group_name: str, + feature_definitions: Dict[str, Dict[Any, Any]], + data_frame: DataFrame, + target_stores: List[str] = None, + row_offset: int = 0, + timeout: Union[int, float] = None, + ) -> List[int]: + """Start multi-threaded ingestion within a single process.""" + executor = ThreadPoolExecutor(max_workers=max_workers) + batch_size = math.ceil(data_frame.shape[0] / max_workers) + + futures = {} + for i in range(max_workers): + start_index = min(i * batch_size, data_frame.shape[0]) + end_index = min(i * batch_size + batch_size, data_frame.shape[0]) + future = executor.submit( + IngestionManagerPandas._ingest_single_batch, + data_frame=data_frame, + feature_group_name=feature_group_name, + feature_definitions=feature_definitions, + start_index=start_index, + end_index=end_index, + target_stores=target_stores, + ) + futures[future] = (start_index + row_offset, end_index + row_offset) + + failed_indices = [] + for future in as_completed(futures, timeout=timeout): + start, end = futures[future] + failed_rows = future.result() + if not failed_rows: + logger.info("Successfully ingested row %d to %d", start, end) + failed_indices.extend(failed_rows) + + executor.shutdown(wait=False) + return failed_indices + + @staticmethod + def _ingest_single_batch( + data_frame: DataFrame, + feature_group_name: str, + feature_definitions: Dict[str, Dict[Any, Any]], + start_index: int, + end_index: int, + target_stores: List[str] = None, + ) -> List[int]: + """Ingest a single batch of DataFrame rows into FeatureStore.""" + logger.info("Started ingesting index %d to %d", start_index, end_index) + failed_rows = [] + + fg = CoreFeatureGroup(feature_group_name=feature_group_name) + + for row in data_frame[start_index:end_index].itertuples(): + IngestionManagerPandas._ingest_row( + data_frame=data_frame, + row=row, + feature_group=fg, + feature_definitions=feature_definitions, + failed_rows=failed_rows, + target_stores=target_stores, + ) + + return failed_rows + + @staticmethod + def _ingest_row( + data_frame: DataFrame, + row: Iterable, + feature_group: CoreFeatureGroup, + feature_definitions: Dict[str, Dict[Any, Any]], + failed_rows: List[int], + target_stores: List[str] = None, + ): + """Ingest a single DataFrame row into FeatureStore using SageMaker Core.""" + try: + record = [] + for index in range(1, len(row)): + feature_name = data_frame.columns[index - 1] + feature_value = row[index] + + if not IngestionManagerPandas._feature_value_is_not_none(feature_value): + continue + + if IngestionManagerPandas._is_feature_collection_type(feature_name, feature_definitions): + record.append(FeatureValue( + feature_name=feature_name, + value_as_string_list=IngestionManagerPandas._convert_to_string_list(feature_value), + )) + else: + record.append(FeatureValue( + feature_name=feature_name, + value_as_string=str(feature_value), + )) + + # Use SageMaker Core's put_record directly + feature_group.put_record( + record=record, + target_stores=target_stores, + ) + + except Exception as e: + logger.error("Failed to ingest row %d: %s", row[0], e) + failed_rows.append(row[0]) + + @staticmethod + def _is_feature_collection_type( + feature_name: str, + feature_definitions: Dict[str, Dict[Any, Any]], + ) -> bool: + """Check if the feature is a collection type.""" + feature_def = feature_definitions.get(feature_name) + if feature_def: + return feature_def.get("CollectionType") is not None + return False + + @staticmethod + def _feature_value_is_not_none(feature_value: Any) -> bool: + """Check if the feature value is not None. + + For Collection Type features, we check if the value is not None. + For Scalar values, we use pd.notna() to keep the behavior same. + """ + if not is_list_like(feature_value): + return pd.notna(feature_value) + return feature_value is not None + + @staticmethod + def _convert_to_string_list(feature_value: List[Any]) -> List[str]: + """Convert a list of feature values to a list of strings.""" + if not is_list_like(feature_value): + raise ValueError( + f"Invalid feature value: {feature_value} for a collection type feature " + f"must be an Array, but was {type(feature_value)}" + ) + return [str(v) if v is not None else None for v in feature_value] diff --git a/sagemaker-mlops/src/sagemaker/mlops/feature_store/inputs.py b/sagemaker-mlops/src/sagemaker/mlops/feature_store/inputs.py new file mode 100644 index 0000000000..f264059eb3 --- /dev/null +++ b/sagemaker-mlops/src/sagemaker/mlops/feature_store/inputs.py @@ -0,0 +1,60 @@ +"""Enums for FeatureStore operations.""" +from enum import Enum + +class TargetStoreEnum(Enum): + """Store types for put_record.""" + ONLINE_STORE = "OnlineStore" + OFFLINE_STORE = "OfflineStore" + +class OnlineStoreStorageTypeEnum(Enum): + """Storage types for online store.""" + STANDARD = "Standard" + IN_MEMORY = "InMemory" + +class TableFormatEnum(Enum): + """Offline store table formats.""" + GLUE = "Glue" + ICEBERG = "Iceberg" + +class ResourceEnum(Enum): + """Resource types for search.""" + FEATURE_GROUP = "FeatureGroup" + FEATURE_METADATA = "FeatureMetadata" + +class SearchOperatorEnum(Enum): + """Search operators.""" + AND = "And" + OR = "Or" + +class SortOrderEnum(Enum): + """Sort orders.""" + ASCENDING = "Ascending" + DESCENDING = "Descending" + +class FilterOperatorEnum(Enum): + """Filter operators.""" + EQUALS = "Equals" + NOT_EQUALS = "NotEquals" + GREATER_THAN = "GreaterThan" + GREATER_THAN_OR_EQUAL_TO = "GreaterThanOrEqualTo" + LESS_THAN = "LessThan" + LESS_THAN_OR_EQUAL_TO = "LessThanOrEqualTo" + CONTAINS = "Contains" + EXISTS = "Exists" + NOT_EXISTS = "NotExists" + IN = "In" + +class DeletionModeEnum(Enum): + """Deletion modes for delete_record.""" + SOFT_DELETE = "SoftDelete" + HARD_DELETE = "HardDelete" + +class ExpirationTimeResponseEnum(Enum): + """ExpiresAt response toggle.""" + DISABLED = "Disabled" + ENABLED = "Enabled" + +class ThroughputModeEnum(Enum): + """Throughput modes for feature group.""" + ON_DEMAND = "OnDemand" + PROVISIONED = "Provisioned" \ No newline at end of file From 193d16fa2c61440ed1cd4d906e64e2726229ce6e Mon Sep 17 00:00:00 2001 From: adishaa Date: Fri, 16 Jan 2026 11:34:01 -0800 Subject: [PATCH 02/10] Add feature store tests --- .../mlops/feature_store/MIGRATION_GUIDE.md | 513 ++++++++++++++++++ .../sagemaker/mlops/feature_store/__init__.py | 8 +- .../mlops/feature_store/dataset_builder.py | 45 +- .../mlops/feature_store/feature_utils.py | 31 +- .../feature_store/ingestion_manager_pandas.py | 19 +- sagemaker-mlops/tests/__init__.py | 0 sagemaker-mlops/tests/unit/__init__.py | 0 .../tests/unit/sagemaker/__init__.py | 0 .../tests/unit/sagemaker/mlops/__init__.py | 0 .../sagemaker/mlops/feature_store/__init__.py | 2 + .../sagemaker/mlops/feature_store/conftest.py | 80 +++ .../mlops/feature_store/test_athena_query.py | 113 ++++ .../feature_store/test_dataset_builder.py | 345 ++++++++++++ .../feature_store/test_feature_definition.py | 126 +++++ .../mlops/feature_store/test_feature_utils.py | 202 +++++++ .../test_ingestion_manager_pandas.py | 256 +++++++++ .../mlops/feature_store/test_inputs.py | 109 ++++ 17 files changed, 1802 insertions(+), 47 deletions(-) create mode 100644 sagemaker-mlops/src/sagemaker/mlops/feature_store/MIGRATION_GUIDE.md create mode 100644 sagemaker-mlops/tests/__init__.py create mode 100644 sagemaker-mlops/tests/unit/__init__.py create mode 100644 sagemaker-mlops/tests/unit/sagemaker/__init__.py create mode 100644 sagemaker-mlops/tests/unit/sagemaker/mlops/__init__.py create mode 100644 sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/__init__.py create mode 100644 sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/conftest.py create mode 100644 sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_athena_query.py create mode 100644 sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_dataset_builder.py create mode 100644 sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_feature_definition.py create mode 100644 sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_feature_utils.py create mode 100644 sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_ingestion_manager_pandas.py create mode 100644 sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_inputs.py diff --git a/sagemaker-mlops/src/sagemaker/mlops/feature_store/MIGRATION_GUIDE.md b/sagemaker-mlops/src/sagemaker/mlops/feature_store/MIGRATION_GUIDE.md new file mode 100644 index 0000000000..40942fa6f3 --- /dev/null +++ b/sagemaker-mlops/src/sagemaker/mlops/feature_store/MIGRATION_GUIDE.md @@ -0,0 +1,513 @@ +# SageMaker FeatureStore V2 to V3 Migration Guide + +## Overview + +V3 uses **sagemaker-core** as the foundation, which provides: +- Pydantic-based shapes with automatic serialization +- Resource classes that manage boto clients internally +- No need for explicit Session management in most cases + +## File Mapping + +| V2 File | V3 File | Notes | +|---------|---------|-------| +| `feature_group.py` | Re-exported from `sagemaker_core.main.resources` | No wrapper class needed | +| `feature_store.py` | Re-exported from `sagemaker_core.main.resources` | `FeatureStore.search()` available | +| `feature_definition.py` | `feature_definition.py` | Helper factories retained | +| `feature_utils.py` | `feature_utils.py` | Standalone functions | +| `inputs.py` | `inputs.py` | Enums only (shapes from core) | +| `dataset_builder.py` | `dataset_builder.py` | Converted to dataclass | +| N/A | `athena_query.py` | Extracted from feature_group.py | +| N/A | `ingestion_manager_pandas.py` | Extracted from feature_group.py | + +--- + +## FeatureGroup Operations + +### Create FeatureGroup + +**V2:** +```python +from sagemaker.feature_store.feature_group import FeatureGroup +from sagemaker.session import Session + +session = Session() +fg = FeatureGroup(name="my-fg", sagemaker_session=session) +fg.load_feature_definitions(data_frame=df) +fg.create( + s3_uri="s3://bucket/prefix", + record_identifier_name="id", + event_time_feature_name="ts", + role_arn=role, + enable_online_store=True, +) +``` + +**V3:** +```python +from sagemaker.mlops.feature_store import ( + FeatureGroup, + OnlineStoreConfig, + OfflineStoreConfig, + S3StorageConfig, + load_feature_definitions_from_dataframe, +) + +feature_defs = load_feature_definitions_from_dataframe(df) + +FeatureGroup.create( + feature_group_name="my-fg", + feature_definitions=feature_defs, + record_identifier_feature_name="id", + event_time_feature_name="ts", + role_arn=role, + online_store_config=OnlineStoreConfig(enable_online_store=True), + offline_store_config=OfflineStoreConfig( + s3_storage_config=S3StorageConfig(s3_uri="s3://bucket/prefix") + ), +) +``` + +### Get/Describe FeatureGroup + +**V2:** +```python +fg = FeatureGroup(name="my-fg", sagemaker_session=session) +response = fg.describe() +``` + +**V3:** +```python +from sagemaker.mlops.feature_store import FeatureGroup + +fg = FeatureGroup.get(feature_group_name="my-fg") +# fg is now a typed object with attributes: +# fg.feature_group_name, fg.feature_definitions, fg.offline_store_config, etc. +``` + +### Delete FeatureGroup + +**V2:** +```python +fg.delete() +``` + +**V3:** +```python +FeatureGroup(feature_group_name="my-fg").delete() +# or +fg = FeatureGroup.get(feature_group_name="my-fg") +fg.delete() +``` + +### Update FeatureGroup + +**V2:** +```python +fg.update( + feature_additions=[FeatureDefinition("new_col", FeatureTypeEnum.STRING)], + throughput_config=ThroughputConfigUpdate(mode=ThroughputModeEnum.ON_DEMAND), +) +``` + +**V3:** +```python +from sagemaker.mlops.feature_store import FeatureGroup, ThroughputConfig + +fg = FeatureGroup.get(feature_group_name="my-fg") +fg.update( + feature_additions=[{"FeatureName": "new_col", "FeatureType": "String"}], + throughput_config=ThroughputConfig(throughput_mode="OnDemand"), +) +``` + +--- + +## Record Operations + +### Put Record + +**V2:** +```python +from sagemaker.feature_store.inputs import FeatureValue + +fg.put_record( + record=[ + FeatureValue(feature_name="id", value_as_string="123"), + FeatureValue(feature_name="name", value_as_string="John"), + ], + target_stores=[TargetStoreEnum.ONLINE_STORE], +) +``` + +**V3:** +```python +from sagemaker.mlops.feature_store import FeatureGroup, FeatureValue + +FeatureGroup(feature_group_name="my-fg").put_record( + record=[ + FeatureValue(feature_name="id", value_as_string="123"), + FeatureValue(feature_name="name", value_as_string="John"), + ], + target_stores=["OnlineStore"], # strings, not enums +) +``` + +### Get Record + +**V2:** +```python +response = fg.get_record(record_identifier_value_as_string="123") +``` + +**V3:** +```python +response = FeatureGroup(feature_group_name="my-fg").get_record( + record_identifier_value_as_string="123" +) +``` + +### Delete Record + +**V2:** +```python +fg.delete_record( + record_identifier_value_as_string="123", + event_time="2024-01-15T00:00:00Z", + deletion_mode=DeletionModeEnum.SOFT_DELETE, +) +``` + +**V3:** +```python +FeatureGroup(feature_group_name="my-fg").delete_record( + record_identifier_value_as_string="123", + event_time="2024-01-15T00:00:00Z", + deletion_mode="SoftDelete", # string, not enum +) +``` + +### Batch Get Record + +**V2:** +```python +from sagemaker.feature_store.feature_store import FeatureStore +from sagemaker.feature_store.inputs import Identifier + +fs = FeatureStore(sagemaker_session=session) +response = fs.batch_get_record( + identifiers=[ + Identifier(feature_group_name="my-fg", record_identifiers_value_as_string=["123", "456"]) + ] +) +``` + +**V3:** +```python +from sagemaker.mlops.feature_store import FeatureGroup + +response = FeatureGroup(feature_group_name="my-fg").batch_get_record( + identifiers=[ + {"FeatureGroupName": "my-fg", "RecordIdentifiersValueAsString": ["123", "456"]} + ] +) +``` + +--- + +## DataFrame Ingestion + +**V2:** +```python +fg.ingest(data_frame=df, max_workers=4, max_processes=2, wait=True) +``` + +**V3:** +```python +from sagemaker.mlops.feature_store import ingest_dataframe + +manager = ingest_dataframe( + feature_group_name="my-fg", + data_frame=df, + max_workers=4, + max_processes=2, + wait=True, +) +# Access failed rows: manager.failed_rows +``` + +--- + +## Athena Query + +**V2:** +```python +query = fg.athena_query() +query.run(query_string="SELECT * FROM ...", output_location="s3://...") +query.wait() +df = query.as_dataframe() +``` + +**V3:** +```python +from sagemaker.mlops.feature_store import create_athena_query + +query = create_athena_query("my-fg", session) +query.run(query_string="SELECT * FROM ...", output_location="s3://...") +query.wait() +df = query.as_dataframe() +``` + +--- + +## Hive DDL Generation + +**V2:** +```python +ddl = fg.as_hive_ddl(database="mydb", table_name="mytable") +``` + +**V3:** +```python +from sagemaker.mlops.feature_store import as_hive_ddl + +ddl = as_hive_ddl("my-fg", database="mydb", table_name="mytable") +``` + +--- + +## Feature Definitions + +**V2:** +```python +fg.load_feature_definitions(data_frame=df) +# Modifies fg.feature_definitions in place +``` + +**V3:** +```python +from sagemaker.mlops.feature_store import load_feature_definitions_from_dataframe + +defs = load_feature_definitions_from_dataframe(df) +# Returns list, doesn't modify any object +``` + +### Using Helper Factories + +**V2 & V3 (same):** +```python +from sagemaker.mlops.feature_store import ( + FractionalFeatureDefinition, + IntegralFeatureDefinition, + StringFeatureDefinition, + VectorCollectionType, +) + +defs = [ + IntegralFeatureDefinition("id"), + StringFeatureDefinition("name"), + FractionalFeatureDefinition("embedding", VectorCollectionType(128)), +] +``` + +--- + +## Search + +**V2:** +```python +from sagemaker.feature_store.feature_store import FeatureStore +from sagemaker.feature_store.inputs import Filter, ResourceEnum + +fs = FeatureStore(sagemaker_session=session) +response = fs.search( + resource=ResourceEnum.FEATURE_GROUP, + filters=[Filter(name="FeatureGroupName", value="my-prefix", operator=FilterOperatorEnum.CONTAINS)], +) +``` + +**V3:** +```python +from sagemaker.mlops.feature_store import FeatureStore, Filter, SearchExpression + +response = FeatureStore.search( + resource="FeatureGroup", + search_expression=SearchExpression( + filters=[Filter(name="FeatureGroupName", value="my-prefix", operator="Contains")] + ), +) +``` + +--- + +## Feature Metadata + +**V2:** +```python +fg.describe_feature_metadata(feature_name="my-feature") +fg.update_feature_metadata(feature_name="my-feature", description="Updated desc") +fg.list_parameters_for_feature_metadata(feature_name="my-feature") +``` + +**V3:** +```python +from sagemaker.mlops.feature_store import FeatureMetadata + +# Get metadata +metadata = FeatureMetadata.get(feature_group_name="my-fg", feature_name="my-feature") +print(metadata.description) +print(metadata.parameters) + +# Update metadata +metadata.update(description="Updated desc") +``` + +--- + +## Dataset Builder + +**V2:** +```python +from sagemaker.feature_store.feature_store import FeatureStore + +fs = FeatureStore(sagemaker_session=session) +builder = fs.create_dataset( + base=fg, + output_path="s3://bucket/output", +) +builder.with_feature_group(other_fg, target_feature_name_in_base="id") +builder.point_in_time_accurate_join() +df, query = builder.to_dataframe() +``` + +**V3:** +```python +from sagemaker.mlops.feature_store import create_dataset, FeatureGroup + +fg = FeatureGroup.get(feature_group_name="my-fg") +other_fg = FeatureGroup.get(feature_group_name="other-fg") + +builder = create_dataset( + base=fg, + output_path="s3://bucket/output", + session=session, +) +builder.with_feature_group(other_fg, target_feature_name_in_base="id") +builder.point_in_time_accurate_join() +df, query = builder.to_dataframe() +``` + +--- + +## Config Objects (Shapes) + +**V2:** +```python +from sagemaker.feature_store.inputs import ( + OnlineStoreConfig, + OfflineStoreConfig, + S3StorageConfig, + TtlDuration, +) + +config = OnlineStoreConfig(enable_online_store=True, ttl_duration=TtlDuration(unit="Hours", value=24)) +config.to_dict() # Manual serialization required +``` + +**V3:** +```python +from sagemaker.mlops.feature_store import ( + OnlineStoreConfig, + OfflineStoreConfig, + S3StorageConfig, + TtlDuration, +) + +config = OnlineStoreConfig(enable_online_store=True, ttl_duration=TtlDuration(unit="Hours", value=24)) +# No to_dict() needed - Pydantic handles serialization automatically +``` + +--- + +## Key Differences Summary + +| Aspect | V2 | V3 | +|--------|----|----| +| **Session** | Required for most operations | Optional - core manages clients | +| **FeatureGroup** | Wrapper class with session | Direct core resource class | +| **Shapes** | `@attr.s` with `to_dict()` | Pydantic with auto-serialization | +| **Enums** | `TargetStoreEnum.ONLINE_STORE.value` | Just use strings: `"OnlineStore"` | +| **Methods** | Instance methods on FeatureGroup | Standalone functions + core methods | +| **Ingestion** | `fg.ingest(df)` | `ingest_dataframe(name, df)` | +| **Athena** | `fg.athena_query()` | `create_athena_query(name, session)` | +| **DDL** | `fg.as_hive_ddl()` | `as_hive_ddl(name)` | +| **Feature Defs** | `fg.load_feature_definitions(df)` | `load_feature_definitions_from_dataframe(df)` | +| **Imports** | Multiple modules | Single `__init__.py` re-exports all | + +--- + +## Missing in V3 (Intentionally) + +These V2 features are **not wrapped** because core provides them directly: + +- `FeatureGroup.create()` - use `FeatureGroup.create()` from core +- `FeatureGroup.delete()` - use `FeatureGroup(...).delete()` from core +- `FeatureGroup.describe()` - use `FeatureGroup.get()` from core (returns typed object) +- `FeatureGroup.update()` - use `FeatureGroup(...).update()` from core +- `FeatureGroup.put_record()` - use `FeatureGroup(...).put_record()` from core +- `FeatureGroup.get_record()` - use `FeatureGroup(...).get_record()` from core +- `FeatureGroup.delete_record()` - use `FeatureGroup(...).delete_record()` from core +- `FeatureGroup.batch_get_record()` - use `FeatureGroup(...).batch_get_record()` from core +- `FeatureStore.search()` - use `FeatureStore.search()` from core +- `FeatureStore.list_feature_groups()` - use `FeatureGroup.get_all()` from core +- All config shapes (`OnlineStoreConfig`, etc.) - re-exported from core + +--- + +## Import Cheatsheet + +```python +# V3 - Everything from one place +from sagemaker.mlops.feature_store import ( + # Resources (from core) + FeatureGroup, + FeatureStore, + FeatureMetadata, + + # Shapes (from core) + OnlineStoreConfig, + OfflineStoreConfig, + S3StorageConfig, + DataCatalogConfig, + TtlDuration, + FeatureValue, + FeatureParameter, + ThroughputConfig, + Filter, + SearchExpression, + + # Enums (local) + TargetStoreEnum, + OnlineStoreStorageTypeEnum, + TableFormatEnum, + DeletionModeEnum, + ThroughputModeEnum, + + # Feature Definition helpers (local) + FeatureDefinition, + FractionalFeatureDefinition, + IntegralFeatureDefinition, + StringFeatureDefinition, + VectorCollectionType, + + # Utility functions (local) + create_athena_query, + as_hive_ddl, + load_feature_definitions_from_dataframe, + ingest_dataframe, + create_dataset, + + # Classes (local) + DatasetBuilder, +) +``` diff --git a/sagemaker-mlops/src/sagemaker/mlops/feature_store/__init__.py b/sagemaker-mlops/src/sagemaker/mlops/feature_store/__init__.py index ee8cd7d1a3..f15d6d3845 100644 --- a/sagemaker-mlops/src/sagemaker/mlops/feature_store/__init__.py +++ b/sagemaker-mlops/src/sagemaker/mlops/feature_store/__init__.py @@ -3,11 +3,10 @@ """SageMaker FeatureStore V3 - powered by sagemaker-core.""" # Resources from core -from sagemaker_core.main.resources import FeatureGroup, FeatureMetadata -from sagemaker_core.main.resources import FeatureStore +from sagemaker.core.resources import FeatureGroup, FeatureMetadata # Shapes from core (Pydantic - no to_dict() needed) -from sagemaker_core.main.shapes import ( +from sagemaker.core.shapes import ( DataCatalogConfig, FeatureParameter, FeatureValue, @@ -52,7 +51,6 @@ from sagemaker.mlops.feature_store.feature_utils import ( as_hive_ddl, create_athena_query, - create_dataset, get_session_from_role, ingest_dataframe, load_feature_definitions_from_dataframe, @@ -76,7 +74,6 @@ # Resources "FeatureGroup", "FeatureMetadata", - "FeatureStore", # Shapes "DataCatalogConfig", "FeatureParameter", @@ -113,7 +110,6 @@ # Utility functions "as_hive_ddl", "create_athena_query", - "create_dataset", "get_session_from_role", "ingest_dataframe", "load_feature_definitions_from_dataframe", diff --git a/sagemaker-mlops/src/sagemaker/mlops/feature_store/dataset_builder.py b/sagemaker-mlops/src/sagemaker/mlops/feature_store/dataset_builder.py index f5450663a6..72e9535320 100644 --- a/sagemaker-mlops/src/sagemaker/mlops/feature_store/dataset_builder.py +++ b/sagemaker-mlops/src/sagemaker/mlops/feature_store/dataset_builder.py @@ -178,7 +178,9 @@ def construct_feature_group_to_be_merged( database=catalog_config.database, table_name=catalog_config.table_name, record_identifier_feature_name=record_id, - event_time_identifier_feature=FeatureDefinition(event_time_name, FeatureTypeEnum(event_time_type)), + event_time_identifier_feature=FeatureDefinition( + feature_name=event_time_name, feature_type=FeatureTypeEnum(event_time_type).value + ), target_feature_name_in_base=target_feature_name_in_base, table_type=TableType.FEATURE_GROUP, feature_name_in_target=feature_name_in_target, @@ -256,6 +258,47 @@ class DatasetBuilder: _event_time_ending_timestamp: datetime.datetime = field(default=None, init=False) _feature_groups_to_be_merged: List[FeatureGroupToBeMerged] = field(default_factory=list, init=False) + @classmethod + def create( + cls, + base: Union[FeatureGroup, pd.DataFrame], + output_path: str, + session: Session, + record_identifier_feature_name: str = None, + event_time_identifier_feature_name: str = None, + included_feature_names: List[str] = None, + kms_key_id: str = None, + ) -> "DatasetBuilder": + """Create a DatasetBuilder for generating a Dataset. + + Args: + base: A FeatureGroup or DataFrame to use as the base. + output_path: S3 URI for output. + session: SageMaker session. + record_identifier_feature_name: Required if base is DataFrame. + event_time_identifier_feature_name: Required if base is DataFrame. + included_feature_names: Features to include in output. + kms_key_id: KMS key for encryption. + + Returns: + DatasetBuilder instance. + """ + if isinstance(base, pd.DataFrame): + if not record_identifier_feature_name or not event_time_identifier_feature_name: + raise ValueError( + "record_identifier_feature_name and event_time_identifier_feature_name " + "are required when base is a DataFrame." + ) + return cls( + _sagemaker_session=session, + _base=base, + _output_path=output_path, + _record_identifier_feature_name=record_identifier_feature_name, + _event_time_identifier_feature_name=event_time_identifier_feature_name, + _included_feature_names=included_feature_names, + _kms_key_id=kms_key_id, + ) + def with_feature_group( self, feature_group: FeatureGroup, diff --git a/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_utils.py b/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_utils.py index f7f6523b8d..0b7c747515 100644 --- a/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_utils.py +++ b/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_utils.py @@ -13,7 +13,6 @@ from sagemaker.mlops.feature_store import FeatureGroup as CoreFeatureGroup, FeatureGroup from sagemaker.core.helper.session_helper import Session from sagemaker.core.s3.client import S3Uploader, S3Downloader -from sagemaker.mlops.feature_store.dataset_builder import DatasetBuilder from sagemaker.mlops.feature_store.feature_definition import ( FeatureDefinition, FractionalFeatureDefinition, @@ -23,7 +22,7 @@ ) from sagemaker.mlops.feature_store.ingestion_manager_pandas import IngestionManagerPandas -from sagemaker import utils +from sagemaker.core.utils import unique_name_from_base logger = logging.getLogger(__name__) @@ -207,7 +206,7 @@ def upload_dataframe_to_s3( Tuple of (s3_folder, temp_table_name). """ - temp_id = utils.unique_name_from_base("dataframe-base") + temp_id = unique_name_from_base("dataframe-base") local_file = f"{temp_id}.csv" s3_folder = os.path.join(output_path, temp_id) @@ -460,29 +459,3 @@ def ingest_dataframe( manager.run(data_frame=data_frame, wait=wait, timeout=timeout) return manager -def create_dataset( - base: Union[FeatureGroup, pd.DataFrame], - output_path: str, - session: Session, - record_identifier_feature_name: str = None, - event_time_identifier_feature_name: str = None, - included_feature_names: Sequence[str] = None, - kms_key_id: str = None, -) -> DatasetBuilder: - """Create a DatasetBuilder for generating a Dataset.""" - if isinstance(base, pd.DataFrame): - if not record_identifier_feature_name or not event_time_identifier_feature_name: - raise ValueError( - "record_identifier_feature_name and event_time_identifier_feature_name " - "are required when base is a DataFrame." - ) - return DatasetBuilder( - _sagemaker_session=session, - _base=base, - _output_path=output_path, - _record_identifier_feature_name=record_identifier_feature_name, - _event_time_identifier_feature_name=event_time_identifier_feature_name, - _included_feature_names=included_feature_names, - _kms_key_id=kms_key_id, - ) - diff --git a/sagemaker-mlops/src/sagemaker/mlops/feature_store/ingestion_manager_pandas.py b/sagemaker-mlops/src/sagemaker/mlops/feature_store/ingestion_manager_pandas.py index 60d022dab1..4d7b4e5375 100644 --- a/sagemaker-mlops/src/sagemaker/mlops/feature_store/ingestion_manager_pandas.py +++ b/sagemaker-mlops/src/sagemaker/mlops/feature_store/ingestion_manager_pandas.py @@ -6,13 +6,12 @@ import signal from concurrent.futures import ThreadPoolExecutor, as_completed from dataclasses import dataclass, field -from multiprocessing.pool import AsyncResult +from multiprocessing import Pool from typing import Any, Dict, Iterable, List, Sequence, Union import pandas as pd from pandas import DataFrame from pandas.api.types import is_list_like -from pathos.multiprocessing import ProcessingPool from sagemaker.core.resources import FeatureGroup as CoreFeatureGroup from sagemaker.core.shapes import FeatureValue @@ -54,8 +53,8 @@ class IngestionManagerPandas: feature_definitions: Dict[str, Dict[Any, Any]] max_workers: int = 1 max_processes: int = 1 - _async_result: AsyncResult = field(default=None, init=False) - _processing_pool: ProcessingPool = field(default=None, init=False) + _async_result: Any = field(default=None, init=False) + _processing_pool: Pool = field(default=None, init=False) _failed_indices: List[int] = field(default_factory=list, init=False) @property @@ -100,12 +99,11 @@ def wait(self, timeout: Union[int, float] = None): results = self._async_result.get(timeout=timeout) except KeyboardInterrupt as e: self._processing_pool.terminate() - self._processing_pool.close() - self._processing_pool.clear() + self._processing_pool.join() raise e else: self._processing_pool.close() - self._processing_pool.clear() + self._processing_pool.join() self._failed_indices = [idx for failed in results for idx in failed] @@ -170,11 +168,10 @@ def _run_multi_process( def init_worker(): signal.signal(signal.SIGINT, signal.SIG_IGN) - self._processing_pool = ProcessingPool(self.max_processes, init_worker) - self._processing_pool.restart(force=True) + self._processing_pool = Pool(self.max_processes, init_worker) - self._async_result = self._processing_pool.amap( - lambda x: IngestionManagerPandas._run_multi_threaded(*x), + self._async_result = self._processing_pool.starmap_async( + IngestionManagerPandas._run_multi_threaded, args, ) diff --git a/sagemaker-mlops/tests/__init__.py b/sagemaker-mlops/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sagemaker-mlops/tests/unit/__init__.py b/sagemaker-mlops/tests/unit/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sagemaker-mlops/tests/unit/sagemaker/__init__.py b/sagemaker-mlops/tests/unit/sagemaker/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sagemaker-mlops/tests/unit/sagemaker/mlops/__init__.py b/sagemaker-mlops/tests/unit/sagemaker/mlops/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/__init__.py b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/__init__.py new file mode 100644 index 0000000000..f34bf7d447 --- /dev/null +++ b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/__init__.py @@ -0,0 +1,2 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 diff --git a/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/conftest.py b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/conftest.py new file mode 100644 index 0000000000..9b2ec55895 --- /dev/null +++ b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/conftest.py @@ -0,0 +1,80 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 +"""Conftest for feature_store tests.""" +import pytest +from unittest.mock import Mock, MagicMock +import pandas as pd +import numpy as np + + +@pytest.fixture +def mock_session(): + """Create a mock Session.""" + session = Mock() + session.boto_session = Mock() + session.boto_region_name = "us-west-2" + session.sagemaker_client = Mock() + session.sagemaker_runtime_client = Mock() + session.sagemaker_featurestore_runtime_client = Mock() + return session + + +@pytest.fixture +def sample_dataframe(): + """Create a sample DataFrame for testing.""" + return pd.DataFrame({ + "id": pd.Series([1, 2, 3, 4, 5], dtype="int64"), + "value": pd.Series([1.1, 2.2, 3.3, 4.4, 5.5], dtype="float64"), + "name": pd.Series(["a", "b", "c", "d", "e"], dtype="string"), + "event_time": pd.Series( + ["2024-01-01T00:00:00Z"] * 5, + dtype="string" + ), + }) + + +@pytest.fixture +def dataframe_with_collections(): + """Create a DataFrame with collection type columns.""" + return pd.DataFrame({ + "id": pd.Series([1, 2, 3], dtype="int64"), + "tags": pd.Series([["a", "b"], ["c"], ["d", "e", "f"]], dtype="object"), + "scores": pd.Series([[1.0, 2.0], [3.0], [4.0, 5.0]], dtype="object"), + "event_time": pd.Series(["2024-01-01"] * 3, dtype="string"), + }) + + +@pytest.fixture +def feature_definitions_dict(): + """Create a feature definitions dictionary.""" + return { + "id": {"FeatureName": "id", "FeatureType": "Integral"}, + "value": {"FeatureName": "value", "FeatureType": "Fractional"}, + "name": {"FeatureName": "name", "FeatureType": "String"}, + "event_time": {"FeatureName": "event_time", "FeatureType": "String"}, + } + + +@pytest.fixture +def mock_feature_group(): + """Create a mock FeatureGroup from core.""" + fg = MagicMock() + fg.feature_group_name = "test-feature-group" + fg.record_identifier_feature_name = "id" + fg.event_time_feature_name = "event_time" + fg.feature_definitions = [ + MagicMock(feature_name="id", feature_type="Integral"), + MagicMock(feature_name="value", feature_type="Fractional"), + MagicMock(feature_name="name", feature_type="String"), + MagicMock(feature_name="event_time", feature_type="String"), + ] + fg.offline_store_config = MagicMock() + fg.offline_store_config.s3_storage_config.s3_uri = "s3://bucket/prefix" + fg.offline_store_config.s3_storage_config.resolved_output_s3_uri = "s3://bucket/prefix/resolved" + fg.offline_store_config.data_catalog_config.catalog = "AwsDataCatalog" + fg.offline_store_config.data_catalog_config.database = "sagemaker_featurestore" + fg.offline_store_config.data_catalog_config.table_name = "test_feature_group" + fg.offline_store_config.data_catalog_config.disable_glue_table_creation = False + fg.online_store_config = MagicMock() + fg.online_store_config.enable_online_store = True + return fg diff --git a/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_athena_query.py b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_athena_query.py new file mode 100644 index 0000000000..2fed784208 --- /dev/null +++ b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_athena_query.py @@ -0,0 +1,113 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 +"""Unit tests for athena_query.py""" +import os +import pytest +from unittest.mock import Mock, patch, MagicMock +import pandas as pd + +from sagemaker.mlops.feature_store.athena_query import AthenaQuery + + +class TestAthenaQuery: + @pytest.fixture + def mock_session(self): + session = Mock() + session.boto_session.client.return_value = Mock() + session.boto_region_name = "us-west-2" + return session + + @pytest.fixture + def athena_query(self, mock_session): + return AthenaQuery( + catalog="AwsDataCatalog", + database="sagemaker_featurestore", + table_name="my_feature_group", + sagemaker_session=mock_session, + ) + + def test_initialization(self, athena_query): + assert athena_query.catalog == "AwsDataCatalog" + assert athena_query.database == "sagemaker_featurestore" + assert athena_query.table_name == "my_feature_group" + assert athena_query._current_query_execution_id is None + + @patch("sagemaker.mlops.feature_store.athena_query.start_query_execution") + def test_run_starts_query(self, mock_start, athena_query): + mock_start.return_value = {"QueryExecutionId": "query-123"} + + result = athena_query.run( + query_string="SELECT * FROM table", + output_location="s3://bucket/output", + ) + + assert result == "query-123" + assert athena_query._current_query_execution_id == "query-123" + assert athena_query._result_bucket == "bucket" + assert athena_query._result_file_prefix == "output" + + @patch("sagemaker.mlops.feature_store.athena_query.start_query_execution") + def test_run_with_kms_key(self, mock_start, athena_query): + mock_start.return_value = {"QueryExecutionId": "query-123"} + + athena_query.run( + query_string="SELECT * FROM table", + output_location="s3://bucket/output", + kms_key="arn:aws:kms:us-west-2:123:key/abc", + ) + + mock_start.assert_called_once() + call_kwargs = mock_start.call_args[1] + assert call_kwargs["kms_key"] == "arn:aws:kms:us-west-2:123:key/abc" + + @patch("sagemaker.mlops.feature_store.athena_query.wait_for_athena_query") + def test_wait_calls_helper(self, mock_wait, athena_query): + athena_query._current_query_execution_id = "query-123" + + athena_query.wait() + + mock_wait.assert_called_once_with(athena_query.sagemaker_session, "query-123") + + @patch("sagemaker.mlops.feature_store.athena_query.get_query_execution") + def test_get_query_execution(self, mock_get, athena_query): + athena_query._current_query_execution_id = "query-123" + mock_get.return_value = {"QueryExecution": {"Status": {"State": "SUCCEEDED"}}} + + result = athena_query.get_query_execution() + + assert result["QueryExecution"]["Status"]["State"] == "SUCCEEDED" + + @patch("sagemaker.mlops.feature_store.athena_query.get_query_execution") + @patch("sagemaker.mlops.feature_store.athena_query.download_athena_query_result") + @patch("pandas.read_csv") + @patch("os.path.join") + def test_as_dataframe_success(self, mock_join, mock_read_csv, mock_download, mock_get, athena_query): + athena_query._current_query_execution_id = "query-123" + athena_query._result_bucket = "bucket" + athena_query._result_file_prefix = "prefix" + + mock_get.return_value = {"QueryExecution": {"Status": {"State": "SUCCEEDED"}}} + mock_join.return_value = "/tmp/query-123.csv" + mock_read_csv.return_value = pd.DataFrame({"col": [1, 2, 3]}) + + with patch("tempfile.gettempdir", return_value="/tmp"): + with patch("os.remove"): + df = athena_query.as_dataframe() + + assert len(df) == 3 + + @patch("sagemaker.mlops.feature_store.athena_query.get_query_execution") + def test_as_dataframe_raises_when_running(self, mock_get, athena_query): + athena_query._current_query_execution_id = "query-123" + mock_get.return_value = {"QueryExecution": {"Status": {"State": "RUNNING"}}} + + with pytest.raises(RuntimeError, match="still executing"): + athena_query.as_dataframe() + + @patch("sagemaker.mlops.feature_store.athena_query.get_query_execution") + def test_as_dataframe_raises_when_failed(self, mock_get, athena_query): + athena_query._current_query_execution_id = "query-123" + mock_get.return_value = {"QueryExecution": {"Status": {"State": "FAILED"}}} + + with pytest.raises(RuntimeError, match="failed"): + athena_query.as_dataframe() diff --git a/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_dataset_builder.py b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_dataset_builder.py new file mode 100644 index 0000000000..254fb0e196 --- /dev/null +++ b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_dataset_builder.py @@ -0,0 +1,345 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 +"""Unit tests for dataset_builder.py""" +import datetime +import pytest +from unittest.mock import Mock, patch, MagicMock +import pandas as pd + +from sagemaker.mlops.feature_store import FeatureGroup +from sagemaker.mlops.feature_store.dataset_builder import ( + DatasetBuilder, + FeatureGroupToBeMerged, + TableType, + JoinTypeEnum, + JoinComparatorEnum, + construct_feature_group_to_be_merged, +) +from sagemaker.mlops.feature_store.feature_definition import ( + FeatureDefinition, + FeatureTypeEnum, +) + + +class TestTableType: + def test_feature_group_value(self): + assert TableType.FEATURE_GROUP.value == "FeatureGroup" + + def test_data_frame_value(self): + assert TableType.DATA_FRAME.value == "DataFrame" + + +class TestJoinTypeEnum: + def test_inner_join(self): + assert JoinTypeEnum.INNER_JOIN.value == "JOIN" + + def test_left_join(self): + assert JoinTypeEnum.LEFT_JOIN.value == "LEFT JOIN" + + def test_right_join(self): + assert JoinTypeEnum.RIGHT_JOIN.value == "RIGHT JOIN" + + def test_full_join(self): + assert JoinTypeEnum.FULL_JOIN.value == "FULL JOIN" + + def test_cross_join(self): + assert JoinTypeEnum.CROSS_JOIN.value == "CROSS JOIN" + + +class TestJoinComparatorEnum: + def test_equals(self): + assert JoinComparatorEnum.EQUALS.value == "=" + + def test_greater_than(self): + assert JoinComparatorEnum.GREATER_THAN.value == ">" + + def test_less_than(self): + assert JoinComparatorEnum.LESS_THAN.value == "<" + + +class TestFeatureGroupToBeMerged: + def test_initialization(self): + fg = FeatureGroupToBeMerged( + features=["id", "value"], + included_feature_names=["id", "value"], + projected_feature_names=["id", "value"], + catalog="AwsDataCatalog", + database="sagemaker_featurestore", + table_name="my_table", + record_identifier_feature_name="id", + event_time_identifier_feature=FeatureDefinition( + feature_name="event_time", + feature_type="String", + ), + ) + + assert fg.features == ["id", "value"] + assert fg.catalog == "AwsDataCatalog" + assert fg.table_name == "my_table" + assert fg.join_type == JoinTypeEnum.INNER_JOIN + assert fg.join_comparator == JoinComparatorEnum.EQUALS + + def test_custom_join_settings(self): + fg = FeatureGroupToBeMerged( + features=["id"], + included_feature_names=["id"], + projected_feature_names=["id"], + catalog="AwsDataCatalog", + database="db", + table_name="table", + record_identifier_feature_name="id", + event_time_identifier_feature=FeatureDefinition( + feature_name="ts", + feature_type="String", + ), + join_type=JoinTypeEnum.LEFT_JOIN, + join_comparator=JoinComparatorEnum.GREATER_THAN, + ) + + assert fg.join_type == JoinTypeEnum.LEFT_JOIN + assert fg.join_comparator == JoinComparatorEnum.GREATER_THAN + + +class TestConstructFeatureGroupToBeMerged: + @patch("sagemaker.mlops.feature_store.dataset_builder.FeatureGroup") + def test_constructs_from_feature_group(self, mock_fg_class): + mock_fg = MagicMock() + mock_fg.feature_group_name = "test-fg" + mock_fg.record_identifier_feature_name = "id" + mock_fg.event_time_feature_name = "event_time" + mock_fg.feature_definitions = [ + MagicMock(feature_name="id", feature_type="Integral"), + MagicMock(feature_name="value", feature_type="Fractional"), + MagicMock(feature_name="event_time", feature_type="String"), + ] + mock_fg.offline_store_config.data_catalog_config.catalog = "MyCatalog" + mock_fg.offline_store_config.data_catalog_config.database = "MyDatabase" + mock_fg.offline_store_config.data_catalog_config.table_name = "MyTable" + mock_fg.offline_store_config.data_catalog_config.disable_glue_table_creation = False + mock_fg_class.get.return_value = mock_fg + + target_fg = MagicMock() + target_fg.feature_group_name = "test-fg" + + result = construct_feature_group_to_be_merged( + target_feature_group=target_fg, + included_feature_names=["id", "value"], + ) + + assert result.table_name == "MyTable" + assert result.database == "MyDatabase" + assert result.record_identifier_feature_name == "id" + assert result.table_type == TableType.FEATURE_GROUP + + @patch("sagemaker.mlops.feature_store.dataset_builder.FeatureGroup") + def test_raises_when_no_metastore(self, mock_fg_class): + mock_fg = MagicMock() + mock_fg.feature_group_name = "test-fg" + mock_fg.offline_store_config = None + mock_fg_class.get.return_value = mock_fg + + target_fg = MagicMock() + target_fg.feature_group_name = "test-fg" + + with pytest.raises(RuntimeError, match="No metastore"): + construct_feature_group_to_be_merged(target_fg, None) + + +class TestDatasetBuilder: + @pytest.fixture + def mock_session(self): + return Mock() + + @pytest.fixture + def sample_dataframe(self): + return pd.DataFrame({ + "id": [1, 2, 3], + "value": [1.1, 2.2, 3.3], + "event_time": ["2024-01-01", "2024-01-02", "2024-01-03"], + }) + + def test_initialization_with_dataframe(self, mock_session, sample_dataframe): + builder = DatasetBuilder( + _sagemaker_session=mock_session, + _base=sample_dataframe, + _output_path="s3://bucket/output", + _record_identifier_feature_name="id", + _event_time_identifier_feature_name="event_time", + ) + + assert builder._output_path == "s3://bucket/output" + assert builder._record_identifier_feature_name == "id" + + def test_fluent_api_point_in_time(self, mock_session, sample_dataframe): + builder = DatasetBuilder( + _sagemaker_session=mock_session, + _base=sample_dataframe, + _output_path="s3://bucket/output", + _record_identifier_feature_name="id", + _event_time_identifier_feature_name="event_time", + ) + + result = builder.point_in_time_accurate_join() + + assert result is builder + assert builder._point_in_time_accurate_join is True + + def test_fluent_api_include_duplicated(self, mock_session, sample_dataframe): + builder = DatasetBuilder( + _sagemaker_session=mock_session, + _base=sample_dataframe, + _output_path="s3://bucket/output", + _record_identifier_feature_name="id", + _event_time_identifier_feature_name="event_time", + ) + + result = builder.include_duplicated_records() + + assert result is builder + assert builder._include_duplicated_records is True + + def test_fluent_api_include_deleted(self, mock_session, sample_dataframe): + builder = DatasetBuilder( + _sagemaker_session=mock_session, + _base=sample_dataframe, + _output_path="s3://bucket/output", + _record_identifier_feature_name="id", + _event_time_identifier_feature_name="event_time", + ) + + result = builder.include_deleted_records() + + assert result is builder + assert builder._include_deleted_records is True + + def test_fluent_api_number_of_recent_records(self, mock_session, sample_dataframe): + builder = DatasetBuilder( + _sagemaker_session=mock_session, + _base=sample_dataframe, + _output_path="s3://bucket/output", + _record_identifier_feature_name="id", + _event_time_identifier_feature_name="event_time", + ) + + result = builder.with_number_of_recent_records_by_record_identifier(5) + + assert result is builder + assert builder._number_of_recent_records == 5 + + def test_fluent_api_number_of_records(self, mock_session, sample_dataframe): + builder = DatasetBuilder( + _sagemaker_session=mock_session, + _base=sample_dataframe, + _output_path="s3://bucket/output", + _record_identifier_feature_name="id", + _event_time_identifier_feature_name="event_time", + ) + + result = builder.with_number_of_records_from_query_results(100) + + assert result is builder + assert builder._number_of_records == 100 + + def test_fluent_api_as_of(self, mock_session, sample_dataframe): + builder = DatasetBuilder( + _sagemaker_session=mock_session, + _base=sample_dataframe, + _output_path="s3://bucket/output", + _record_identifier_feature_name="id", + _event_time_identifier_feature_name="event_time", + ) + + timestamp = datetime.datetime(2024, 1, 15, 12, 0, 0) + result = builder.as_of(timestamp) + + assert result is builder + assert builder._write_time_ending_timestamp == timestamp + + def test_fluent_api_event_time_range(self, mock_session, sample_dataframe): + builder = DatasetBuilder( + _sagemaker_session=mock_session, + _base=sample_dataframe, + _output_path="s3://bucket/output", + _record_identifier_feature_name="id", + _event_time_identifier_feature_name="event_time", + ) + + start = datetime.datetime(2024, 1, 1) + end = datetime.datetime(2024, 1, 31) + result = builder.with_event_time_range(start, end) + + assert result is builder + assert builder._event_time_starting_timestamp == start + assert builder._event_time_ending_timestamp == end + + @patch.object(DatasetBuilder, "_run_query") + @patch("sagemaker.mlops.feature_store.dataset_builder.construct_feature_group_to_be_merged") + def test_with_feature_group(self, mock_construct, mock_run, mock_session, sample_dataframe): + mock_fg_to_merge = MagicMock() + mock_construct.return_value = mock_fg_to_merge + + builder = DatasetBuilder( + _sagemaker_session=mock_session, + _base=sample_dataframe, + _output_path="s3://bucket/output", + _record_identifier_feature_name="id", + _event_time_identifier_feature_name="event_time", + ) + + mock_fg = MagicMock() + result = builder.with_feature_group(mock_fg, target_feature_name_in_base="id") + + assert result is builder + assert len(builder._feature_groups_to_be_merged) == 1 + + +class TestDatasetBuilderCreate: + @pytest.fixture + def mock_session(self): + return Mock() + + def test_create_with_feature_group(self, mock_session): + mock_fg = MagicMock(spec=FeatureGroup) + builder = DatasetBuilder.create( + base=mock_fg, + output_path="s3://bucket/output", + session=mock_session, + ) + assert builder._base == mock_fg + assert builder._output_path == "s3://bucket/output" + + def test_create_with_dataframe(self, mock_session): + df = pd.DataFrame({"id": [1], "value": [10]}) + builder = DatasetBuilder.create( + base=df, + output_path="s3://bucket/output", + session=mock_session, + record_identifier_feature_name="id", + event_time_identifier_feature_name="event_time", + ) + assert builder._record_identifier_feature_name == "id" + + def test_create_with_dataframe_requires_identifiers(self, mock_session): + df = pd.DataFrame({"id": [1], "value": [10]}) + with pytest.raises(ValueError, match="record_identifier_feature_name"): + DatasetBuilder.create( + base=df, + output_path="s3://bucket/output", + session=mock_session, + ) + + +class TestDatasetBuilderValidation: + @pytest.fixture + def mock_session(self): + return Mock() + + def test_to_csv_raises_for_invalid_base(self, mock_session): + builder = DatasetBuilder( + _sagemaker_session=mock_session, + _base="invalid", # Not DataFrame or FeatureGroup + _output_path="s3://bucket/output", + ) + + with pytest.raises(ValueError, match="must be either"): + builder.to_csv_file() diff --git a/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_feature_definition.py b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_feature_definition.py new file mode 100644 index 0000000000..299868b5d2 --- /dev/null +++ b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_feature_definition.py @@ -0,0 +1,126 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 +"""Unit tests for feature_definition.py""" +import pytest + +from sagemaker.mlops.feature_store.feature_definition import ( + FeatureDefinition, + FeatureTypeEnum, + CollectionTypeEnum, + IntegralFeatureDefinition, + FractionalFeatureDefinition, + StringFeatureDefinition, + VectorCollectionType, + ListCollectionType, + SetCollectionType, +) + + +class TestFeatureTypeEnum: + def test_fractional_value(self): + assert FeatureTypeEnum.FRACTIONAL.value == "Fractional" + + def test_integral_value(self): + assert FeatureTypeEnum.INTEGRAL.value == "Integral" + + def test_string_value(self): + assert FeatureTypeEnum.STRING.value == "String" + + +class TestCollectionTypeEnum: + def test_list_value(self): + assert CollectionTypeEnum.LIST.value == "List" + + def test_set_value(self): + assert CollectionTypeEnum.SET.value == "Set" + + def test_vector_value(self): + assert CollectionTypeEnum.VECTOR.value == "Vector" + + +class TestCollectionTypes: + def test_list_collection_type(self): + collection = ListCollectionType() + assert collection.collection_type == "List" + assert collection.collection_config is None + + def test_set_collection_type(self): + collection = SetCollectionType() + assert collection.collection_type == "Set" + assert collection.collection_config is None + + def test_vector_collection_type(self): + collection = VectorCollectionType(dimension=128) + assert collection.collection_type == "Vector" + assert collection.collection_config is not None + assert collection.collection_config.vector_config.dimension == 128 + + +class TestFeatureDefinitionFactories: + def test_integral_feature_definition(self): + definition = IntegralFeatureDefinition(feature_name="my_int_feature") + assert definition.feature_name == "my_int_feature" + assert definition.feature_type == "Integral" + assert definition.collection_type is None + + def test_fractional_feature_definition(self): + definition = FractionalFeatureDefinition(feature_name="my_float_feature") + assert definition.feature_name == "my_float_feature" + assert definition.feature_type == "Fractional" + assert definition.collection_type is None + + def test_string_feature_definition(self): + definition = StringFeatureDefinition(feature_name="my_string_feature") + assert definition.feature_name == "my_string_feature" + assert definition.feature_type == "String" + assert definition.collection_type is None + + def test_integral_with_list_collection(self): + definition = IntegralFeatureDefinition( + feature_name="my_int_list", + collection_type=ListCollectionType(), + ) + assert definition.feature_name == "my_int_list" + assert definition.feature_type == "Integral" + assert definition.collection_type == "List" + + def test_string_with_set_collection(self): + definition = StringFeatureDefinition( + feature_name="my_string_set", + collection_type=SetCollectionType(), + ) + assert definition.feature_name == "my_string_set" + assert definition.feature_type == "String" + assert definition.collection_type == "Set" + + def test_fractional_with_vector_collection(self): + definition = FractionalFeatureDefinition( + feature_name="my_embedding", + collection_type=VectorCollectionType(dimension=256), + ) + assert definition.feature_name == "my_embedding" + assert definition.feature_type == "Fractional" + assert definition.collection_type == "Vector" + assert definition.collection_config.vector_config.dimension == 256 + + +class TestFeatureDefinitionSerialization: + """Test that FeatureDefinition can be serialized (Pydantic model_dump).""" + + def test_simple_definition_serialization(self): + definition = IntegralFeatureDefinition(feature_name="id") + # Pydantic model - use model_dump + data = definition.model_dump(exclude_none=True) + assert data["feature_name"] == "id" + assert data["feature_type"] == "Integral" + + def test_collection_definition_serialization(self): + definition = FractionalFeatureDefinition( + feature_name="vector", + collection_type=VectorCollectionType(dimension=10), + ) + data = definition.model_dump(exclude_none=True) + assert data["feature_name"] == "vector" + assert data["feature_type"] == "Fractional" + assert data["collection_type"] == "Vector" + assert data["collection_config"]["vector_config"]["dimension"] == 10 diff --git a/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_feature_utils.py b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_feature_utils.py new file mode 100644 index 0000000000..a9d5408bf6 --- /dev/null +++ b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_feature_utils.py @@ -0,0 +1,202 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 +"""Unit tests for feature_utils.py""" +import pytest +from unittest.mock import Mock, patch, MagicMock +import pandas as pd +import numpy as np + +from sagemaker.mlops.feature_store.feature_utils import ( + load_feature_definitions_from_dataframe, + as_hive_ddl, + create_athena_query, + ingest_dataframe, + get_session_from_role, + _is_collection_column, + _generate_feature_definition, +) +from sagemaker.mlops.feature_store.feature_definition import ( + FeatureDefinition, + ListCollectionType, +) + + +class TestLoadFeatureDefinitionsFromDataframe: + @pytest.fixture + def sample_dataframe(self): + return pd.DataFrame({ + "id": pd.Series([1, 2, 3], dtype="int64"), + "value": pd.Series([1.1, 2.2, 3.3], dtype="float64"), + "name": pd.Series(["a", "b", "c"], dtype="string"), + }) + + def test_infers_integral_type(self, sample_dataframe): + defs = load_feature_definitions_from_dataframe(sample_dataframe) + id_def = next(d for d in defs if d.feature_name == "id") + assert id_def.feature_type == "Integral" + + def test_infers_fractional_type(self, sample_dataframe): + defs = load_feature_definitions_from_dataframe(sample_dataframe) + value_def = next(d for d in defs if d.feature_name == "value") + assert value_def.feature_type == "Fractional" + + def test_infers_string_type(self, sample_dataframe): + defs = load_feature_definitions_from_dataframe(sample_dataframe) + name_def = next(d for d in defs if d.feature_name == "name") + assert name_def.feature_type == "String" + + def test_returns_correct_count(self, sample_dataframe): + defs = load_feature_definitions_from_dataframe(sample_dataframe) + assert len(defs) == 3 + + def test_collection_type_with_in_memory_storage(self): + df = pd.DataFrame({ + "id": pd.Series([1, 2], dtype="int64"), + "tags": pd.Series([["a", "b"], ["c"]], dtype="object"), + }) + defs = load_feature_definitions_from_dataframe(df, online_storage_type="InMemory") + tags_def = next(d for d in defs if d.feature_name == "tags") + assert tags_def.collection_type == "List" + + +class TestIsCollectionColumn: + def test_list_column_returns_true(self): + series = pd.Series([[1, 2], [3, 4], [5]]) + assert _is_collection_column(series) == True + + def test_scalar_column_returns_false(self): + series = pd.Series([1, 2, 3]) + assert _is_collection_column(series) == False + + def test_empty_series(self): + series = pd.Series([], dtype="object") + assert _is_collection_column(series) == False + + +class TestAsHiveDdl: + @patch("sagemaker.mlops.feature_store.feature_utils.CoreFeatureGroup") + def test_generates_ddl_string(self, mock_fg_class): + # Setup mock + mock_fg = MagicMock() + mock_fg.feature_definitions = [ + MagicMock(feature_name="id", feature_type="Integral"), + MagicMock(feature_name="value", feature_type="Fractional"), + MagicMock(feature_name="name", feature_type="String"), + ] + mock_fg.offline_store_config.s3_storage_config.resolved_output_s3_uri = "s3://bucket/prefix" + mock_fg_class.get.return_value = mock_fg + + ddl = as_hive_ddl("my-feature-group") + + assert "CREATE EXTERNAL TABLE" in ddl + assert "my-feature-group" in ddl + assert "id INT" in ddl + assert "value FLOAT" in ddl + assert "name STRING" in ddl + assert "write_time TIMESTAMP" in ddl + assert "event_time TIMESTAMP" in ddl + assert "is_deleted BOOLEAN" in ddl + assert "s3://bucket/prefix" in ddl + + @patch("sagemaker.mlops.feature_store.feature_utils.CoreFeatureGroup") + def test_custom_database_and_table(self, mock_fg_class): + mock_fg = MagicMock() + mock_fg.feature_definitions = [] + mock_fg.offline_store_config.s3_storage_config.resolved_output_s3_uri = "s3://bucket/prefix" + mock_fg_class.get.return_value = mock_fg + + ddl = as_hive_ddl("my-fg", database="custom_db", table_name="custom_table") + + assert "custom_db.custom_table" in ddl + + +class TestCreateAthenaQuery: + @patch("sagemaker.mlops.feature_store.feature_utils.CoreFeatureGroup") + def test_creates_athena_query(self, mock_fg_class): + mock_fg = MagicMock() + mock_fg.offline_store_config.data_catalog_config.catalog = "MyCatalog" + mock_fg.offline_store_config.data_catalog_config.database = "MyDatabase" + mock_fg.offline_store_config.data_catalog_config.table_name = "MyTable" + mock_fg.offline_store_config.data_catalog_config.disable_glue_table_creation = False + mock_fg_class.get.return_value = mock_fg + + session = Mock() + query = create_athena_query("my-fg", session) + + assert query.catalog == "AwsDataCatalog" # disable_glue=False uses default + assert query.database == "MyDatabase" + assert query.table_name == "MyTable" + + @patch("sagemaker.mlops.feature_store.feature_utils.CoreFeatureGroup") + def test_raises_when_no_metastore(self, mock_fg_class): + mock_fg = MagicMock() + mock_fg.offline_store_config = None + mock_fg_class.get.return_value = mock_fg + + session = Mock() + with pytest.raises(RuntimeError, match="No metastore"): + create_athena_query("my-fg", session) + + +class TestIngestDataframe: + @patch("sagemaker.mlops.feature_store.feature_utils.IngestionManagerPandas") + @patch("sagemaker.mlops.feature_store.feature_utils.CoreFeatureGroup") + def test_creates_manager_and_runs(self, mock_fg_class, mock_manager_class): + mock_fg = MagicMock() + mock_fg.feature_definitions = [ + MagicMock(feature_name="id", feature_type="Integral"), + ] + mock_fg_class.get.return_value = mock_fg + + mock_manager = MagicMock() + mock_manager_class.return_value = mock_manager + + df = pd.DataFrame({"id": [1, 2, 3]}) + result = ingest_dataframe("my-fg", df, max_workers=2, max_processes=1) + + mock_manager_class.assert_called_once() + mock_manager.run.assert_called_once() + assert result == mock_manager + + def test_raises_on_invalid_max_workers(self): + df = pd.DataFrame({"id": [1, 2, 3]}) + with pytest.raises(ValueError, match="max_workers"): + ingest_dataframe("my-fg", df, max_workers=0) + + def test_raises_on_invalid_max_processes(self): + df = pd.DataFrame({"id": [1, 2, 3]}) + with pytest.raises(ValueError, match="max_processes"): + ingest_dataframe("my-fg", df, max_processes=-1) + + +class TestGetSessionFromRole: + @patch("sagemaker.mlops.feature_store.feature_utils.boto3") + @patch("sagemaker.mlops.feature_store.feature_utils.Session") + def test_creates_session_without_role(self, mock_session_class, mock_boto3): + mock_boto_session = MagicMock() + mock_boto3.Session.return_value = mock_boto_session + + get_session_from_role(region="us-west-2") + + mock_boto3.Session.assert_called_with(region_name="us-west-2") + mock_session_class.assert_called_once() + + @patch("sagemaker.mlops.feature_store.feature_utils.boto3") + @patch("sagemaker.mlops.feature_store.feature_utils.Session") + def test_assumes_role_when_provided(self, mock_session_class, mock_boto3): + mock_boto_session = MagicMock() + mock_sts = MagicMock() + mock_sts.assume_role.return_value = { + "Credentials": { + "AccessKeyId": "key", + "SecretAccessKey": "secret", + "SessionToken": "token", + } + } + mock_boto_session.client.return_value = mock_sts + mock_boto3.Session.return_value = mock_boto_session + + get_session_from_role(region="us-west-2", assume_role="arn:aws:iam::123:role/MyRole") + + mock_sts.assume_role.assert_called_once() + assert mock_boto3.Session.call_count == 2 # Initial + after assume diff --git a/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_ingestion_manager_pandas.py b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_ingestion_manager_pandas.py new file mode 100644 index 0000000000..2ecf495967 --- /dev/null +++ b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_ingestion_manager_pandas.py @@ -0,0 +1,256 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 +"""Unit tests for ingestion_manager_pandas.py""" +import pytest +from unittest.mock import Mock, patch, MagicMock +import pandas as pd +import numpy as np + +from sagemaker.mlops.feature_store.ingestion_manager_pandas import ( + IngestionManagerPandas, + IngestionError, +) + + +class TestIngestionError: + def test_stores_failed_rows(self): + error = IngestionError([1, 5, 10], "Some rows failed") + assert error.failed_rows == [1, 5, 10] + assert "Some rows failed" in str(error) + + +class TestIngestionManagerPandas: + @pytest.fixture + def feature_definitions(self): + return { + "id": {"FeatureName": "id", "FeatureType": "Integral"}, + "value": {"FeatureName": "value", "FeatureType": "Fractional"}, + "name": {"FeatureName": "name", "FeatureType": "String"}, + } + + @pytest.fixture + def sample_dataframe(self): + return pd.DataFrame({ + "id": [1, 2, 3], + "value": [1.1, 2.2, 3.3], + "name": ["a", "b", "c"], + }) + + @pytest.fixture + def manager(self, feature_definitions): + return IngestionManagerPandas( + feature_group_name="test-fg", + feature_definitions=feature_definitions, + max_workers=1, + max_processes=1, + ) + + def test_initialization(self, manager): + assert manager.feature_group_name == "test-fg" + assert manager.max_workers == 1 + assert manager.max_processes == 1 + assert manager.failed_rows == [] + + def test_failed_rows_property(self, manager): + manager._failed_indices = [1, 2, 3] + assert manager.failed_rows == [1, 2, 3] + + +class TestIngestionManagerHelpers: + def test_is_feature_collection_type_true(self): + feature_defs = { + "tags": {"FeatureName": "tags", "FeatureType": "String", "CollectionType": "List"}, + } + assert IngestionManagerPandas._is_feature_collection_type("tags", feature_defs) is True + + def test_is_feature_collection_type_false(self): + feature_defs = { + "id": {"FeatureName": "id", "FeatureType": "Integral"}, + } + assert IngestionManagerPandas._is_feature_collection_type("id", feature_defs) is False + + def test_is_feature_collection_type_missing(self): + feature_defs = {} + assert IngestionManagerPandas._is_feature_collection_type("unknown", feature_defs) is False + + def test_feature_value_is_not_none_scalar(self): + assert IngestionManagerPandas._feature_value_is_not_none(5) is True + assert IngestionManagerPandas._feature_value_is_not_none(None) is False + assert IngestionManagerPandas._feature_value_is_not_none(np.nan) is False + + def test_feature_value_is_not_none_list(self): + assert IngestionManagerPandas._feature_value_is_not_none([1, 2, 3]) is True + assert IngestionManagerPandas._feature_value_is_not_none([]) is True + assert IngestionManagerPandas._feature_value_is_not_none(None) is False + + def test_convert_to_string_list(self): + result = IngestionManagerPandas._convert_to_string_list([1, 2, 3]) + assert result == ["1", "2", "3"] + + def test_convert_to_string_list_with_none(self): + result = IngestionManagerPandas._convert_to_string_list([1, None, 3]) + assert result == ["1", None, "3"] + + def test_convert_to_string_list_raises_for_non_list(self): + with pytest.raises(ValueError, match="must be an Array"): + IngestionManagerPandas._convert_to_string_list("not a list") + + +class TestIngestionManagerRun: + @pytest.fixture + def feature_definitions(self): + return { + "id": {"FeatureName": "id", "FeatureType": "Integral"}, + "value": {"FeatureName": "value", "FeatureType": "Fractional"}, + } + + @pytest.fixture + def sample_dataframe(self): + return pd.DataFrame({ + "id": [1, 2, 3], + "value": [1.1, 2.2, 3.3], + }) + + @patch.object(IngestionManagerPandas, "_run_single_process_single_thread") + def test_run_single_thread_mode(self, mock_single, feature_definitions, sample_dataframe): + manager = IngestionManagerPandas( + feature_group_name="test-fg", + feature_definitions=feature_definitions, + max_workers=1, + max_processes=1, + ) + + manager.run(sample_dataframe) + + mock_single.assert_called_once() + + @patch.object(IngestionManagerPandas, "_run_multi_process") + def test_run_multi_process_mode(self, mock_multi, feature_definitions, sample_dataframe): + manager = IngestionManagerPandas( + feature_group_name="test-fg", + feature_definitions=feature_definitions, + max_workers=2, + max_processes=2, + ) + + manager.run(sample_dataframe) + + mock_multi.assert_called_once() + + +class TestIngestionManagerIngestRow: + @pytest.fixture + def feature_definitions(self): + return { + "id": {"FeatureName": "id", "FeatureType": "Integral"}, + "name": {"FeatureName": "name", "FeatureType": "String"}, + } + + @pytest.fixture + def collection_feature_definitions(self): + return { + "id": {"FeatureName": "id", "FeatureType": "Integral"}, + "tags": {"FeatureName": "tags", "FeatureType": "String", "CollectionType": "List"}, + } + + def test_ingest_row_success(self, feature_definitions): + df = pd.DataFrame({"id": [1], "name": ["test"]}) + mock_fg = MagicMock() + failed_rows = [] + + for row in df.itertuples(): + IngestionManagerPandas._ingest_row( + data_frame=df, + row=row, + feature_group=mock_fg, + feature_definitions=feature_definitions, + failed_rows=failed_rows, + target_stores=None, + ) + + mock_fg.put_record.assert_called_once() + assert len(failed_rows) == 0 + + def test_ingest_row_with_collection_type(self, collection_feature_definitions): + df = pd.DataFrame({ + "id": [1], + "tags": [["tag1", "tag2"]], + }) + mock_fg = MagicMock() + failed_rows = [] + + for row in df.itertuples(): + IngestionManagerPandas._ingest_row( + data_frame=df, + row=row, + feature_group=mock_fg, + feature_definitions=collection_feature_definitions, + failed_rows=failed_rows, + target_stores=None, + ) + + mock_fg.put_record.assert_called_once() + call_args = mock_fg.put_record.call_args + record = call_args[1]["record"] + + # Find the tags feature value + tags_value = next(v for v in record if v.feature_name == "tags") + assert tags_value.value_as_string_list == ["tag1", "tag2"] + + def test_ingest_row_failure_appends_to_failed(self, feature_definitions): + df = pd.DataFrame({"id": [1], "name": ["test"]}) + mock_fg = MagicMock() + mock_fg.put_record.side_effect = Exception("API Error") + failed_rows = [] + + for row in df.itertuples(): + IngestionManagerPandas._ingest_row( + data_frame=df, + row=row, + feature_group=mock_fg, + feature_definitions=feature_definitions, + failed_rows=failed_rows, + target_stores=None, + ) + + assert len(failed_rows) == 1 + assert failed_rows[0] == 0 # Index of failed row + + def test_ingest_row_with_target_stores(self, feature_definitions): + df = pd.DataFrame({"id": [1], "name": ["test"]}) + mock_fg = MagicMock() + failed_rows = [] + + for row in df.itertuples(): + IngestionManagerPandas._ingest_row( + data_frame=df, + row=row, + feature_group=mock_fg, + feature_definitions=feature_definitions, + failed_rows=failed_rows, + target_stores=["OnlineStore"], + ) + + call_args = mock_fg.put_record.call_args + assert call_args[1]["target_stores"] == ["OnlineStore"] + + def test_ingest_row_skips_none_values(self, feature_definitions): + df = pd.DataFrame({"id": [1], "name": [None]}) + mock_fg = MagicMock() + failed_rows = [] + + for row in df.itertuples(): + IngestionManagerPandas._ingest_row( + data_frame=df, + row=row, + feature_group=mock_fg, + feature_definitions=feature_definitions, + failed_rows=failed_rows, + target_stores=None, + ) + + call_args = mock_fg.put_record.call_args + record = call_args[1]["record"] + # Only id should be in record, name is None + assert len(record) == 1 + assert record[0].feature_name == "id" diff --git a/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_inputs.py b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_inputs.py new file mode 100644 index 0000000000..44e3ec6085 --- /dev/null +++ b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_inputs.py @@ -0,0 +1,109 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 +"""Unit tests for inputs.py (enums).""" +import pytest + +from sagemaker.mlops.feature_store.inputs import ( + TargetStoreEnum, + OnlineStoreStorageTypeEnum, + TableFormatEnum, + ResourceEnum, + SearchOperatorEnum, + SortOrderEnum, + FilterOperatorEnum, + DeletionModeEnum, + ExpirationTimeResponseEnum, + ThroughputModeEnum, +) + + +class TestTargetStoreEnum: + def test_online_store(self): + assert TargetStoreEnum.ONLINE_STORE.value == "OnlineStore" + + def test_offline_store(self): + assert TargetStoreEnum.OFFLINE_STORE.value == "OfflineStore" + + +class TestOnlineStoreStorageTypeEnum: + def test_standard(self): + assert OnlineStoreStorageTypeEnum.STANDARD.value == "Standard" + + def test_in_memory(self): + assert OnlineStoreStorageTypeEnum.IN_MEMORY.value == "InMemory" + + +class TestTableFormatEnum: + def test_glue(self): + assert TableFormatEnum.GLUE.value == "Glue" + + def test_iceberg(self): + assert TableFormatEnum.ICEBERG.value == "Iceberg" + + +class TestResourceEnum: + def test_feature_group(self): + assert ResourceEnum.FEATURE_GROUP.value == "FeatureGroup" + + def test_feature_metadata(self): + assert ResourceEnum.FEATURE_METADATA.value == "FeatureMetadata" + + +class TestSearchOperatorEnum: + def test_and(self): + assert SearchOperatorEnum.AND.value == "And" + + def test_or(self): + assert SearchOperatorEnum.OR.value == "Or" + + +class TestSortOrderEnum: + def test_ascending(self): + assert SortOrderEnum.ASCENDING.value == "Ascending" + + def test_descending(self): + assert SortOrderEnum.DESCENDING.value == "Descending" + + +class TestFilterOperatorEnum: + def test_equals(self): + assert FilterOperatorEnum.EQUALS.value == "Equals" + + def test_not_equals(self): + assert FilterOperatorEnum.NOT_EQUALS.value == "NotEquals" + + def test_greater_than(self): + assert FilterOperatorEnum.GREATER_THAN.value == "GreaterThan" + + def test_contains(self): + assert FilterOperatorEnum.CONTAINS.value == "Contains" + + def test_exists(self): + assert FilterOperatorEnum.EXISTS.value == "Exists" + + def test_in(self): + assert FilterOperatorEnum.IN.value == "In" + + +class TestDeletionModeEnum: + def test_soft_delete(self): + assert DeletionModeEnum.SOFT_DELETE.value == "SoftDelete" + + def test_hard_delete(self): + assert DeletionModeEnum.HARD_DELETE.value == "HardDelete" + + +class TestExpirationTimeResponseEnum: + def test_disabled(self): + assert ExpirationTimeResponseEnum.DISABLED.value == "Disabled" + + def test_enabled(self): + assert ExpirationTimeResponseEnum.ENABLED.value == "Enabled" + + +class TestThroughputModeEnum: + def test_on_demand(self): + assert ThroughputModeEnum.ON_DEMAND.value == "OnDemand" + + def test_provisioned(self): + assert ThroughputModeEnum.PROVISIONED.value == "Provisioned" From f38579455720e0a70a5b7d4dc215e8e095489b18 Mon Sep 17 00:00:00 2001 From: Basssem Halim Date: Mon, 26 Jan 2026 16:32:37 -0800 Subject: [PATCH 03/10] feat(feature_store): Add Lake Formation support to Feature Group - Add LakeFormationConfig class to configure Lake Formation governance on offline stores - Implement FeatureGroup subclass with Lake Formation integration capabilities - Add helper methods for S3 URI/ARN conversion and Lake Formation role management - Add S3 deny policy generation for Lake Formation access control - Implement Lake Formation resource registration and S3 bucket policy setup - Add integration tests for Lake Formation feature store workflows - Add unit tests for Lake Formation configuration and policy generation - Update feature_store module exports to include FeatureGroup and LakeFormationConfig - Update API documentation to include Feature Store section in sagemaker_mlops.rst - Enable fine-grained access control for feature store offline stores using AWS Lake Formation --- docs/api/sagemaker_mlops.rst | 8 + .../sagemaker/mlops/feature_store/__init__.py | 6 +- .../mlops/feature_store/feature_group.py | 711 ++++++ .../integ/test_featureStore_lakeformation.py | 660 +++++ .../mlops/feature_store/test_lakeformation.py | 2141 +++++++++++++++++ 5 files changed, 3525 insertions(+), 1 deletion(-) create mode 100644 sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py create mode 100644 sagemaker-mlops/tests/integ/test_featureStore_lakeformation.py create mode 100644 sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_lakeformation.py diff --git a/docs/api/sagemaker_mlops.rst b/docs/api/sagemaker_mlops.rst index f67879111d..d9f911068e 100644 --- a/docs/api/sagemaker_mlops.rst +++ b/docs/api/sagemaker_mlops.rst @@ -21,6 +21,14 @@ Workflow Management :undoc-members: :show-inheritance: +Feature Store +------------- + +.. automodule:: sagemaker.mlops.feature_store + :members: + :undoc-members: + :show-inheritance: + Local Development ----------------- diff --git a/sagemaker-mlops/src/sagemaker/mlops/feature_store/__init__.py b/sagemaker-mlops/src/sagemaker/mlops/feature_store/__init__.py index f15d6d3845..1b635df2a7 100644 --- a/sagemaker-mlops/src/sagemaker/mlops/feature_store/__init__.py +++ b/sagemaker-mlops/src/sagemaker/mlops/feature_store/__init__.py @@ -2,8 +2,11 @@ # Licensed under the Apache License, Version 2.0 """SageMaker FeatureStore V3 - powered by sagemaker-core.""" +# FeatureGroup with Lake Formation support (local subclass) +from sagemaker.mlops.feature_store.feature_group import FeatureGroup, LakeFormationConfig + # Resources from core -from sagemaker.core.resources import FeatureGroup, FeatureMetadata +from sagemaker.core.resources import FeatureMetadata # Shapes from core (Pydantic - no to_dict() needed) from sagemaker.core.shapes import ( @@ -79,6 +82,7 @@ "FeatureParameter", "FeatureValue", "Filter", + "LakeFormationConfig", "OfflineStoreConfig", "OnlineStoreConfig", "OnlineStoreSecurityConfig", diff --git a/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py b/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py new file mode 100644 index 0000000000..c5fcb9211a --- /dev/null +++ b/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py @@ -0,0 +1,711 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# Licensed under the Apache License, Version 2.0 +"""FeatureGroup with Lake Formation support.""" + +import logging +from typing import List, Optional + +import botocore.exceptions + +from sagemaker.core.resources import FeatureGroup as CoreFeatureGroup +from sagemaker.core.resources import Base +from sagemaker.core.shapes import ( + FeatureDefinition, + OfflineStoreConfig, + OnlineStoreConfig, + Tag, + ThroughputConfig, +) +from sagemaker.core.shapes import Unassigned +from sagemaker.core.helper.pipeline_variable import StrPipeVar +from sagemaker.core.s3.utils import parse_s3_url +from sagemaker.core.common_utils import aws_partition +from boto3 import Session + + +logger = logging.getLogger(__name__) + + +class LakeFormationConfig: + """Configuration for Lake Formation governance on Feature Group offline stores. + + Attributes: + enabled: If True, enables Lake Formation governance for the offline store. + Requires offline_store_config and role_arn to be set on the Feature Group. + use_service_linked_role: Whether to use the Lake Formation service-linked role + for S3 registration. If True, Lake Formation uses its service-linked role. + If False, registration_role_arn must be provided. Default is True. + registration_role_arn: IAM role ARN to use for S3 registration with Lake Formation. + Required when use_service_linked_role is False. This can be different from the + Feature Group's execution role. + show_s3_policy: If True, prints the S3 deny policy to the console after successful + Lake Formation setup. This policy should be added to your S3 bucket to restrict + access to only the allowed principals. Default is False. + """ + + enabled: bool = False + use_service_linked_role: bool = True + registration_role_arn: Optional[str] = None + show_s3_policy: bool = False + + +class FeatureGroup(CoreFeatureGroup): + + # Inherit parent docstring and append our additions + if CoreFeatureGroup.__doc__ and __doc__: + __doc__ = CoreFeatureGroup.__doc__ + + @staticmethod + def _s3_uri_to_arn(s3_uri: str, region: Optional[str] = None) -> str: + """ + Convert S3 URI to S3 ARN format for Lake Formation. + + Args: + s3_uri: S3 URI in format s3://bucket/path or already an ARN + region: AWS region name (e.g., 'us-west-2'). Used to determine the correct + partition for the ARN. If not provided, defaults to 'aws' partition. + + Returns: + S3 ARN in format arn:{partition}:s3:::bucket/path + + Note: + This format is specifically used for Lake Formation resource registration. + The triple colon (:::) after 's3' is correct - S3 ARNs don't include + region or account ID fields. + """ + if s3_uri.startswith("arn:"): + return s3_uri + + # Determine partition based on region + partition = aws_partition(region) if region else "aws" + + bucket, key = parse_s3_url(s3_uri) + # Reconstruct as ARN - key may be empty string + s3_path = f"{bucket}/{key}" if key else bucket + return f"arn:{partition}:s3:::{s3_path}" + + @staticmethod + def _extract_account_id_from_arn(arn: str) -> str: + """ + Extract AWS account ID from an ARN. + + Args: + arn: AWS ARN in format arn:aws:service:region:account:resource + + Returns: + AWS account ID (the 5th colon-separated field) + + Raises: + ValueError: If ARN format is invalid (fewer than 5 colon-separated parts) + """ + parts = arn.split(":") + if len(parts) < 5: + raise ValueError(f"Invalid ARN format: {arn}") + return parts[4] + + @staticmethod + def _get_lake_formation_service_linked_role_arn( + account_id: str, region: Optional[str] = None + ) -> str: + """ + Generate the Lake Formation service-linked role ARN for an account. + + Args: + account_id: AWS account ID + region: AWS region name (e.g., 'us-west-2'). Used to determine the correct + partition for the ARN. If not provided, defaults to 'aws' partition. + + Returns: + Lake Formation service-linked role ARN in format: + arn:{partition}:iam::{account}:role/aws-service-role/lakeformation.amazonaws.com/ + AWSServiceRoleForLakeFormationDataAccess + """ + partition = aws_partition(region) if region else "aws" + return ( + f"arn:{partition}:iam::{account_id}:role/aws-service-role/" + f"lakeformation.amazonaws.com/AWSServiceRoleForLakeFormationDataAccess" + ) + + def _generate_s3_deny_policy( + self, + bucket_name: str, + s3_prefix: str, + lake_formation_role_arn: str, + feature_store_role_arn: str, + ) -> dict: + """ + Generate an S3 deny policy for Lake Formation governance. + + This policy denies S3 access to the offline store data prefix except for + the Lake Formation role and Feature Store execution role. + + Args: + bucket_name: S3 bucket name. + s3_prefix: S3 prefix path (without bucket name). + lake_formation_role_arn: Lake Formation registration role ARN. + feature_store_role_arn: Feature Store execution role ARN. + + Returns: + S3 bucket policy as a dict with valid JSON structure containing: + - Version: "2012-10-17" + - Statement: List with two deny statements: + 1. Deny GetObject, PutObject, DeleteObject on data prefix except allowed principals + 2. Deny ListBucket on bucket with prefix condition except allowed principals + """ + policy = { + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "DenyAllAccessToFeatureStorePrefixExceptAllowedPrincipals", + "Effect": "Deny", + "Principal": "*", + "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"], + "Resource": f"arn:aws:s3:::{bucket_name}/{s3_prefix}/*", + "Condition": { + "StringNotEquals": { + "aws:PrincipalArn": [ + lake_formation_role_arn, + feature_store_role_arn, + ] + } + }, + }, + { + "Sid": "DenyListOnPrefixExceptAllowedPrincipals", + "Effect": "Deny", + "Principal": "*", + "Action": "s3:ListBucket", + "Resource": f"arn:aws:s3:::{bucket_name}", + "Condition": { + "StringLike": {"s3:prefix": f"{s3_prefix}/*"}, + "StringNotEquals": { + "aws:PrincipalArn": [ + lake_formation_role_arn, + feature_store_role_arn, + ] + }, + }, + }, + ], + } + return policy + + def _get_lake_formation_client( + self, + session: Optional[Session] = None, + region: Optional[str] = None, + ): + """ + Get a Lake Formation client. + + Args: + session: Boto3 session. If not provided, a new session will be created. + region: AWS region name. + + Returns: + A boto3 Lake Formation client. + """ + # TODO: don't create w new client for each call + boto_session = session or Session() + return boto_session.client("lakeformation", region_name=region) + + def _register_s3_with_lake_formation( + self, + s3_location: str, + session: Optional[Session] = None, + region: Optional[str] = None, + use_service_linked_role: bool = True, + role_arn: Optional[str] = None, + ) -> bool: + """ + Register an S3 location with Lake Formation. + + Args: + s3_location: S3 URI or ARN to register. + session: Boto3 session. + region: AWS region. If not provided, will be inferred from the session. + use_service_linked_role: Whether to use the Lake Formation service-linked role. + If True, Lake Formation uses its service-linked role for registration. + If False, role_arn must be provided. + role_arn: IAM role ARN to use for registration. Required when + use_service_linked_role is False. + + Returns: + True if registration succeeded or location already registered. + + Raises: + ValueError: If use_service_linked_role is False but role_arn is not provided. + ClientError: If registration fails for unexpected reasons. + """ + if not use_service_linked_role and not role_arn: + raise ValueError("role_arn must be provided when use_service_linked_role is False") + + # Get region from session if not provided + if region is None and session is not None: + region = session.region_name() + + client = self._get_lake_formation_client(session, region) + resource_arn = self._s3_uri_to_arn(s3_location, region) + + try: + register_params = {"ResourceArn": resource_arn} + + if use_service_linked_role: + register_params["UseServiceLinkedRole"] = True + else: + register_params["RoleArn"] = role_arn + + client.register_resource(**register_params) + logger.info(f"Successfully registered S3 location: {resource_arn}") + return True + except botocore.exceptions.ClientError as e: + if e.response["Error"]["Code"] == "AlreadyExistsException": + logger.info(f"S3 location already registered: {resource_arn}") + return True + raise + + def _revoke_iam_allowed_principal( + self, + database_name: str, + table_name: str, + session: Optional[Session] = None, + region: Optional[str] = None, + ) -> bool: + """ + Revoke IAMAllowedPrincipal permissions from a Glue table. + + Args: + database_name: Glue database name. + table_name: Glue table name. + session: Boto3 session. + region: AWS region. If not provided, will be inferred from the session. + + Returns: + True if revocation succeeded or permissions didn't exist. + + Raises: + ClientError: If revocation fails for unexpected reasons. + """ + # Get region from session if not provided + if region is None and session is not None: + region = session.region_name() + + client = self._get_lake_formation_client(session, region) + + try: + client.revoke_permissions( + Principal={"DataLakePrincipalIdentifier": "IAM_ALLOWED_PRINCIPALS"}, + Resource={ + "Table": { + "DatabaseName": database_name, + "Name": table_name, + } + }, + Permissions=["ALL"], + ) + logger.info(f"Revoked IAMAllowedPrincipal from table: {database_name}.{table_name}") + return True + except botocore.exceptions.ClientError as e: + # if the Table doesn't have that permission because the user already revoked it + # then just return True + if e.response["Error"]["Code"] == "InvalidInputException": + logger.info( + f"IAMAllowedPrincipal permissions may not exist on: {database_name}.{table_name}" + ) + return True + raise + + def _grant_lake_formation_permissions( + self, + role_arn: str, + database_name: str, + table_name: str, + session: Optional[Session] = None, + region: Optional[str] = None, + ) -> bool: + """ + Grant permissions to a role on a Glue table via Lake Formation. + + Args: + role_arn: IAM role ARN to grant permissions to. + database_name: Glue database name. + table_name: Glue table name. + session: Boto3 session. + region: AWS region. If not provided, will be inferred from the session. + + Returns: + True if grant succeeded or permissions already exist. + + Raises: + ClientError: If grant fails for unexpected reasons. + """ + # Get region from session if not provided + if region is None and session is not None: + region = session.region_name() + + client = self._get_lake_formation_client(session, region) + permissions = ["SELECT", "INSERT", "DELETE", "DESCRIBE", "ALTER"] + + try: + client.grant_permissions( + Principal={"DataLakePrincipalIdentifier": role_arn}, + Resource={ + "Table": { + "DatabaseName": database_name, + "Name": table_name, + } + }, + Permissions=permissions, + PermissionsWithGrantOption=[], + ) + logger.info(f"Granted permissions to {role_arn} on table: {database_name}.{table_name}") + return True + except botocore.exceptions.ClientError as e: + if e.response["Error"]["Code"] == "InvalidInputException": + logger.info( + f"Permissions may already exist for {role_arn} on: {database_name}.{table_name}" + ) + return True + raise + + @Base.add_validate_call + def enable_lake_formation( + self, + session: Optional[Session] = None, + region: Optional[str] = None, + use_service_linked_role: bool = True, + registration_role_arn: Optional[str] = None, + wait_for_active: bool = False, + show_s3_policy: bool = False, + ) -> dict: + """ + Enable Lake Formation governance for this Feature Group's offline store. + + This method: + 1. Optionally waits for Feature Group to reach 'Created' status + 2. Validates Feature Group status is 'Created' + 3. Registers the offline store S3 location as data lake location + 4. Grants the execution role permissions on the Glue table + 5. Revokes IAMAllowedPrincipal permissions from the Glue table + + The role ARN is automatically extracted from the Feature Group's configuration. + Each phase depends on the success of the previous phase - if any phase fails, + subsequent phases are not executed. + + Parameters: + session: Boto3 session. + region: Region name. + use_service_linked_role: Whether to use the Lake Formation service-linked role + for S3 registration. If True, Lake Formation uses its service-linked role. + If False, registration_role_arn must be provided. Default is True. + registration_role_arn: IAM role ARN to use for S3 registration with Lake Formation. + Required when use_service_linked_role is False. This can be different from the + Feature Group's execution role (role_arn) + wait_for_active: If True, waits for the Feature Group to reach 'Created' status + before enabling Lake Formation. Default is False. + show_s3_policy: If True, prints the S3 deny policy to the console after successful + Lake Formation setup. This policy should be added to your S3 bucket to restrict + access to only the allowed principals. Default is False. + + Returns: + Dict with status of each Lake Formation operation: + - s3_registration: bool + - iam_principal_revoked: bool + - permissions_granted: bool + + Raises: + ValueError: If the Feature Group has no offline store configured, + if role_arn is not set on the Feature Group, if use_service_linked_role + is False but registration_role_arn is not provided, or if the Feature Group + is not in 'Created' status. + ClientError: If Lake Formation operations fail. + RuntimeError: If a phase fails and subsequent phases cannot proceed. + """ + # Get region from session if not provided + if region is None and session is not None: + region = session.region_name() + + # Wait for Created status if requested + if wait_for_active: + self.wait_for_status(target_status="Created") + + # Refresh to get latest state + self.refresh() + + # Validate Feature Group status + if self.feature_group_status not in ["Created"]: + raise ValueError( + f"Feature Group '{self.feature_group_name}' must be in 'Created' status " + f"to enable Lake Formation. Current status: '{self.feature_group_status}'. " + f"Use wait_for_active=True to automatically wait for the Feature Group to be ready." + ) + + # Validate offline store exists + if self.offline_store_config is None or self.offline_store_config == Unassigned(): + raise ValueError( + f"Feature Group '{self.feature_group_name}' does not have an offline store configured. " + "Lake Formation can only be enabled for Feature Groups with offline stores." + ) + + # Get role ARN from Feature Group config + if self.role_arn is None or self.role_arn == Unassigned(): + raise ValueError( + f"Feature Group '{self.feature_group_name}' does not have a role_arn configured. " + "Lake Formation requires a role ARN to grant permissions." + ) + if not use_service_linked_role and registration_role_arn is None: + raise ValueError( + "Either 'use_service_linked_role' must be True or 'registration_role_arn' must be provided." + ) + + # Extract required configuration + s3_config = self.offline_store_config.s3_storage_config + if s3_config is None: + raise ValueError("Offline store S3 configuration is missing") + + resolved_s3_uri = s3_config.resolved_output_s3_uri + if resolved_s3_uri is None or resolved_s3_uri == Unassigned(): + raise ValueError( + "Resolved S3 URI not available. Ensure the Feature Group is in 'Created' status." + ) + + data_catalog_config = self.offline_store_config.data_catalog_config + if data_catalog_config is None: + raise ValueError("Data catalog configuration is missing from offline store config") + + database_name = data_catalog_config.database + table_name = data_catalog_config.table_name + + if not database_name or not table_name: + raise ValueError("Database name and table name are required from data catalog config") + + # Convert to str to handle PipelineVariable types + resolved_s3_uri_str = str(resolved_s3_uri) + database_name_str = str(database_name) + table_name_str = str(table_name) + role_arn_str = str(self.role_arn) + + # Execute Lake Formation setup with fail-fast behavior + results = { + "s3_registration": False, + "iam_principal_revoked": False, + "permissions_granted": False, + } + + # Phase 1: Register S3 with Lake Formation + try: + results["s3_registration"] = self._register_s3_with_lake_formation( + resolved_s3_uri_str, + session, + region, + use_service_linked_role=use_service_linked_role, + role_arn=registration_role_arn, + ) + except Exception as e: + raise RuntimeError( + f"Failed to register S3 location with Lake Formation. " + f"Subsequent phases skipped. Results: {results}. Error: {e}" + ) from e + + if not results["s3_registration"]: + raise RuntimeError( + f"Failed to register S3 location with Lake Formation. " + f"Subsequent phases skipped. Results: {results}" + ) + + # Phase 2: Grant Lake Formation permissions to the role + try: + results["permissions_granted"] = self._grant_lake_formation_permissions( + role_arn_str, database_name_str, table_name_str, session, region + ) + except Exception as e: + raise RuntimeError( + f"Failed to grant Lake Formation permissions. " + f"Subsequent phases skipped. Results: {results}. Error: {e}" + ) from e + + if not results["permissions_granted"]: + raise RuntimeError( + f"Failed to grant Lake Formation permissions. " + f"Subsequent phases skipped. Results: {results}" + ) + + # Phase 3: Revoke IAMAllowedPrincipal permissions + try: + results["iam_principal_revoked"] = self._revoke_iam_allowed_principal( + database_name_str, table_name_str, session, region + ) + except Exception as e: + raise RuntimeError( + f"Failed to revoke IAMAllowedPrincipal permissions. Results: {results}. Error: {e}" + ) from e + + if not results["iam_principal_revoked"]: + raise RuntimeError( + f"Failed to revoke IAMAllowedPrincipal permissions. Results: {results}" + ) + + logger.info(f"Lake Formation setup complete for {self.feature_group_name}: {results}") + + # Generate and optionally print S3 deny policy + if show_s3_policy: + # Extract bucket name and prefix from resolved S3 URI using core utility + bucket_name, s3_prefix = parse_s3_url(resolved_s3_uri_str) + + # Extract account ID from Feature Group ARN + feature_group_arn_str = str(self.feature_group_arn) if self.feature_group_arn else "" + account_id = self._extract_account_id_from_arn(feature_group_arn_str) + + # Determine Lake Formation role ARN based on use_service_linked_role flag + if use_service_linked_role: + lf_role_arn = self._get_lake_formation_service_linked_role_arn(account_id, region) + else: + # registration_role_arn is validated earlier when use_service_linked_role is False + lf_role_arn = str(registration_role_arn) + + # Generate the S3 deny policy + policy = self._generate_s3_deny_policy( + bucket_name=bucket_name, + s3_prefix=s3_prefix, + lake_formation_role_arn=lf_role_arn, + feature_store_role_arn=role_arn_str, + ) + + # Print policy with clear instructions + import json + + print("\n" + "=" * 80) + print("S3 Bucket Policy Update recommended") + print("=" * 80) + print( + "\nTo complete Lake Formation setup, add the following deny policy to your S3 bucket." + ) + print( + "This policy restricts access to the offline store data to only the allowed principals." + ) + print("\nBucket:", bucket_name) + print("\nPolicy to add:") + print("-" * 40) + print(json.dumps(policy, indent=2)) + print("-" * 40) + print("\nNote: Merge this with your existing bucket policy if one exists.") + print("=" * 80 + "\n") + + return results + + @classmethod + @Base.add_validate_call + def create( + cls, + feature_group_name: StrPipeVar, + record_identifier_feature_name: StrPipeVar, + event_time_feature_name: StrPipeVar, + feature_definitions: List[FeatureDefinition], + online_store_config: Optional[OnlineStoreConfig] = None, + offline_store_config: Optional[OfflineStoreConfig] = None, + throughput_config: Optional[ThroughputConfig] = None, + role_arn: Optional[StrPipeVar] = None, + description: Optional[StrPipeVar] = None, + tags: Optional[List[Tag]] = None, + use_pre_prod_offline_store_replicator_lambda: Optional[bool] = None, + lake_formation_config: Optional[LakeFormationConfig] = None, + session: Optional[Session] = None, + region: Optional[StrPipeVar] = None, + ) -> Optional["FeatureGroup"]: + """ + Create a FeatureGroup resource with optional Lake Formation governance. + + Parameters: + feature_group_name: The name of the FeatureGroup. + record_identifier_feature_name: The name of the Feature whose value uniquely + identifies a Record. + event_time_feature_name: The name of the feature that stores the EventTime. + feature_definitions: A list of Feature names and types. + online_store_config: Configuration for the OnlineStore. + offline_store_config: Configuration for the OfflineStore. + throughput_config: Throughput configuration. + role_arn: IAM execution role ARN for the OfflineStore. + description: A free-form description of the FeatureGroup. + tags: Tags used to identify Features in each FeatureGroup. + use_pre_prod_offline_store_replicator_lambda: Pre-prod replicator flag. + lake_formation_config: Optional LakeFormationConfig to configure Lake Formation + governance. When enabled=True, requires offline_store_config and role_arn. + session: Boto3 session. + region: Region name. + + Returns: + The FeatureGroup resource. + + Raises: + botocore.exceptions.ClientError: This exception is raised for AWS service related errors. + The error message and error code can be parsed from the exception as follows: + ``` + try: + # AWS service call here + except botocore.exceptions.ClientError as e: + error_message = e.response['Error']['Message'] + error_code = e.response['Error']['Code'] + ``` + ResourceInUse: Resource being accessed is in use. + ResourceLimitExceeded: You have exceeded an SageMaker resource limit. + For example, you might have too many training jobs created. + ConfigSchemaValidationError: Raised when a configuration file does not adhere to the schema + LocalConfigNotFoundError: Raised when a configuration file is not found in local file system + S3ConfigNotFoundError: Raised when a configuration file is not found in S3 + """ + # Validation for Lake Formation + if lake_formation_config is not None and lake_formation_config.enabled: + if offline_store_config is None: + raise ValueError( + "lake_formation_config with enabled=True requires offline_store_config to be configured" + ) + if role_arn is None: + raise ValueError( + "lake_formation_config with enabled=True requires role_arn to be specified" + ) + if ( + not lake_formation_config.use_service_linked_role + and not lake_formation_config.registration_role_arn + ): + raise ValueError( + "registration_role_arn must be provided in lake_formation_config " + "when use_service_linked_role is False" + ) + + # Build kwargs, only including non-None values so parent uses its defaults + create_kwargs = { + "feature_group_name": feature_group_name, + "record_identifier_feature_name": record_identifier_feature_name, + "event_time_feature_name": event_time_feature_name, + "feature_definitions": feature_definitions, + "session": session, + "region": region, + } + if online_store_config is not None: + create_kwargs["online_store_config"] = online_store_config + if offline_store_config is not None: + create_kwargs["offline_store_config"] = offline_store_config + if throughput_config is not None: + create_kwargs["throughput_config"] = throughput_config + if role_arn is not None: + create_kwargs["role_arn"] = role_arn + if description is not None: + create_kwargs["description"] = description + if tags is not None: + create_kwargs["tags"] = tags + if use_pre_prod_offline_store_replicator_lambda is not None: + create_kwargs["use_pre_prod_offline_store_replicator_lambda"] = use_pre_prod_offline_store_replicator_lambda + + feature_group = super().create(**create_kwargs) + + # Enable Lake Formation if requested + if lake_formation_config is not None and lake_formation_config.enabled: + feature_group.wait_for_status(target_status="Created") + feature_group.enable_lake_formation( + session=session, + region=region, + use_service_linked_role=lake_formation_config.use_service_linked_role, + registration_role_arn=lake_formation_config.registration_role_arn, + show_s3_policy=lake_formation_config.show_s3_policy, + ) + return feature_group diff --git a/sagemaker-mlops/tests/integ/test_featureStore_lakeformation.py b/sagemaker-mlops/tests/integ/test_featureStore_lakeformation.py new file mode 100644 index 0000000000..dc6f12181a --- /dev/null +++ b/sagemaker-mlops/tests/integ/test_featureStore_lakeformation.py @@ -0,0 +1,660 @@ +""" +Integration tests for Lake Formation with FeatureGroup. + +These tests require: +- AWS credentials with Lake Formation and SageMaker permissions +- An S3 bucket for offline store (uses default SageMaker bucket) +- An IAM role for Feature Store (uses execution role) + +Run with: pytest tests/integ/test_featureStore_lakeformation.py -v -m integ +""" + +import uuid + +import boto3 +import pytest +from botocore.exceptions import ClientError + +from sagemaker.core.helper.session_helper import Session, get_execution_role +from sagemaker.mlops.feature_store import ( + FeatureGroup, + LakeFormationConfig, + OfflineStoreConfig, + OnlineStoreConfig, + S3StorageConfig, + StringFeatureDefinition, + FractionalFeatureDefinition, +) + +feature_definitions = [ + StringFeatureDefinition(feature_name="record_id"), + StringFeatureDefinition(feature_name="event_time"), + FractionalFeatureDefinition(feature_name="feature_value"), +] + + +@pytest.fixture(scope="module") +def sagemaker_session(): + return Session() + + +@pytest.fixture(scope="module") +def role(sagemaker_session): + return get_execution_role(sagemaker_session) + + +@pytest.fixture(scope="module") +def s3_uri(sagemaker_session): + bucket = sagemaker_session.default_bucket() + return f"s3://{bucket}/feature-store-test" + + +@pytest.fixture(scope="module") +def region(): + return "us-west-2" + + +@pytest.fixture(scope="module") +def shared_feature_group_for_negative_tests(s3_uri, role, region): + """ + Create a single FeatureGroup for negative tests that only need to verify + error conditions without modifying the resource. + + This fixture is module-scoped to be created once and shared across tests, + reducing test execution time. + """ + fg_name = f"test-lf-negative-{uuid.uuid4().hex[:8]}" + fg = None + + try: + fg = create_test_feature_group(fg_name, s3_uri, role, region) + fg.wait_for_status(target_status="Created", poll=30, timeout=300) + yield fg + finally: + if fg: + cleanup_feature_group(fg) + + +def generate_feature_group_name(): + """Generate a unique feature group name for testing.""" + return f"test-lf-fg-{uuid.uuid4().hex[:8]}" + + +def create_test_feature_group(name: str, s3_uri: str, role_arn: str, region: str) -> FeatureGroup: + """Create a FeatureGroup with offline store for testing.""" + + offline_store_config = OfflineStoreConfig(s3_storage_config=S3StorageConfig(s3_uri=s3_uri)) + + fg = FeatureGroup.create( + feature_group_name=name, + record_identifier_feature_name="record_id", + event_time_feature_name="event_time", + feature_definitions=feature_definitions, + offline_store_config=offline_store_config, + role_arn=role_arn, + region=region, + ) + + return fg + + +def cleanup_feature_group(fg: FeatureGroup): + """ + Delete a FeatureGroup and its associated Glue table. + + Args: + fg: The FeatureGroup to delete. + """ + try: + # Delete the Glue table if it exists + if fg.offline_store_config is not None: + try: + fg.refresh() # Ensure we have latest config + data_catalog_config = fg.offline_store_config.data_catalog_config + if data_catalog_config is not None: + database_name = data_catalog_config.database + table_name = data_catalog_config.table_name + + if database_name and table_name: + glue_client = boto3.client("glue") + try: + glue_client.delete_table(DatabaseName=database_name, Name=table_name) + except ClientError as e: + # Ignore if table doesn't exist + if e.response["Error"]["Code"] != "EntityNotFoundException": + raise + except Exception: + # Don't fail cleanup if Glue table deletion fails + pass + + # Delete the FeatureGroup + fg.delete() + except ClientError: + # Don't fail cleanup if Glue table deletion fails + pass + + +@pytest.mark.serial +@pytest.mark.slow_test +def test_create_feature_group_and_enable_lake_formation(s3_uri, role, region): + """ + Test creating a FeatureGroup and enabling Lake Formation governance. + + This test: + 1. Creates a new FeatureGroup with offline store + 2. Waits for it to reach Created status + 3. Enables Lake Formation governance (registers S3, grants permissions, revokes IAM principals) + 4. Cleans up the FeatureGroup + """ + + fg_name = generate_feature_group_name() + fg = None + + try: + # Create the FeatureGroup + fg = create_test_feature_group(fg_name, s3_uri, role, region) + assert fg is not None + + # Wait for Created status + fg.wait_for_status(target_status="Created", poll=30, timeout=300) + assert fg.feature_group_status == "Created" + + # Enable Lake Formation governance + result = fg.enable_lake_formation() + + # Verify all phases completed successfully + assert result["s3_registration"] is True + assert result["permissions_granted"] is True + assert result["iam_principal_revoked"] is True + + finally: + print('done') + # Cleanup + if fg: + cleanup_feature_group(fg) + + +@pytest.mark.serial +@pytest.mark.slow_test +def test_create_feature_group_with_lake_formation_enabled(s3_uri, role, region): + """ + Test creating a FeatureGroup with lake_formation_config.enabled=True. + + This test verifies the integrated workflow where Lake Formation is enabled + automatically during FeatureGroup creation: + 1. Creates a new FeatureGroup with lake_formation_config.enabled=True + 2. Verifies the FeatureGroup is created and Lake Formation is configured + 3. Cleans up the FeatureGroup + """ + + fg_name = generate_feature_group_name() + fg = None + + try: + # Create the FeatureGroup with Lake Formation enabled + + offline_store_config = OfflineStoreConfig(s3_storage_config=S3StorageConfig(s3_uri=s3_uri)) + lake_formation_config = LakeFormationConfig() + lake_formation_config.enabled = True + + fg = FeatureGroup.create( + feature_group_name=fg_name, + record_identifier_feature_name="record_id", + event_time_feature_name="event_time", + feature_definitions=feature_definitions, + offline_store_config=offline_store_config, + role_arn=role, + lake_formation_config=lake_formation_config, + ) + + # Verify the FeatureGroup was created + assert fg is not None + assert fg.feature_group_name == fg_name + assert fg.feature_group_status == "Created" + + # Verify Lake Formation is configured by checking we can refresh without errors + fg.refresh() + assert fg.offline_store_config is not None + + finally: + # Cleanup + if fg: + cleanup_feature_group(fg) + + +@pytest.mark.serial +def test_create_feature_group_without_lake_formation(s3_uri, role, region): + """ + Test creating a FeatureGroup without Lake Formation enabled. + + This test verifies that when lake_formation_config is not provided or enabled=False, + the FeatureGroup is created successfully without any Lake Formation operations: + 1. Creates a new FeatureGroup without lake_formation_config + 2. Verifies the FeatureGroup is created successfully + 3. Verifies no Lake Formation operations were performed + 4. Cleans up the FeatureGroup + """ + fg_name = generate_feature_group_name() + fg = None + + try: + # Create the FeatureGroup without Lake Formation + offline_store_config = OfflineStoreConfig(s3_storage_config=S3StorageConfig(s3_uri=s3_uri)) + + # Create without lake_formation_config (default behavior) + fg = FeatureGroup.create( + feature_group_name=fg_name, + record_identifier_feature_name="record_id", + event_time_feature_name="event_time", + feature_definitions=feature_definitions, + offline_store_config=offline_store_config, + role_arn=role, + ) + + # Verify the FeatureGroup was created + assert fg is not None + assert fg.feature_group_name == fg_name + + # Wait for Created status to ensure it's fully provisioned + fg.wait_for_status(target_status="Created", poll=30, timeout=300) + assert fg.feature_group_status == "Created" + + # Verify offline store is configured + fg.refresh() + assert fg.offline_store_config is not None + assert fg.offline_store_config.s3_storage_config is not None + + finally: + # Cleanup + if fg: + cleanup_feature_group(fg) + + +# ============================================================================ +# Negative Integration Tests +# ============================================================================ + + +def test_create_feature_group_with_lake_formation_fails_without_offline_store(role, region): + """ + Test that creating a FeatureGroup with enable_lake_formation=True fails + when no offline store is configured. + + Expected behavior: ValueError should be raised indicating offline store is required. + """ + fg_name = generate_feature_group_name() + + lake_formation_config = LakeFormationConfig() + lake_formation_config.enabled = True + + # Attempt to create without offline store but with Lake Formation enabled + with pytest.raises(ValueError) as exc_info: + FeatureGroup.create( + feature_group_name=fg_name, + record_identifier_feature_name="record_id", + event_time_feature_name="event_time", + feature_definitions=feature_definitions, + role_arn=role, + lake_formation_config=lake_formation_config, + ) + + # Verify error message mentions offline_store_config requirement + assert "lake_formation_config with enabled=True requires offline_store_config to be configured" in str( + exc_info.value + ) + + +def test_create_feature_group_with_lake_formation_fails_without_role(s3_uri, region): + """ + Test that creating a FeatureGroup with lake_formation_config.enabled=True fails + when no role_arn is provided. + + Expected behavior: ValueError should be raised indicating role_arn is required. + """ + fg_name = generate_feature_group_name() + + offline_store_config = OfflineStoreConfig(s3_storage_config=S3StorageConfig(s3_uri=s3_uri)) + lake_formation_config = LakeFormationConfig() + lake_formation_config.enabled = True + + # Attempt to create without role_arn but with Lake Formation enabled + with pytest.raises(ValueError) as exc_info: + FeatureGroup.create( + feature_group_name=fg_name, + record_identifier_feature_name="record_id", + event_time_feature_name="event_time", + feature_definitions=feature_definitions, + offline_store_config=offline_store_config, + lake_formation_config=lake_formation_config, + ) + + # Verify error message mentions role_arn requirement + assert "lake_formation_config with enabled=True requires role_arn to be specified" in str(exc_info.value) + + +def test_enable_lake_formation_fails_for_non_created_status(s3_uri, role, region): + """ + Test that enable_lake_formation() fails when called on a FeatureGroup + that is not in 'Created' status. + + Expected behavior: ValueError should be raised indicating the Feature Group + must be in 'Created' status. + + Note: This test creates its own FeatureGroup because it needs to test + behavior during the 'Creating' status, which requires a fresh resource. + """ + fg_name = generate_feature_group_name() + fg = None + + try: + # Create the FeatureGroup + fg = create_test_feature_group(fg_name, s3_uri, role, region) + assert fg is not None + + # Immediately try to enable Lake Formation without waiting for Created status + # The Feature Group will be in 'Creating' status + with pytest.raises(ValueError) as exc_info: + fg.enable_lake_formation(wait_for_active=False) + + # Verify error message mentions status requirement + error_msg = str(exc_info.value) + assert "must be in 'Created' status to enable Lake Formation" in error_msg + + finally: + # Cleanup + if fg: + fg.wait_for_status(target_status="Created", poll=30, timeout=300) + cleanup_feature_group(fg) + + +def test_enable_lake_formation_without_offline_store(role, region): + """ + Test that enable_lake_formation() fails when called on a FeatureGroup + without an offline store configured. + + Expected behavior: ValueError should be raised indicating offline store is required. + + Note: This test creates a FeatureGroup with only online store, which is a valid + configuration, but Lake Formation cannot be enabled for it. + """ + fg_name = generate_feature_group_name() + fg = None + + try: + # Create a FeatureGroup with only online store (no offline store) + online_store_config = OnlineStoreConfig(enable_online_store=True) + + fg = FeatureGroup.create( + feature_group_name=fg_name, + record_identifier_feature_name="record_id", + event_time_feature_name="event_time", + feature_definitions=feature_definitions, + online_store_config=online_store_config, + role_arn=role, + ) + + # Wait for Created status + fg.wait_for_status(target_status="Created", poll=30, timeout=300) + + # Attempt to enable Lake Formation + with pytest.raises(ValueError) as exc_info: + fg.enable_lake_formation() + # Verify error message mentions offline store requirement + assert "does not have an offline store configured" in str(exc_info.value) + + finally: + # Cleanup + if fg: + cleanup_feature_group(fg) + + +def test_enable_lake_formation_fails_with_invalid_registration_role( + shared_feature_group_for_negative_tests, +): + """ + Test that enable_lake_formation() fails when use_service_linked_role=False + but no registration_role_arn is provided. + + Expected behavior: ValueError should be raised indicating registration_role_arn + is required when not using service-linked role. + """ + fg = shared_feature_group_for_negative_tests + + # Attempt to enable Lake Formation without service-linked role and without registration_role_arn + with pytest.raises(ValueError) as exc_info: + fg.enable_lake_formation( + use_service_linked_role=False, + registration_role_arn=None, + ) + + # Verify error message mentions role requirement + error_msg = str(exc_info.value) + assert "registration_role_arn" in error_msg + + +def test_enable_lake_formation_fails_with_nonexistent_role( + shared_feature_group_for_negative_tests, role +): + """ + Test that enable_lake_formation() properly bubbles errors when using + a nonexistent role ARN for Lake Formation registration. + + Expected behavior: RuntimeError or ClientError should be raised with details + about the registration failure. + + Note: This test uses a nonexistent role ARN (current role with random suffix) + to trigger an error during S3 registration with Lake Formation. + """ + fg = shared_feature_group_for_negative_tests + + # Generate a nonexistent role ARN by appending a random string to the current role + nonexistent_role = f"{role}-nonexistent-{uuid.uuid4().hex[:8]}" + + with pytest.raises(RuntimeError) as exc_info: + fg.enable_lake_formation( + use_service_linked_role=False, + registration_role_arn=nonexistent_role, + ) + + # Verify we got an appropriate error + error_msg = str(exc_info.value) + print(exc_info) + # Should mention role-related issues (not found, invalid, access denied, etc.) + assert "EntityNotFoundException" in error_msg + + +# ============================================================================ +# Full Flow Integration Tests with Policy Output +# ============================================================================ + + +@pytest.mark.serial +@pytest.mark.slow_test +def test_enable_lake_formation_full_flow_with_policy_output(s3_uri, role, region, capsys): + """ + Test the full Lake Formation flow with S3 deny policy output. + + This test verifies: + 1. Creates a FeatureGroup with offline store + 2. Enables Lake Formation with show_s3_policy=True + 3. Verifies all Lake Formation phases complete successfully + 4. Verifies the S3 deny policy is printed to the console + 5. Verifies the policy structure contains expected elements + + This validates Requirements 6.1-6.9 from the design document. + """ + fg_name = generate_feature_group_name() + fg = None + + try: + # Create the FeatureGroup + fg = create_test_feature_group(fg_name, s3_uri, role, region) + assert fg is not None + + # Wait for Created status + fg.wait_for_status(target_status="Created", poll=30, timeout=300) + assert fg.feature_group_status == "Created" + + # Enable Lake Formation governance with policy output + result = fg.enable_lake_formation(show_s3_policy=True) + + # Verify all phases completed successfully + assert result["s3_registration"] is True + assert result["permissions_granted"] is True + assert result["iam_principal_revoked"] is True + + # Capture the printed output + captured = capsys.readouterr() + output = captured.out + + # Re-print the output so it's visible in terminal with -s flag + print(output) + + # Verify the policy header is printed + assert "S3 Bucket Policy Update recommended" in output + assert "=" * 80 in output + + # Verify bucket information is printed + # Extract bucket name from s3_uri (s3://bucket/path -> bucket) + expected_bucket = s3_uri.replace("s3://", "").split("/")[0] + assert f"Bucket: {expected_bucket}" in output + + # Verify policy structure elements are present + assert '"Version": "2012-10-17"' in output + assert '"Statement"' in output + assert '"Effect": "Deny"' in output + assert '"Principal": "*"' in output + + # Verify the deny actions are present + assert "s3:GetObject" in output + assert "s3:PutObject" in output + assert "s3:DeleteObject" in output + assert "s3:ListBucket" in output + + # Verify the condition structure is present + assert "StringNotEquals" in output + assert "aws:PrincipalArn" in output + + # Verify the role ARN is in the allowed principals + assert role in output + + # Verify the service-linked role pattern is present (default use_service_linked_role=True) + assert "aws-service-role/lakeformation.amazonaws.com/AWSServiceRoleForLakeFormationDataAccess" in output + + # Verify instructions are printed + assert "Merge this with your existing bucket policy" in output + + finally: + # Cleanup + if fg: + cleanup_feature_group(fg) + + +@pytest.mark.serial +@pytest.mark.slow_test +def test_enable_lake_formation_no_policy_output_by_default(s3_uri, role, region, capsys): + """ + Test that S3 deny policy is NOT printed when show_s3_policy=False (default). + + This test verifies: + 1. Creates a FeatureGroup with offline store + 2. Enables Lake Formation without show_s3_policy (defaults to False) + 3. Verifies all Lake Formation phases complete successfully + 4. Verifies the S3 deny policy is NOT printed to the console + + This validates Requirement 6.2 from the design document. + """ + fg_name = generate_feature_group_name() + fg = None + + try: + # Create the FeatureGroup + fg = create_test_feature_group(fg_name, s3_uri, role, region) + assert fg is not None + + # Wait for Created status + fg.wait_for_status(target_status="Created", poll=30, timeout=300) + assert fg.feature_group_status == "Created" + + # Enable Lake Formation governance WITHOUT policy output (default) + result = fg.enable_lake_formation() + + # Verify all phases completed successfully + assert result["s3_registration"] is True + assert result["permissions_granted"] is True + assert result["iam_principal_revoked"] is True + + # Capture the printed output + captured = capsys.readouterr() + output = captured.out + + # Verify the policy is NOT printed + assert "S3 Bucket Policy Update recommended" not in output + assert '"Version": "2012-10-17"' not in output + assert "s3:GetObject" not in output + + finally: + # Cleanup + if fg: + cleanup_feature_group(fg) + + +@pytest.mark.serial +@pytest.mark.slow_test +def test_enable_lake_formation_with_custom_role_policy_output(s3_uri, role, region, capsys): + """ + Test the full Lake Formation flow with custom registration role and policy output. + + This test verifies: + 1. Creates a FeatureGroup with offline store + 2. Enables Lake Formation with use_service_linked_role=False and a custom registration_role_arn + 3. Verifies the S3 deny policy uses the custom role ARN instead of service-linked role + + This validates Requirements 6.4, 6.5 from the design document. + + Note: This test uses the same execution role as the registration role for simplicity. + In production, these would typically be different roles. + """ + fg_name = generate_feature_group_name() + fg = None + + try: + # Create the FeatureGroup + fg = create_test_feature_group(fg_name, s3_uri, role, region) + assert fg is not None + + # Wait for Created status + fg.wait_for_status(target_status="Created", poll=30, timeout=300) + assert fg.feature_group_status == "Created" + + # Enable Lake Formation with custom registration role and policy output + # Using the same role for both execution and registration for test simplicity + result = fg.enable_lake_formation( + use_service_linked_role=False, + registration_role_arn=role, + show_s3_policy=True, + ) + + # Verify all phases completed successfully + assert result["s3_registration"] is True + assert result["permissions_granted"] is True + assert result["iam_principal_revoked"] is True + + # Capture the printed output + captured = capsys.readouterr() + output = captured.out + + # Verify the policy header is printed + assert "S3 Bucket Policy Update recommended" in output + + # Verify the custom role ARN is used in the policy (appears twice - once for each principal) + # The role should appear as both the Lake Formation role and the Feature Store role + assert output.count(role) >= 2 + + # Verify the service-linked role is NOT used + assert "aws-service-role/lakeformation.amazonaws.com/AWSServiceRoleForLakeFormationDataAccess" not in output + + finally: + # Cleanup + if fg: + cleanup_feature_group(fg) diff --git a/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_lakeformation.py b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_lakeformation.py new file mode 100644 index 0000000000..e4d44df37a --- /dev/null +++ b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_lakeformation.py @@ -0,0 +1,2141 @@ +"""Unit tests for Lake Formation integration with FeatureGroup.""" +from unittest.mock import MagicMock, patch + +import botocore.exceptions +import pytest + +from sagemaker.mlops.feature_store import FeatureGroup, LakeFormationConfig + + +class TestS3UriToArn: + """Tests for _s3_uri_to_arn static method.""" + + def test_converts_s3_uri_to_arn(self): + """Test S3 URI is converted to ARN format.""" + uri = "s3://my-bucket/my-prefix/data" + result = FeatureGroup._s3_uri_to_arn(uri) + assert result == "arn:aws:s3:::my-bucket/my-prefix/data" + + def test_handles_bucket_only_uri(self): + """Test S3 URI with bucket only.""" + uri = "s3://my-bucket" + result = FeatureGroup._s3_uri_to_arn(uri) + assert result == "arn:aws:s3:::my-bucket" + + def test_returns_arn_unchanged(self): + """Test ARN input is returned unchanged (idempotent).""" + arn = "arn:aws:s3:::my-bucket/path" + result = FeatureGroup._s3_uri_to_arn(arn) + assert result == arn + + def test_uses_region_for_partition(self): + """Test that region is used to determine partition.""" + uri = "s3://my-bucket/path" + result = FeatureGroup._s3_uri_to_arn(uri, region="cn-north-1") + assert result.startswith("arn:aws-cn:s3:::") + + + +class TestGetLakeFormationClient: + """Tests for _get_lake_formation_client method.""" + + @patch("sagemaker.mlops.feature_store.feature_group.Session") + def test_creates_client_with_default_session(self, mock_session_class): + """Test client creation with default session.""" + mock_session = MagicMock() + mock_client = MagicMock() + mock_session.client.return_value = mock_client + mock_session_class.return_value = mock_session + + fg = MagicMock(spec=FeatureGroup) + fg._get_lake_formation_client = FeatureGroup._get_lake_formation_client.__get__(fg) + + client = fg._get_lake_formation_client(region="us-west-2") + + mock_session.client.assert_called_with("lakeformation", region_name="us-west-2") + assert client == mock_client + + def test_creates_client_with_provided_session(self): + """Test client creation with provided session.""" + mock_session = MagicMock() + mock_client = MagicMock() + mock_session.client.return_value = mock_client + + fg = MagicMock(spec=FeatureGroup) + fg._get_lake_formation_client = FeatureGroup._get_lake_formation_client.__get__(fg) + + client = fg._get_lake_formation_client(session=mock_session, region="us-west-2") + + mock_session.client.assert_called_with("lakeformation", region_name="us-west-2") + assert client == mock_client + + +class TestRegisterS3WithLakeFormation: + """Tests for _register_s3_with_lake_formation method.""" + + def setup_method(self): + """Set up test fixtures.""" + self.fg = MagicMock(spec=FeatureGroup) + self.fg._s3_uri_to_arn = FeatureGroup._s3_uri_to_arn + self.fg._register_s3_with_lake_formation = ( + FeatureGroup._register_s3_with_lake_formation.__get__(self.fg) + ) + self.mock_client = MagicMock() + self.fg._get_lake_formation_client = MagicMock(return_value=self.mock_client) + + def test_successful_registration_returns_true(self): + """Test successful S3 registration returns True.""" + self.mock_client.register_resource.return_value = {} + + result = self.fg._register_s3_with_lake_formation("s3://test-bucket/prefix") + + assert result is True + self.mock_client.register_resource.assert_called_with( + ResourceArn="arn:aws:s3:::test-bucket/prefix", + UseServiceLinkedRole=True, + ) + + def test_already_exists_exception_returns_true(self): + """Test AlreadyExistsException is handled gracefully.""" + self.mock_client.register_resource.side_effect = botocore.exceptions.ClientError( + {"Error": {"Code": "AlreadyExistsException", "Message": "Already exists"}}, + "RegisterResource", + ) + + result = self.fg._register_s3_with_lake_formation("s3://test-bucket/prefix") + + assert result is True + + def test_other_exceptions_are_propagated(self): + """Test non-AlreadyExistsException errors are propagated.""" + self.mock_client.register_resource.side_effect = botocore.exceptions.ClientError( + {"Error": {"Code": "AccessDeniedException", "Message": "Access denied"}}, + "RegisterResource", + ) + + with pytest.raises(botocore.exceptions.ClientError) as exc_info: + self.fg._register_s3_with_lake_formation("s3://test-bucket/prefix") + + assert exc_info.value.response["Error"]["Code"] == "AccessDeniedException" + + def test_uses_service_linked_role(self): + """Test UseServiceLinkedRole is set to True.""" + self.mock_client.register_resource.return_value = {} + + self.fg._register_s3_with_lake_formation("s3://bucket/path") + + call_args = self.mock_client.register_resource.call_args + assert call_args[1]["UseServiceLinkedRole"] is True + + def test_uses_custom_role_arn_when_service_linked_role_disabled(self): + """Test custom role ARN is used when use_service_linked_role is False.""" + self.mock_client.register_resource.return_value = {} + custom_role = "arn:aws:iam::123456789012:role/CustomLakeFormationRole" + + self.fg._register_s3_with_lake_formation( + "s3://bucket/path", + use_service_linked_role=False, + role_arn=custom_role, + ) + + call_args = self.mock_client.register_resource.call_args + assert call_args[1]["RoleArn"] == custom_role + assert "UseServiceLinkedRole" not in call_args[1] + + def test_raises_error_when_role_arn_missing_and_service_linked_role_disabled(self): + """Test ValueError when use_service_linked_role is False but role_arn not provided.""" + with pytest.raises(ValueError) as exc_info: + self.fg._register_s3_with_lake_formation( + "s3://bucket/path", use_service_linked_role=False + ) + + assert "role_arn must be provided when use_service_linked_role is False" in str( + exc_info.value + ) + + + +class TestRevokeIamAllowedPrincipal: + """Tests for _revoke_iam_allowed_principal method.""" + + def setup_method(self): + """Set up test fixtures.""" + self.fg = MagicMock(spec=FeatureGroup) + self.fg._revoke_iam_allowed_principal = FeatureGroup._revoke_iam_allowed_principal.__get__( + self.fg + ) + self.mock_client = MagicMock() + self.fg._get_lake_formation_client = MagicMock(return_value=self.mock_client) + + def test_successful_revocation_returns_true(self): + """Test successful revocation returns True.""" + self.mock_client.revoke_permissions.return_value = {} + + result = self.fg._revoke_iam_allowed_principal("test_database", "test_table") + + assert result is True + self.mock_client.revoke_permissions.assert_called_once() + + def test_revoke_permissions_call_structure(self): + """Test that revoke_permissions is called with correct parameters.""" + self.mock_client.revoke_permissions.return_value = {} + database_name = "my_database" + table_name = "my_table" + + self.fg._revoke_iam_allowed_principal(database_name, table_name) + + call_args = self.mock_client.revoke_permissions.call_args + assert call_args[1]["Principal"] == { + "DataLakePrincipalIdentifier": "IAM_ALLOWED_PRINCIPALS" + } + assert call_args[1]["Permissions"] == ["ALL"] + assert call_args[1]["Resource"] == { + "Table": { + "DatabaseName": database_name, + "Name": table_name, + } + } + + def test_invalid_input_exception_returns_true(self): + """Test InvalidInputException is handled gracefully (permissions may not exist).""" + self.mock_client.revoke_permissions.side_effect = botocore.exceptions.ClientError( + {"Error": {"Code": "InvalidInputException", "Message": "Permissions not found"}}, + "RevokePermissions", + ) + + result = self.fg._revoke_iam_allowed_principal("test_database", "test_table") + + assert result is True + + def test_other_exceptions_are_propagated(self): + """Test non-InvalidInputException errors are propagated.""" + self.mock_client.revoke_permissions.side_effect = botocore.exceptions.ClientError( + {"Error": {"Code": "AccessDeniedException", "Message": "Access denied"}}, + "RevokePermissions", + ) + + with pytest.raises(botocore.exceptions.ClientError) as exc_info: + self.fg._revoke_iam_allowed_principal("test_database", "test_table") + + assert exc_info.value.response["Error"]["Code"] == "AccessDeniedException" + + def test_passes_session_and_region_to_client(self): + """Test session and region are passed to get_lake_formation_client.""" + self.mock_client.revoke_permissions.return_value = {} + mock_session = MagicMock() + + self.fg._revoke_iam_allowed_principal( + "test_database", "test_table", session=mock_session, region="us-west-2" + ) + + self.fg._get_lake_formation_client.assert_called_with(mock_session, "us-west-2") + + + +class TestGrantLakeFormationPermissions: + """Tests for _grant_lake_formation_permissions method.""" + + def setup_method(self): + """Set up test fixtures.""" + self.fg = MagicMock(spec=FeatureGroup) + self.fg._grant_lake_formation_permissions = ( + FeatureGroup._grant_lake_formation_permissions.__get__(self.fg) + ) + self.mock_client = MagicMock() + self.fg._get_lake_formation_client = MagicMock(return_value=self.mock_client) + + def test_successful_grant_returns_true(self): + """Test successful permission grant returns True.""" + self.mock_client.grant_permissions.return_value = {} + + result = self.fg._grant_lake_formation_permissions( + "arn:aws:iam::123456789012:role/TestRole", "test_database", "test_table" + ) + + assert result is True + self.mock_client.grant_permissions.assert_called_once() + + def test_grant_permissions_call_structure(self): + """Test that grant_permissions is called with correct parameters.""" + self.mock_client.grant_permissions.return_value = {} + role_arn = "arn:aws:iam::123456789012:role/MyExecutionRole" + + self.fg._grant_lake_formation_permissions(role_arn, "my_database", "my_table") + + call_args = self.mock_client.grant_permissions.call_args + assert call_args[1]["Principal"] == {"DataLakePrincipalIdentifier": role_arn} + assert call_args[1]["Resource"] == { + "Table": { + "DatabaseName": "my_database", + "Name": "my_table", + } + } + assert call_args[1]["Permissions"] == ["SELECT", "INSERT", "DELETE", "DESCRIBE", "ALTER"] + assert call_args[1]["PermissionsWithGrantOption"] == [] + + def test_invalid_input_exception_returns_true(self): + """Test InvalidInputException is handled gracefully (permissions may exist).""" + self.mock_client.grant_permissions.side_effect = botocore.exceptions.ClientError( + {"Error": {"Code": "InvalidInputException", "Message": "Permissions already exist"}}, + "GrantPermissions", + ) + + result = self.fg._grant_lake_formation_permissions( + "arn:aws:iam::123456789012:role/TestRole", "test_database", "test_table" + ) + + assert result is True + + def test_other_exceptions_are_propagated(self): + """Test non-InvalidInputException errors are propagated.""" + self.mock_client.grant_permissions.side_effect = botocore.exceptions.ClientError( + {"Error": {"Code": "AccessDeniedException", "Message": "Access denied"}}, + "GrantPermissions", + ) + + with pytest.raises(botocore.exceptions.ClientError) as exc_info: + self.fg._grant_lake_formation_permissions( + "arn:aws:iam::123456789012:role/TestRole", "test_database", "test_table" + ) + + assert exc_info.value.response["Error"]["Code"] == "AccessDeniedException" + + def test_passes_session_and_region_to_client(self): + """Test session and region are passed to get_lake_formation_client.""" + self.mock_client.grant_permissions.return_value = {} + mock_session = MagicMock() + + self.fg._grant_lake_formation_permissions( + "arn:aws:iam::123456789012:role/TestRole", + "test_database", + "test_table", + session=mock_session, + region="us-west-2", + ) + + self.fg._get_lake_formation_client.assert_called_with(mock_session, "us-west-2") + + + +class TestEnableLakeFormationValidation: + """Tests for enable_lake_formation validation logic.""" + + @patch.object(FeatureGroup, "refresh") + def test_raises_error_when_no_offline_store(self, mock_refresh): + """Test that enable_lake_formation raises ValueError when no offline store is configured.""" + fg = FeatureGroup(feature_group_name="test-fg") + fg.offline_store_config = None + fg.feature_group_status = "Created" + + with pytest.raises(ValueError, match="does not have an offline store configured"): + fg.enable_lake_formation() + + # Verify refresh was called + mock_refresh.assert_called_once() + + @patch.object(FeatureGroup, "refresh") + def test_raises_error_when_no_role_arn(self, mock_refresh): + """Test that enable_lake_formation raises ValueError when no role_arn is configured.""" + from sagemaker.core.shapes import OfflineStoreConfig, S3StorageConfig, DataCatalogConfig + + fg = FeatureGroup(feature_group_name="test-fg") + fg.offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig( + s3_uri="s3://test-bucket/path", + resolved_output_s3_uri="s3://test-bucket/resolved-path", + ), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database="test_db", table_name="test_table" + ), + ) + fg.role_arn = None + fg.feature_group_status = "Created" + + with pytest.raises(ValueError, match="does not have a role_arn configured"): + fg.enable_lake_formation() + + # Verify refresh was called + mock_refresh.assert_called_once() + + @patch.object(FeatureGroup, "refresh") + def test_raises_error_when_invalid_status(self, mock_refresh): + """Test enable_lake_formation raises ValueError when Feature Group not in Created status.""" + from sagemaker.core.shapes import OfflineStoreConfig, S3StorageConfig, DataCatalogConfig + + fg = FeatureGroup(feature_group_name="test-fg") + fg.offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig( + s3_uri="s3://test-bucket/path", + resolved_output_s3_uri="s3://test-bucket/resolved-path", + ), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database="test_db", table_name="test_table" + ), + ) + fg.role_arn = "arn:aws:iam::123456789012:role/TestRole" + fg.feature_group_status = "Creating" + + with pytest.raises(ValueError, match="must be in 'Created' status"): + fg.enable_lake_formation() + + # Verify refresh was called + mock_refresh.assert_called_once() + + @patch.object(FeatureGroup, "wait_for_status") + @patch.object(FeatureGroup, "refresh") + @patch.object(FeatureGroup, "_register_s3_with_lake_formation") + @patch.object(FeatureGroup, "_grant_lake_formation_permissions") + @patch.object(FeatureGroup, "_revoke_iam_allowed_principal") + def test_wait_for_active_calls_wait_for_status( + self, mock_revoke, mock_grant, mock_register, mock_refresh, mock_wait + ): + """Test that wait_for_active=True calls wait_for_status with 'Created' target.""" + from sagemaker.core.shapes import OfflineStoreConfig, S3StorageConfig, DataCatalogConfig + + fg = FeatureGroup(feature_group_name="test-fg") + fg.offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig( + s3_uri="s3://test-bucket/path", + resolved_output_s3_uri="s3://test-bucket/resolved-path", + ), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database="test_db", table_name="test_table" + ), + ) + fg.role_arn = "arn:aws:iam::123456789012:role/TestRole" + fg.feature_group_arn = "arn:aws:sagemaker:us-west-2:123456789012:feature-group/test-fg" + fg.feature_group_status = "Created" + + # Mock successful Lake Formation operations + mock_register.return_value = True + mock_grant.return_value = True + mock_revoke.return_value = True + + # Call with wait_for_active=True + fg.enable_lake_formation(wait_for_active=True) + + # Verify wait_for_status was called with "Created" + mock_wait.assert_called_once_with(target_status="Created") + # Verify refresh was called after wait + mock_refresh.assert_called_once() + + @patch.object(FeatureGroup, "wait_for_status") + @patch.object(FeatureGroup, "refresh") + @patch.object(FeatureGroup, "_register_s3_with_lake_formation") + @patch.object(FeatureGroup, "_grant_lake_formation_permissions") + @patch.object(FeatureGroup, "_revoke_iam_allowed_principal") + def test_wait_for_active_false_does_not_call_wait( + self, mock_revoke, mock_grant, mock_register, mock_refresh, mock_wait + ): + """Test that wait_for_active=False does not call wait_for_status.""" + from sagemaker.core.shapes import OfflineStoreConfig, S3StorageConfig, DataCatalogConfig + + fg = FeatureGroup(feature_group_name="test-fg") + fg.offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig( + s3_uri="s3://test-bucket/path", + resolved_output_s3_uri="s3://test-bucket/resolved-path", + ), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database="test_db", table_name="test_table" + ), + ) + fg.role_arn = "arn:aws:iam::123456789012:role/TestRole" + fg.feature_group_arn = "arn:aws:sagemaker:us-west-2:123456789012:feature-group/test-fg" + fg.feature_group_status = "Created" + + # Mock successful Lake Formation operations + mock_register.return_value = True + mock_grant.return_value = True + mock_revoke.return_value = True + + # Call with wait_for_active=False (default) + fg.enable_lake_formation(wait_for_active=False) + + # Verify wait_for_status was NOT called + mock_wait.assert_not_called() + # Verify refresh was still called + mock_refresh.assert_called_once() + + + @pytest.mark.parametrize( + "feature_group_name,role_arn,s3_uri,database_name,table_name", + [ + ("test-fg", "TestRole", "path1", "db1", "table1"), + ("my_feature_group", "ExecutionRole", "data/features", "feature_db", "feature_table"), + ("fg123", "MyRole123", "ml/features/v1", "analytics", "features_v1"), + ("simple", "SimpleRole", "simple-path", "simple_db", "simple_table"), + ( + "complex-name", + "ComplexExecutionRole", + "complex/path/structure", + "complex_database", + "complex_table_name", + ), + ( + "underscore_name", + "Underscore_Role", + "underscore_path", + "underscore_db", + "underscore_table", + ), + ("mixed-123", "Mixed123Role", "mixed/path/123", "mixed_db_123", "mixed_table_123"), + ("x", "XRole", "x", "x", "x"), + ( + "very-long-name", + "VeryLongRoleName", + "very/long/path/structure", + "very_long_database_name", + "very_long_table_name", + ), + ], + ) + @patch.object(FeatureGroup, "refresh") + @patch.object(FeatureGroup, "_register_s3_with_lake_formation") + @patch.object(FeatureGroup, "_grant_lake_formation_permissions") + @patch.object(FeatureGroup, "_revoke_iam_allowed_principal") + def test_fail_fast_phase_execution( + self, + mock_revoke, + mock_grant, + mock_register, + mock_refresh, + feature_group_name, + role_arn, + s3_uri, + database_name, + table_name, + ): + """ + Test fail-fast behavior for Lake Formation phases. + + If Phase 1 (S3 registration) fails, Phase 2 and 3 should not execute. + If Phase 2 fails, Phase 3 should not execute. + RuntimeError should indicate which phase failed. + """ + from sagemaker.core.shapes import OfflineStoreConfig, S3StorageConfig, DataCatalogConfig + + fg = FeatureGroup(feature_group_name=feature_group_name) + fg.offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig( + s3_uri=f"s3://test-bucket/{s3_uri}", + resolved_output_s3_uri=f"s3://test-bucket/resolved-{s3_uri}", + ), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database=database_name, table_name=table_name + ), + ) + fg.role_arn = f"arn:aws:iam::123456789012:role/{role_arn}" + fg.feature_group_status = "Created" + + # Test Phase 1 failure - subsequent phases should not be called + mock_register.side_effect = Exception("Phase 1 failed") + mock_grant.return_value = True + mock_revoke.return_value = True + + with pytest.raises( + RuntimeError, match="Failed to register S3 location with Lake Formation" + ): + fg.enable_lake_formation() + + # Verify Phase 1 was called but Phase 2 and 3 were not + mock_register.assert_called_once() + mock_grant.assert_not_called() + mock_revoke.assert_not_called() + + # Reset mocks for Phase 2 failure test + mock_register.reset_mock() + mock_grant.reset_mock() + mock_revoke.reset_mock() + + # Test Phase 2 failure - Phase 3 should not be called + mock_register.side_effect = None + mock_register.return_value = True + mock_grant.side_effect = Exception("Phase 2 failed") + mock_revoke.return_value = True + + with pytest.raises(RuntimeError, match="Failed to grant Lake Formation permissions"): + fg.enable_lake_formation() + + # Verify Phase 1 and 2 were called but Phase 3 was not + mock_register.assert_called_once() + mock_grant.assert_called_once() + mock_revoke.assert_not_called() + + # Reset mocks for Phase 3 failure test + mock_register.reset_mock() + mock_grant.reset_mock() + mock_revoke.reset_mock() + + # Test Phase 3 failure - all phases should be called + mock_register.side_effect = None + mock_register.return_value = True + mock_grant.side_effect = None + mock_grant.return_value = True + mock_revoke.side_effect = Exception("Phase 3 failed") + + with pytest.raises(RuntimeError, match="Failed to revoke IAMAllowedPrincipal permissions"): + fg.enable_lake_formation() + + # Verify all phases were called + mock_register.assert_called_once() + mock_grant.assert_called_once() + mock_revoke.assert_called_once() + + + +class TestUnhandledExceptionPropagation: + """Tests for proper propagation of unhandled boto3 exceptions.""" + + def test_register_s3_propagates_unhandled_exceptions(self): + """ + Non-AlreadyExists Errors Propagate from S3 Registration + + For any error from Lake Formation's register_resource API that is not + AlreadyExistsException, the error should be propagated to the caller unchanged. + + """ + fg = MagicMock(spec=FeatureGroup) + fg._s3_uri_to_arn = FeatureGroup._s3_uri_to_arn + fg._register_s3_with_lake_formation = FeatureGroup._register_s3_with_lake_formation.__get__( + fg + ) + mock_client = MagicMock() + fg._get_lake_formation_client = MagicMock(return_value=mock_client) + + # Configure mock to raise an unhandled error + mock_client.register_resource.side_effect = botocore.exceptions.ClientError( + { + "Error": { + "Code": "AccessDeniedException", + "Message": "User does not have permission", + } + }, + "RegisterResource", + ) + + # Verify the exception is propagated unchanged + with pytest.raises(botocore.exceptions.ClientError) as exc_info: + fg._register_s3_with_lake_formation("s3://test-bucket/path") + + # Verify error details are preserved + assert exc_info.value.response["Error"]["Code"] == "AccessDeniedException" + assert exc_info.value.response["Error"]["Message"] == "User does not have permission" + assert exc_info.value.operation_name == "RegisterResource" + + def test_revoke_iam_principal_propagates_unhandled_exceptions(self): + """ + Non-InvalidInput Errors Propagate from IAM Principal Revocation + + For any error from Lake Formation's revoke_permissions API that is not + InvalidInputException, the error should be propagated to the caller unchanged. + + """ + fg = MagicMock(spec=FeatureGroup) + fg._revoke_iam_allowed_principal = FeatureGroup._revoke_iam_allowed_principal.__get__(fg) + mock_client = MagicMock() + fg._get_lake_formation_client = MagicMock(return_value=mock_client) + + # Configure mock to raise an unhandled error + mock_client.revoke_permissions.side_effect = botocore.exceptions.ClientError( + { + "Error": { + "Code": "AccessDeniedException", + "Message": "User does not have permission", + } + }, + "RevokePermissions", + ) + + # Verify the exception is propagated unchanged + with pytest.raises(botocore.exceptions.ClientError) as exc_info: + fg._revoke_iam_allowed_principal("test_database", "test_table") + + # Verify error details are preserved + assert exc_info.value.response["Error"]["Code"] == "AccessDeniedException" + assert exc_info.value.response["Error"]["Message"] == "User does not have permission" + assert exc_info.value.operation_name == "RevokePermissions" + + def test_grant_permissions_propagates_unhandled_exceptions(self): + """ + Non-InvalidInput Errors Propagate from Permission Grant + + For any error from Lake Formation's grant_permissions API that is not + InvalidInputException, the error should be propagated to the caller unchanged. + + """ + fg = MagicMock(spec=FeatureGroup) + fg._grant_lake_formation_permissions = ( + FeatureGroup._grant_lake_formation_permissions.__get__(fg) + ) + mock_client = MagicMock() + fg._get_lake_formation_client = MagicMock(return_value=mock_client) + + # Configure mock to raise an unhandled error + mock_client.grant_permissions.side_effect = botocore.exceptions.ClientError( + { + "Error": { + "Code": "AccessDeniedException", + "Message": "User does not have permission", + } + }, + "GrantPermissions", + ) + + # Verify the exception is propagated unchanged + with pytest.raises(botocore.exceptions.ClientError) as exc_info: + fg._grant_lake_formation_permissions( + "arn:aws:iam::123456789012:role/TestRole", "test_database", "test_table" + ) + + # Verify error details are preserved + assert exc_info.value.response["Error"]["Code"] == "AccessDeniedException" + assert exc_info.value.response["Error"]["Message"] == "User does not have permission" + assert exc_info.value.operation_name == "GrantPermissions" + + def test_handled_exceptions_do_not_propagate(self): + """ + Verify that specifically handled exceptions (AlreadyExistsException, InvalidInputException) + do NOT propagate but return True instead, while all other exceptions are propagated. + """ + fg = MagicMock(spec=FeatureGroup) + fg._s3_uri_to_arn = FeatureGroup._s3_uri_to_arn + fg._register_s3_with_lake_formation = FeatureGroup._register_s3_with_lake_formation.__get__( + fg + ) + fg._revoke_iam_allowed_principal = FeatureGroup._revoke_iam_allowed_principal.__get__(fg) + fg._grant_lake_formation_permissions = ( + FeatureGroup._grant_lake_formation_permissions.__get__(fg) + ) + mock_client = MagicMock() + fg._get_lake_formation_client = MagicMock(return_value=mock_client) + + # Test AlreadyExistsException is handled (not propagated) + mock_client.register_resource.side_effect = botocore.exceptions.ClientError( + {"Error": {"Code": "AlreadyExistsException", "Message": "Already exists"}}, + "RegisterResource", + ) + result = fg._register_s3_with_lake_formation("s3://test-bucket/path") + assert result is True # Should return True, not raise + + # Test InvalidInputException is handled for revoke (not propagated) + mock_client.revoke_permissions.side_effect = botocore.exceptions.ClientError( + {"Error": {"Code": "InvalidInputException", "Message": "Invalid input"}}, + "RevokePermissions", + ) + result = fg._revoke_iam_allowed_principal("db", "table") + assert result is True # Should return True, not raise + + # Test InvalidInputException is handled for grant (not propagated) + mock_client.grant_permissions.side_effect = botocore.exceptions.ClientError( + {"Error": {"Code": "InvalidInputException", "Message": "Invalid input"}}, + "GrantPermissions", + ) + result = fg._grant_lake_formation_permissions( + "arn:aws:iam::123456789012:role/TestRole", "db", "table" + ) + assert result is True # Should return True, not raise + + + +class TestCreateWithLakeFormation: + """Tests for create() method with Lake Formation integration.""" + + @pytest.mark.parametrize( + "feature_group_name,record_id_feature,event_time_feature", + [ + ("test-fg", "record_id", "event_time"), + ("my_feature_group", "id", "timestamp"), + ("fg123", "identifier", "time"), + ("simple", "rec_id", "evt_time"), + ("complex-name", "record_identifier", "event_timestamp"), + ("underscore_name", "record_id_field", "event_time_field"), + ("mixed-123", "id_123", "time_123"), + ("x", "x_id", "x_time"), + ("very-long-name", "very_long_record_id", "very_long_event_time"), + ], + ) + @patch("sagemaker.core.resources.Base.get_sagemaker_client") + @patch.object(FeatureGroup, "get") + @patch.object(FeatureGroup, "wait_for_status") + @patch.object(FeatureGroup, "enable_lake_formation") + def test_no_lake_formation_operations_when_disabled( + self, + mock_enable_lf, + mock_wait, + mock_get, + mock_get_client, + feature_group_name, + record_id_feature, + event_time_feature, + ): + """ + No Lake Formation Operations When Disabled + + For any call to FeatureGroup.create() where lake_formation_config is None or has enabled=False, + no Lake Formation client methods should be invoked. + + """ + from sagemaker.core.shapes import FeatureDefinition + + # Mock the SageMaker client + mock_client = MagicMock() + mock_client.create_feature_group.return_value = { + "FeatureGroupArn": "arn:aws:sagemaker:us-west-2:123456789012:feature-group/test" + } + mock_get_client.return_value = mock_client + + # Mock the get method to return a feature group + mock_fg = MagicMock(spec=FeatureGroup) + mock_fg.feature_group_name = feature_group_name + mock_get.return_value = mock_fg + + # Create feature definitions + feature_definitions = [ + FeatureDefinition(feature_name=record_id_feature, feature_type="String"), + FeatureDefinition(feature_name=event_time_feature, feature_type="String"), + ] + + # Test 1: lake_formation_config with enabled=False (explicit) + lf_config = LakeFormationConfig() + lf_config.enabled = False + result = FeatureGroup.create( + feature_group_name=feature_group_name, + record_identifier_feature_name=record_id_feature, + event_time_feature_name=event_time_feature, + feature_definitions=feature_definitions, + lake_formation_config=lf_config, + ) + + # Verify enable_lake_formation was NOT called + mock_enable_lf.assert_not_called() + # Verify wait_for_status was NOT called + mock_wait.assert_not_called() + # Verify the feature group was returned + assert result == mock_fg + + # Reset mocks for next test + mock_enable_lf.reset_mock() + mock_wait.reset_mock() + mock_get.reset_mock() + mock_get.return_value = mock_fg + + # Test 2: lake_formation_config not specified (defaults to None) + result = FeatureGroup.create( + feature_group_name=feature_group_name, + record_identifier_feature_name=record_id_feature, + event_time_feature_name=event_time_feature, + feature_definitions=feature_definitions, + # lake_formation_config not specified, should default to None + ) + + # Verify enable_lake_formation was NOT called + mock_enable_lf.assert_not_called() + # Verify wait_for_status was NOT called + mock_wait.assert_not_called() + # Verify the feature group was returned + assert result == mock_fg + + @pytest.mark.parametrize( + "feature_group_name,record_id_feature,event_time_feature,role_arn,s3_uri,database,table", + [ + ("test-fg", "record_id", "event_time", "TestRole", "path1", "db1", "table1"), + ( + "my_feature_group", + "id", + "timestamp", + "ExecutionRole", + "data/features", + "feature_db", + "feature_table", + ), + ( + "fg123", + "identifier", + "time", + "MyRole123", + "ml/features/v1", + "analytics", + "features_v1", + ), + ], + ) + @patch("sagemaker.core.resources.Base.get_sagemaker_client") + @patch.object(FeatureGroup, "get") + @patch.object(FeatureGroup, "wait_for_status") + @patch.object(FeatureGroup, "enable_lake_formation") + def test_enable_lake_formation_called_when_enabled( + self, + mock_enable_lf, + mock_wait, + mock_get, + mock_get_client, + feature_group_name, + record_id_feature, + event_time_feature, + role_arn, + s3_uri, + database, + table, + ): + """ + Test that enable_lake_formation is called when lake_formation_config has enabled=True. + + This verifies the integration between create() and enable_lake_formation(). + """ + from sagemaker.core.shapes import ( + FeatureDefinition, + OfflineStoreConfig, + S3StorageConfig, + DataCatalogConfig, + ) + + # Mock the SageMaker client + mock_client = MagicMock() + mock_client.create_feature_group.return_value = { + "FeatureGroupArn": "arn:aws:sagemaker:us-west-2:123456789012:feature-group/test" + } + mock_get_client.return_value = mock_client + + # Mock the get method to return a feature group + mock_fg = MagicMock(spec=FeatureGroup) + mock_fg.feature_group_name = feature_group_name + mock_fg.wait_for_status = mock_wait + mock_fg.enable_lake_formation = mock_enable_lf + mock_get.return_value = mock_fg + + # Create feature definitions + feature_definitions = [ + FeatureDefinition(feature_name=record_id_feature, feature_type="String"), + FeatureDefinition(feature_name=event_time_feature, feature_type="String"), + ] + + # Create offline store config + offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig(s3_uri=f"s3://test-bucket/{s3_uri}"), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database=database, table_name=table + ), + ) + + # Create LakeFormationConfig with enabled=True + lf_config = LakeFormationConfig() + lf_config.enabled = True + + # Create with lake_formation_config enabled=True + result = FeatureGroup.create( + feature_group_name=feature_group_name, + record_identifier_feature_name=record_id_feature, + event_time_feature_name=event_time_feature, + feature_definitions=feature_definitions, + offline_store_config=offline_store_config, + role_arn=f"arn:aws:iam::123456789012:role/{role_arn}", + lake_formation_config=lf_config, + ) + + # Verify wait_for_status was called with "Created" + mock_wait.assert_called_once_with(target_status="Created") + # Verify enable_lake_formation was called with default use_service_linked_role=True + mock_enable_lf.assert_called_once_with( + session=None, + region=None, + use_service_linked_role=True, + registration_role_arn=None, + show_s3_policy=False, + ) + # Verify the feature group was returned + assert result == mock_fg + + @pytest.mark.parametrize( + "feature_group_name,record_id_feature,event_time_feature", + [ + ("test-fg", "record_id", "event_time"), + ("my_feature_group", "id", "timestamp"), + ("fg123", "identifier", "time"), + ], + ) + @patch("sagemaker.core.resources.Base.get_sagemaker_client") + def test_validation_error_when_lake_formation_enabled_without_offline_store( + self, mock_get_client, feature_group_name, record_id_feature, event_time_feature + ): + """Test create() raises ValueError when lake_formation_config enabled=True without offline_store.""" + from sagemaker.core.shapes import FeatureDefinition + + # Mock the SageMaker client + mock_client = MagicMock() + mock_get_client.return_value = mock_client + + # Create feature definitions + feature_definitions = [ + FeatureDefinition(feature_name=record_id_feature, feature_type="String"), + FeatureDefinition(feature_name=event_time_feature, feature_type="String"), + ] + + # Create LakeFormationConfig with enabled=True + lf_config = LakeFormationConfig() + lf_config.enabled = True + + # Test with lake_formation_config enabled=True but no offline_store_config + with pytest.raises( + ValueError, + match="lake_formation_config with enabled=True requires offline_store_config to be configured", + ): + FeatureGroup.create( + feature_group_name=feature_group_name, + record_identifier_feature_name=record_id_feature, + event_time_feature_name=event_time_feature, + feature_definitions=feature_definitions, + lake_formation_config=lf_config, + # offline_store_config not provided + ) + + @pytest.mark.parametrize( + "feature_group_name,record_id_feature,event_time_feature,s3_uri,database,table", + [ + ("test-fg", "record_id", "event_time", "path1", "db1", "table1"), + ("my_feature_group", "id", "timestamp", "data/features", "feature_db", "feature_table"), + ("fg123", "identifier", "time", "ml/features/v1", "analytics", "features_v1"), + ], + ) + @patch("sagemaker.core.resources.Base.get_sagemaker_client") + def test_validation_error_when_lake_formation_enabled_without_role_arn( + self, + mock_get_client, + feature_group_name, + record_id_feature, + event_time_feature, + s3_uri, + database, + table, + ): + """Test create() raises ValueError when lake_formation_config enabled=True without role_arn.""" + from sagemaker.core.shapes import ( + FeatureDefinition, + OfflineStoreConfig, + S3StorageConfig, + DataCatalogConfig, + ) + + # Mock the SageMaker client + mock_client = MagicMock() + mock_get_client.return_value = mock_client + + # Create feature definitions + feature_definitions = [ + FeatureDefinition(feature_name=record_id_feature, feature_type="String"), + FeatureDefinition(feature_name=event_time_feature, feature_type="String"), + ] + + # Create offline store config + offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig(s3_uri=f"s3://test-bucket/{s3_uri}"), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database=database, table_name=table + ), + ) + + # Create LakeFormationConfig with enabled=True + lf_config = LakeFormationConfig() + lf_config.enabled = True + + # Test with lake_formation_config enabled=True but no role_arn + with pytest.raises( + ValueError, match="lake_formation_config with enabled=True requires role_arn to be specified" + ): + FeatureGroup.create( + feature_group_name=feature_group_name, + record_identifier_feature_name=record_id_feature, + event_time_feature_name=event_time_feature, + feature_definitions=feature_definitions, + offline_store_config=offline_store_config, + lake_formation_config=lf_config, + # role_arn not provided + ) + + + @pytest.mark.parametrize( + "feature_group_name,record_id_feature,event_time_feature,role_arn,s3_uri,database,table,use_slr", + [ + ("test-fg", "record_id", "event_time", "TestRole", "path1", "db1", "table1", True), + ("my_feature_group", "id", "timestamp", "ExecutionRole", "data/features", "feature_db", "feature_table", False), + ("fg123", "identifier", "time", "MyRole123", "ml/features/v1", "analytics", "features_v1", True), + ], + ) + @patch("sagemaker.core.resources.Base.get_sagemaker_client") + @patch.object(FeatureGroup, "get") + @patch.object(FeatureGroup, "wait_for_status") + @patch.object(FeatureGroup, "enable_lake_formation") + def test_use_service_linked_role_extraction_from_config( + self, + mock_enable_lf, + mock_wait, + mock_get, + mock_get_client, + feature_group_name, + record_id_feature, + event_time_feature, + role_arn, + s3_uri, + database, + table, + use_slr, + ): + """ + Test that use_service_linked_role is correctly extracted from lake_formation_config. + + Verifies: + - use_service_linked_role defaults to True when not specified + - use_service_linked_role is passed correctly to enable_lake_formation() + """ + from sagemaker.core.shapes import ( + FeatureDefinition, + OfflineStoreConfig, + S3StorageConfig, + DataCatalogConfig, + ) + + # Mock the SageMaker client + mock_client = MagicMock() + mock_client.create_feature_group.return_value = { + "FeatureGroupArn": "arn:aws:sagemaker:us-west-2:123456789012:feature-group/test" + } + mock_get_client.return_value = mock_client + + # Mock the get method to return a feature group + mock_fg = MagicMock(spec=FeatureGroup) + mock_fg.feature_group_name = feature_group_name + mock_fg.wait_for_status = mock_wait + mock_fg.enable_lake_formation = mock_enable_lf + mock_get.return_value = mock_fg + + # Create feature definitions + feature_definitions = [ + FeatureDefinition(feature_name=record_id_feature, feature_type="String"), + FeatureDefinition(feature_name=event_time_feature, feature_type="String"), + ] + + # Create offline store config + offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig(s3_uri=f"s3://test-bucket/{s3_uri}"), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database=database, table_name=table + ), + ) + + # Build LakeFormationConfig with use_service_linked_role + lf_config = LakeFormationConfig() + lf_config.enabled = True + lf_config.use_service_linked_role = use_slr + # When use_service_linked_role is False, registration_role_arn is required + expected_registration_role = None + if not use_slr: + lf_config.registration_role_arn = "arn:aws:iam::123456789012:role/LFRegistrationRole" + expected_registration_role = "arn:aws:iam::123456789012:role/LFRegistrationRole" + + # Create with lake_formation_config + result = FeatureGroup.create( + feature_group_name=feature_group_name, + record_identifier_feature_name=record_id_feature, + event_time_feature_name=event_time_feature, + feature_definitions=feature_definitions, + offline_store_config=offline_store_config, + role_arn=f"arn:aws:iam::123456789012:role/{role_arn}", + lake_formation_config=lf_config, + ) + + # Verify enable_lake_formation was called with correct use_service_linked_role value + mock_enable_lf.assert_called_once_with( + session=None, + region=None, + use_service_linked_role=use_slr, + registration_role_arn=expected_registration_role, + show_s3_policy=False, + ) + # Verify the feature group was returned + assert result == mock_fg + + +class TestExtractAccountIdFromArn: + """Tests for _extract_account_id_from_arn static method.""" + + def test_extracts_account_id_from_sagemaker_arn(self): + """Test extracting account ID from a SageMaker Feature Group ARN.""" + arn = "arn:aws:sagemaker:us-west-2:123456789012:feature-group/my-feature-group" + result = FeatureGroup._extract_account_id_from_arn(arn) + assert result == "123456789012" + + def test_raises_value_error_for_invalid_arn_too_few_parts(self): + """Test that ValueError is raised for ARN with fewer than 5 colon-separated parts.""" + invalid_arn = "arn:aws:sagemaker:us-west-2" # Only 4 parts + with pytest.raises(ValueError, match="Invalid ARN format"): + FeatureGroup._extract_account_id_from_arn(invalid_arn) + + def test_raises_value_error_for_empty_string(self): + """Test that ValueError is raised for empty string.""" + with pytest.raises(ValueError, match="Invalid ARN format"): + FeatureGroup._extract_account_id_from_arn("") + + def test_raises_value_error_for_non_arn_string(self): + """Test that ValueError is raised for non-ARN string.""" + with pytest.raises(ValueError, match="Invalid ARN format"): + FeatureGroup._extract_account_id_from_arn("not-an-arn") + + def test_raises_value_error_for_s3_uri(self): + """Test that ValueError is raised for S3 URI (not ARN).""" + with pytest.raises(ValueError, match="Invalid ARN format"): + FeatureGroup._extract_account_id_from_arn("s3://my-bucket/my-prefix") + + def test_handles_arn_with_resource_path(self): + """Test extracting account ID from ARN with complex resource path.""" + arn = "arn:aws:sagemaker:us-west-2:123456789012:feature-group/my-fg/version/1" + result = FeatureGroup._extract_account_id_from_arn(arn) + assert result == "123456789012" + + +class TestGetLakeFormationServiceLinkedRoleArn: + """Tests for _get_lake_formation_service_linked_role_arn static method.""" + + def test_generates_correct_service_linked_role_arn(self): + """Test that the method generates the correct service-linked role ARN format.""" + account_id = "123456789012" + result = FeatureGroup._get_lake_formation_service_linked_role_arn(account_id) + expected = "arn:aws:iam::123456789012:role/aws-service-role/lakeformation.amazonaws.com/AWSServiceRoleForLakeFormationDataAccess" + assert result == expected + + def test_uses_region_for_partition(self): + """Test that region is used to determine partition.""" + account_id = "123456789012" + result = FeatureGroup._get_lake_formation_service_linked_role_arn(account_id, region="cn-north-1") + assert result.startswith("arn:aws-cn:iam::") + + + +class TestGenerateS3DenyPolicy: + """Tests for _generate_s3_deny_policy method.""" + + def setup_method(self): + """Set up test fixtures.""" + self.fg = MagicMock(spec=FeatureGroup) + self.fg._generate_s3_deny_policy = FeatureGroup._generate_s3_deny_policy.__get__(self.fg) + + def test_policy_includes_correct_bucket_arn_in_object_statement(self): + """Test that the policy includes correct bucket ARN and prefix in object actions statement.""" + bucket_name = "my-feature-store-bucket" + s3_prefix = "feature-store/data/my-feature-group" + lf_role_arn = "arn:aws:iam::123456789012:role/LakeFormationRole" + fs_role_arn = "arn:aws:iam::123456789012:role/FeatureStoreRole" + + policy = self.fg._generate_s3_deny_policy( + bucket_name=bucket_name, + s3_prefix=s3_prefix, + lake_formation_role_arn=lf_role_arn, + feature_store_role_arn=fs_role_arn, + ) + + # Verify the object actions statement has correct Resource ARN + object_statement = policy["Statement"][0] + expected_resource = f"arn:aws:s3:::{bucket_name}/{s3_prefix}/*" + assert object_statement["Resource"] == expected_resource + + def test_policy_includes_correct_bucket_arn_in_list_statement(self): + """Test that the policy includes correct bucket ARN in ListBucket statement.""" + bucket_name = "my-feature-store-bucket" + s3_prefix = "feature-store/data/my-feature-group" + lf_role_arn = "arn:aws:iam::123456789012:role/LakeFormationRole" + fs_role_arn = "arn:aws:iam::123456789012:role/FeatureStoreRole" + + policy = self.fg._generate_s3_deny_policy( + bucket_name=bucket_name, + s3_prefix=s3_prefix, + lake_formation_role_arn=lf_role_arn, + feature_store_role_arn=fs_role_arn, + ) + + # Verify the ListBucket statement has correct Resource ARN (bucket only) + list_statement = policy["Statement"][1] + expected_resource = f"arn:aws:s3:::{bucket_name}" + assert list_statement["Resource"] == expected_resource + + def test_policy_includes_correct_prefix_condition_in_list_statement(self): + """Test that the policy includes correct prefix condition in ListBucket statement.""" + bucket_name = "my-feature-store-bucket" + s3_prefix = "feature-store/data/my-feature-group" + lf_role_arn = "arn:aws:iam::123456789012:role/LakeFormationRole" + fs_role_arn = "arn:aws:iam::123456789012:role/FeatureStoreRole" + + policy = self.fg._generate_s3_deny_policy( + bucket_name=bucket_name, + s3_prefix=s3_prefix, + lake_formation_role_arn=lf_role_arn, + feature_store_role_arn=fs_role_arn, + ) + + # Verify the ListBucket statement has correct prefix condition + list_statement = policy["Statement"][1] + expected_prefix = f"{s3_prefix}/*" + assert list_statement["Condition"]["StringLike"]["s3:prefix"] == expected_prefix + + def test_policy_preserves_bucket_name_exactly(self): + """Test that bucket name is preserved exactly without modification.""" + # Test with various bucket name formats + test_cases = [ + "simple-bucket", + "bucket.with.dots", + "bucket-with-dashes-123", + "mybucket", + "a" * 63, # Max bucket name length + ] + + for bucket_name in test_cases: + policy = self.fg._generate_s3_deny_policy( + bucket_name=bucket_name, + s3_prefix="prefix", + lake_formation_role_arn="arn:aws:iam::123456789012:role/LFRole", + feature_store_role_arn="arn:aws:iam::123456789012:role/FSRole", + ) + + # Verify bucket name is preserved in both statements + assert bucket_name in policy["Statement"][0]["Resource"] + assert bucket_name in policy["Statement"][1]["Resource"] + + def test_policy_preserves_prefix_exactly(self): + """Test that S3 prefix is preserved exactly without modification.""" + # Test with various prefix formats + test_cases = [ + "simple-prefix", + "path/to/data", + "feature-store/account-id/region/feature-group-name", + "deep/nested/path/structure/data", + "prefix_with_underscores", + "prefix-with-dashes", + ] + + for s3_prefix in test_cases: + policy = self.fg._generate_s3_deny_policy( + bucket_name="test-bucket", + s3_prefix=s3_prefix, + lake_formation_role_arn="arn:aws:iam::123456789012:role/LFRole", + feature_store_role_arn="arn:aws:iam::123456789012:role/FSRole", + ) + + # Verify prefix is preserved in object statement Resource + assert f"{s3_prefix}/*" in policy["Statement"][0]["Resource"] + # Verify prefix is preserved in list statement Condition + assert policy["Statement"][1]["Condition"]["StringLike"]["s3:prefix"] == f"{s3_prefix}/*" + + def test_policy_has_correct_s3_arn_format(self): + """Test that the policy uses correct S3 ARN format (arn:aws:s3:::bucket/path).""" + bucket_name = "test-bucket" + s3_prefix = "test/prefix" + + policy = self.fg._generate_s3_deny_policy( + bucket_name=bucket_name, + s3_prefix=s3_prefix, + lake_formation_role_arn="arn:aws:iam::123456789012:role/LFRole", + feature_store_role_arn="arn:aws:iam::123456789012:role/FSRole", + ) + + # Verify object statement Resource starts with correct ARN prefix + object_resource = policy["Statement"][0]["Resource"] + assert object_resource.startswith("arn:aws:s3:::") + assert object_resource == f"arn:aws:s3:::{bucket_name}/{s3_prefix}/*" + + # Verify list statement Resource is bucket-only ARN + list_resource = policy["Statement"][1]["Resource"] + assert list_resource.startswith("arn:aws:s3:::") + assert list_resource == f"arn:aws:s3:::{bucket_name}" + + def test_policy_structure_validation(self): + """Test that the policy has correct overall structure.""" + policy = self.fg._generate_s3_deny_policy( + bucket_name="test-bucket", + s3_prefix="test/prefix", + lake_formation_role_arn="arn:aws:iam::123456789012:role/LFRole", + feature_store_role_arn="arn:aws:iam::123456789012:role/FSRole", + ) + + # Verify policy version + assert policy["Version"] == "2012-10-17" + + # Verify exactly two statements + assert len(policy["Statement"]) == 2 + + # Verify first statement structure (object actions) + object_statement = policy["Statement"][0] + assert object_statement["Sid"] == "DenyAllAccessToFeatureStorePrefixExceptAllowedPrincipals" + assert object_statement["Effect"] == "Deny" + assert object_statement["Principal"] == "*" + assert "Condition" in object_statement + assert "StringNotEquals" in object_statement["Condition"] + + # Verify second statement structure (list bucket) + list_statement = policy["Statement"][1] + assert list_statement["Sid"] == "DenyListOnPrefixExceptAllowedPrincipals" + assert list_statement["Effect"] == "Deny" + assert list_statement["Principal"] == "*" + assert "Condition" in list_statement + assert "StringLike" in list_statement["Condition"] + assert "StringNotEquals" in list_statement["Condition"] + + def test_policy_includes_both_principals_in_allowed_list(self): + """Test that both Lake Formation role and Feature Store role are in allowed principals.""" + lf_role_arn = "arn:aws:iam::123456789012:role/LakeFormationRole" + fs_role_arn = "arn:aws:iam::123456789012:role/FeatureStoreRole" + + policy = self.fg._generate_s3_deny_policy( + bucket_name="test-bucket", + s3_prefix="test/prefix", + lake_formation_role_arn=lf_role_arn, + feature_store_role_arn=fs_role_arn, + ) + + # Verify both principals in object statement + object_principals = policy["Statement"][0]["Condition"]["StringNotEquals"]["aws:PrincipalArn"] + assert lf_role_arn in object_principals + assert fs_role_arn in object_principals + assert len(object_principals) == 2 + + # Verify both principals in list statement + list_principals = policy["Statement"][1]["Condition"]["StringNotEquals"]["aws:PrincipalArn"] + assert lf_role_arn in list_principals + assert fs_role_arn in list_principals + assert len(list_principals) == 2 + + def test_policy_has_correct_actions_in_each_statement(self): + """Test that each statement has the correct S3 actions.""" + policy = self.fg._generate_s3_deny_policy( + bucket_name="test-bucket", + s3_prefix="test/prefix", + lake_formation_role_arn="arn:aws:iam::123456789012:role/LFRole", + feature_store_role_arn="arn:aws:iam::123456789012:role/FSRole", + ) + + # Verify object statement has correct actions + object_actions = policy["Statement"][0]["Action"] + assert "s3:GetObject" in object_actions + assert "s3:PutObject" in object_actions + assert "s3:DeleteObject" in object_actions + assert len(object_actions) == 3 + + # Verify list statement has correct action + list_action = policy["Statement"][1]["Action"] + assert list_action == "s3:ListBucket" + + + +class TestEnableLakeFormationServiceLinkedRoleInPolicy: + """Tests for service-linked role ARN usage in S3 deny policy generation.""" + + @patch.object(FeatureGroup, "refresh") + @patch.object(FeatureGroup, "_register_s3_with_lake_formation") + @patch.object(FeatureGroup, "_grant_lake_formation_permissions") + @patch.object(FeatureGroup, "_revoke_iam_allowed_principal") + @patch.object(FeatureGroup, "_generate_s3_deny_policy") + @patch("builtins.print") + def test_uses_service_linked_role_arn_when_use_service_linked_role_true( + self, + mock_print, + mock_generate_policy, + mock_revoke, + mock_grant, + mock_register, + mock_refresh, + ): + """ + Test that enable_lake_formation uses the auto-generated service-linked role ARN + when use_service_linked_role=True. + """ + from sagemaker.core.shapes import OfflineStoreConfig, S3StorageConfig, DataCatalogConfig + + fg = FeatureGroup(feature_group_name="test-fg") + fg.offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig( + s3_uri="s3://test-bucket/path", + resolved_output_s3_uri="s3://test-bucket/resolved-path/data", + ), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database="test_db", table_name="test_table" + ), + ) + fg.role_arn = "arn:aws:iam::123456789012:role/FeatureStoreRole" + fg.feature_group_arn = "arn:aws:sagemaker:us-west-2:123456789012:feature-group/test-fg" + fg.feature_group_status = "Created" + + # Mock successful Lake Formation operations + mock_register.return_value = True + mock_grant.return_value = True + mock_revoke.return_value = True + mock_generate_policy.return_value = {"Version": "2012-10-17", "Statement": []} + + # Call with use_service_linked_role=True (default) + fg.enable_lake_formation(use_service_linked_role=True, show_s3_policy=True) + + # Verify _generate_s3_deny_policy was called with the service-linked role ARN + expected_slr_arn = "arn:aws:iam::123456789012:role/aws-service-role/lakeformation.amazonaws.com/AWSServiceRoleForLakeFormationDataAccess" + mock_generate_policy.assert_called_once() + call_kwargs = mock_generate_policy.call_args[1] + assert call_kwargs["lake_formation_role_arn"] == expected_slr_arn + assert call_kwargs["feature_store_role_arn"] == fg.role_arn + + @patch.object(FeatureGroup, "refresh") + @patch.object(FeatureGroup, "_register_s3_with_lake_formation") + @patch.object(FeatureGroup, "_grant_lake_formation_permissions") + @patch.object(FeatureGroup, "_revoke_iam_allowed_principal") + @patch.object(FeatureGroup, "_generate_s3_deny_policy") + @patch("builtins.print") + def test_uses_service_linked_role_arn_by_default( + self, + mock_print, + mock_generate_policy, + mock_revoke, + mock_grant, + mock_register, + mock_refresh, + ): + """ + Test that enable_lake_formation uses the service-linked role ARN by default + (when use_service_linked_role is not explicitly specified). + """ + from sagemaker.core.shapes import OfflineStoreConfig, S3StorageConfig, DataCatalogConfig + + fg = FeatureGroup(feature_group_name="test-fg") + fg.offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig( + s3_uri="s3://test-bucket/path", + resolved_output_s3_uri="s3://test-bucket/resolved-path/data", + ), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database="test_db", table_name="test_table" + ), + ) + fg.role_arn = "arn:aws:iam::987654321098:role/MyFeatureStoreRole" + fg.feature_group_arn = "arn:aws:sagemaker:us-east-1:987654321098:feature-group/test-fg" + fg.feature_group_status = "Created" + + # Mock successful Lake Formation operations + mock_register.return_value = True + mock_grant.return_value = True + mock_revoke.return_value = True + mock_generate_policy.return_value = {"Version": "2012-10-17", "Statement": []} + + # Call without specifying use_service_linked_role (should default to True) + fg.enable_lake_formation(show_s3_policy=True) + + # Verify _generate_s3_deny_policy was called with the service-linked role ARN + expected_slr_arn = "arn:aws:iam::987654321098:role/aws-service-role/lakeformation.amazonaws.com/AWSServiceRoleForLakeFormationDataAccess" + mock_generate_policy.assert_called_once() + call_kwargs = mock_generate_policy.call_args[1] + assert call_kwargs["lake_formation_role_arn"] == expected_slr_arn + + @patch.object(FeatureGroup, "refresh") + @patch.object(FeatureGroup, "_register_s3_with_lake_formation") + @patch.object(FeatureGroup, "_grant_lake_formation_permissions") + @patch.object(FeatureGroup, "_revoke_iam_allowed_principal") + @patch.object(FeatureGroup, "_generate_s3_deny_policy") + @patch("builtins.print") + def test_service_linked_role_arn_uses_correct_account_id( + self, + mock_print, + mock_generate_policy, + mock_revoke, + mock_grant, + mock_register, + mock_refresh, + ): + """ + Test that the service-linked role ARN is generated with the correct account ID + extracted from the Feature Group ARN. + """ + from sagemaker.core.shapes import OfflineStoreConfig, S3StorageConfig, DataCatalogConfig + + # Use a specific account ID to verify it's extracted correctly + account_id = "111222333444" + fg = FeatureGroup(feature_group_name="test-fg") + fg.offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig( + s3_uri="s3://test-bucket/path", + resolved_output_s3_uri="s3://test-bucket/resolved-path/data", + ), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database="test_db", table_name="test_table" + ), + ) + fg.role_arn = f"arn:aws:iam::{account_id}:role/FeatureStoreRole" + fg.feature_group_arn = f"arn:aws:sagemaker:us-west-2:{account_id}:feature-group/test-fg" + fg.feature_group_status = "Created" + + # Mock successful Lake Formation operations + mock_register.return_value = True + mock_grant.return_value = True + mock_revoke.return_value = True + mock_generate_policy.return_value = {"Version": "2012-10-17", "Statement": []} + + # Call with use_service_linked_role=True + fg.enable_lake_formation(use_service_linked_role=True, show_s3_policy=True) + + # Verify the service-linked role ARN contains the correct account ID + expected_slr_arn = f"arn:aws:iam::{account_id}:role/aws-service-role/lakeformation.amazonaws.com/AWSServiceRoleForLakeFormationDataAccess" + mock_generate_policy.assert_called_once() + call_kwargs = mock_generate_policy.call_args[1] + assert call_kwargs["lake_formation_role_arn"] == expected_slr_arn + assert account_id in call_kwargs["lake_formation_role_arn"] + + + +class TestRegistrationRoleArnUsedWhenServiceLinkedRoleFalse: + """Tests for verifying registration_role_arn is used when use_service_linked_role=False.""" + + @patch.object(FeatureGroup, "refresh") + @patch.object(FeatureGroup, "_register_s3_with_lake_formation") + @patch.object(FeatureGroup, "_grant_lake_formation_permissions") + @patch.object(FeatureGroup, "_revoke_iam_allowed_principal") + @patch.object(FeatureGroup, "_generate_s3_deny_policy") + @patch("builtins.print") + def test_uses_registration_role_arn_when_use_service_linked_role_false( + self, + mock_print, + mock_generate_policy, + mock_revoke, + mock_grant, + mock_register, + mock_refresh, + ): + """ + Test that when use_service_linked_role=False, the registration_role_arn is used + in the S3 deny policy instead of the auto-generated service-linked role ARN. + """ + from sagemaker.core.shapes import OfflineStoreConfig, S3StorageConfig, DataCatalogConfig + + # Set up Feature Group with required configuration + fg = FeatureGroup(feature_group_name="test-fg") + fg.offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig( + s3_uri="s3://test-bucket/path", + resolved_output_s3_uri="s3://test-bucket/resolved-path/data", + ), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database="test_db", table_name="test_table" + ), + ) + fg.role_arn = "arn:aws:iam::123456789012:role/FeatureStoreRole" + fg.feature_group_arn = "arn:aws:sagemaker:us-west-2:123456789012:feature-group/test-fg" + fg.feature_group_status = "Created" + + # Mock successful Lake Formation operations + mock_register.return_value = True + mock_grant.return_value = True + mock_revoke.return_value = True + mock_generate_policy.return_value = {"Version": "2012-10-17", "Statement": []} + + # Custom registration role ARN + custom_registration_role = "arn:aws:iam::123456789012:role/CustomLakeFormationRole" + + # Call with use_service_linked_role=False and registration_role_arn + fg.enable_lake_formation( + use_service_linked_role=False, + registration_role_arn=custom_registration_role, + show_s3_policy=True, + ) + + # Verify _generate_s3_deny_policy was called with the custom registration role ARN + mock_generate_policy.assert_called_once() + call_kwargs = mock_generate_policy.call_args[1] + assert call_kwargs["lake_formation_role_arn"] == custom_registration_role + + # Verify it's NOT the service-linked role ARN + service_linked_role_pattern = "aws-service-role/lakeformation.amazonaws.com" + assert service_linked_role_pattern not in call_kwargs["lake_formation_role_arn"] + + @patch.object(FeatureGroup, "refresh") + @patch.object(FeatureGroup, "_register_s3_with_lake_formation") + @patch.object(FeatureGroup, "_grant_lake_formation_permissions") + @patch.object(FeatureGroup, "_revoke_iam_allowed_principal") + @patch.object(FeatureGroup, "_generate_s3_deny_policy") + @patch("builtins.print") + def test_registration_role_arn_passed_to_s3_registration( + self, + mock_print, + mock_generate_policy, + mock_revoke, + mock_grant, + mock_register, + mock_refresh, + ): + """ + Test that when use_service_linked_role=False, the registration_role_arn is also + passed to _register_s3_with_lake_formation. + """ + from sagemaker.core.shapes import OfflineStoreConfig, S3StorageConfig, DataCatalogConfig + + # Set up Feature Group with required configuration + fg = FeatureGroup(feature_group_name="test-fg") + fg.offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig( + s3_uri="s3://test-bucket/path", + resolved_output_s3_uri="s3://test-bucket/resolved-path/data", + ), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database="test_db", table_name="test_table" + ), + ) + fg.role_arn = "arn:aws:iam::123456789012:role/FeatureStoreRole" + fg.feature_group_arn = "arn:aws:sagemaker:us-west-2:123456789012:feature-group/test-fg" + fg.feature_group_status = "Created" + + # Mock successful Lake Formation operations + mock_register.return_value = True + mock_grant.return_value = True + mock_revoke.return_value = True + mock_generate_policy.return_value = {"Version": "2012-10-17", "Statement": []} + + # Custom registration role ARN + custom_registration_role = "arn:aws:iam::123456789012:role/CustomLakeFormationRole" + + # Call with use_service_linked_role=False and registration_role_arn + fg.enable_lake_formation( + use_service_linked_role=False, + registration_role_arn=custom_registration_role, + show_s3_policy=True, + ) + + # Verify _register_s3_with_lake_formation was called with the correct parameters + mock_register.assert_called_once() + call_args = mock_register.call_args + assert call_args[1]["use_service_linked_role"] == False + assert call_args[1]["role_arn"] == custom_registration_role + + @patch.object(FeatureGroup, "refresh") + @patch.object(FeatureGroup, "_register_s3_with_lake_formation") + @patch.object(FeatureGroup, "_grant_lake_formation_permissions") + @patch.object(FeatureGroup, "_revoke_iam_allowed_principal") + @patch.object(FeatureGroup, "_generate_s3_deny_policy") + @patch("builtins.print") + def test_different_registration_role_arns_produce_different_policies( + self, + mock_print, + mock_generate_policy, + mock_revoke, + mock_grant, + mock_register, + mock_refresh, + ): + """ + Test that different registration_role_arn values result in different + lake_formation_role_arn values in the generated policy. + """ + from sagemaker.core.shapes import OfflineStoreConfig, S3StorageConfig, DataCatalogConfig + + # Set up Feature Group with required configuration + fg = FeatureGroup(feature_group_name="test-fg") + fg.offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig( + s3_uri="s3://test-bucket/path", + resolved_output_s3_uri="s3://test-bucket/resolved-path/data", + ), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database="test_db", table_name="test_table" + ), + ) + fg.role_arn = "arn:aws:iam::123456789012:role/FeatureStoreRole" + fg.feature_group_arn = "arn:aws:sagemaker:us-west-2:123456789012:feature-group/test-fg" + fg.feature_group_status = "Created" + + # Mock successful Lake Formation operations + mock_register.return_value = True + mock_grant.return_value = True + mock_revoke.return_value = True + mock_generate_policy.return_value = {"Version": "2012-10-17", "Statement": []} + + # First call with one registration role + first_role = "arn:aws:iam::123456789012:role/FirstLakeFormationRole" + fg.enable_lake_formation( + use_service_linked_role=False, + registration_role_arn=first_role, + show_s3_policy=True, + ) + + first_call_kwargs = mock_generate_policy.call_args[1] + first_lf_role = first_call_kwargs["lake_formation_role_arn"] + + # Reset mocks + mock_generate_policy.reset_mock() + mock_register.reset_mock() + mock_grant.reset_mock() + mock_revoke.reset_mock() + + # Second call with different registration role + second_role = "arn:aws:iam::123456789012:role/SecondLakeFormationRole" + fg.enable_lake_formation( + use_service_linked_role=False, + registration_role_arn=second_role, + show_s3_policy=True, + ) + + second_call_kwargs = mock_generate_policy.call_args[1] + second_lf_role = second_call_kwargs["lake_formation_role_arn"] + + # Verify different roles were used + assert first_lf_role == first_role + assert second_lf_role == second_role + assert first_lf_role != second_lf_role + + + +class TestPolicyPrintedWithClearInstructions: + """Tests for verifying the S3 deny policy is printed with clear instructions.""" + + @patch.object(FeatureGroup, "refresh") + @patch.object(FeatureGroup, "_register_s3_with_lake_formation") + @patch.object(FeatureGroup, "_grant_lake_formation_permissions") + @patch.object(FeatureGroup, "_revoke_iam_allowed_principal") + @patch("builtins.print") + def test_policy_printed_with_header_and_instructions( + self, + mock_print, + mock_revoke, + mock_grant, + mock_register, + mock_refresh, + ): + """ + Test that enable_lake_formation prints the S3 deny policy with clear + header and instructions for the user. + """ + from sagemaker.core.shapes import OfflineStoreConfig, S3StorageConfig, DataCatalogConfig + + # Set up Feature Group with required configuration + fg = FeatureGroup(feature_group_name="test-fg") + fg.offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig( + s3_uri="s3://test-bucket/path", + resolved_output_s3_uri="s3://test-bucket/resolved-path/data", + ), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database="test_db", table_name="test_table" + ), + ) + fg.role_arn = "arn:aws:iam::123456789012:role/FeatureStoreRole" + fg.feature_group_arn = "arn:aws:sagemaker:us-west-2:123456789012:feature-group/test-fg" + fg.feature_group_status = "Created" + + # Mock successful Lake Formation operations + mock_register.return_value = True + mock_grant.return_value = True + mock_revoke.return_value = True + + # Call enable_lake_formation with show_s3_policy=True + fg.enable_lake_formation(show_s3_policy=True) + + # Collect all print calls + print_calls = [str(call) for call in mock_print.call_args_list] + all_printed_text = " ".join(print_calls) + + # Verify header is printed + assert "S3 Bucket Policy" in all_printed_text, "Header should mention 'S3 Bucket Policy'" + + # Verify instructions are printed + assert ( + "Lake Formation" in all_printed_text + or "deny policy" in all_printed_text + ), "Instructions should mention Lake Formation or deny policy" + + # Verify bucket name is printed + assert "test-bucket" in all_printed_text, "Bucket name should be printed" + + # Verify note about merging with existing policy is printed + assert ( + "Merge" in all_printed_text or "existing" in all_printed_text + ), "Note about merging with existing policy should be printed" + + @patch.object(FeatureGroup, "refresh") + @patch.object(FeatureGroup, "_register_s3_with_lake_formation") + @patch.object(FeatureGroup, "_grant_lake_formation_permissions") + @patch.object(FeatureGroup, "_revoke_iam_allowed_principal") + @patch("builtins.print") + def test_policy_json_is_printed( + self, + mock_print, + mock_revoke, + mock_grant, + mock_register, + mock_refresh, + ): + """ + Test that the S3 deny policy JSON is printed to the console when show_s3_policy=True. + """ + from sagemaker.core.shapes import OfflineStoreConfig, S3StorageConfig, DataCatalogConfig + + # Set up Feature Group with required configuration + fg = FeatureGroup(feature_group_name="test-fg") + fg.offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig( + s3_uri="s3://test-bucket/path", + resolved_output_s3_uri="s3://test-bucket/resolved-path/data", + ), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database="test_db", table_name="test_table" + ), + ) + fg.role_arn = "arn:aws:iam::123456789012:role/FeatureStoreRole" + fg.feature_group_arn = "arn:aws:sagemaker:us-west-2:123456789012:feature-group/test-fg" + fg.feature_group_status = "Created" + + # Mock successful Lake Formation operations + mock_register.return_value = True + mock_grant.return_value = True + mock_revoke.return_value = True + + # Call enable_lake_formation with show_s3_policy=True + fg.enable_lake_formation(show_s3_policy=True) + + # Collect all print calls + print_calls = [str(call) for call in mock_print.call_args_list] + all_printed_text = " ".join(print_calls) + + # Verify policy JSON structure elements are printed + assert "Version" in all_printed_text, "Policy JSON should contain 'Version'" + assert "Statement" in all_printed_text, "Policy JSON should contain 'Statement'" + assert "Effect" in all_printed_text, "Policy JSON should contain 'Effect'" + assert "Deny" in all_printed_text, "Policy JSON should contain 'Deny' effect" + + @patch.object(FeatureGroup, "refresh") + @patch.object(FeatureGroup, "_register_s3_with_lake_formation") + @patch.object(FeatureGroup, "_grant_lake_formation_permissions") + @patch.object(FeatureGroup, "_revoke_iam_allowed_principal") + @patch("builtins.print") + def test_policy_printed_only_after_successful_setup( + self, + mock_print, + mock_revoke, + mock_grant, + mock_register, + mock_refresh, + ): + """ + Test that the S3 deny policy is only printed after all Lake Formation + phases complete successfully. + """ + from sagemaker.core.shapes import OfflineStoreConfig, S3StorageConfig, DataCatalogConfig + + # Set up Feature Group with required configuration + fg = FeatureGroup(feature_group_name="test-fg") + fg.offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig( + s3_uri="s3://test-bucket/path", + resolved_output_s3_uri="s3://test-bucket/resolved-path/data", + ), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database="test_db", table_name="test_table" + ), + ) + fg.role_arn = "arn:aws:iam::123456789012:role/FeatureStoreRole" + fg.feature_group_arn = "arn:aws:sagemaker:us-west-2:123456789012:feature-group/test-fg" + fg.feature_group_status = "Created" + + # Mock Phase 1 failure + mock_register.side_effect = Exception("Phase 1 failed") + mock_grant.return_value = True + mock_revoke.return_value = True + + # Call enable_lake_formation with show_s3_policy=True - should fail + with pytest.raises(RuntimeError): + fg.enable_lake_formation(show_s3_policy=True) + + # Collect all print calls + print_calls = [str(call) for call in mock_print.call_args_list] + all_printed_text = " ".join(print_calls) + + # Verify policy was NOT printed when setup failed + assert "S3 Bucket Policy" not in all_printed_text, "Policy should not be printed when setup fails" + + # Reset mocks + mock_print.reset_mock() + mock_register.reset_mock() + mock_register.side_effect = None + mock_register.return_value = True + + # Mock Phase 2 failure + mock_grant.side_effect = Exception("Phase 2 failed") + + # Call enable_lake_formation with show_s3_policy=True - should fail + with pytest.raises(RuntimeError): + fg.enable_lake_formation(show_s3_policy=True) + + # Collect all print calls + print_calls = [str(call) for call in mock_print.call_args_list] + all_printed_text = " ".join(print_calls) + + # Verify policy was NOT printed when setup fails at Phase 2 + assert "S3 Bucket Policy" not in all_printed_text, "Policy should not be printed when Phase 2 fails" + + # Reset mocks + mock_print.reset_mock() + mock_grant.reset_mock() + mock_grant.side_effect = None + mock_grant.return_value = True + + # Mock Phase 3 failure + mock_revoke.side_effect = Exception("Phase 3 failed") + + # Call enable_lake_formation with show_s3_policy=True - should fail + with pytest.raises(RuntimeError): + fg.enable_lake_formation(show_s3_policy=True) + + # Collect all print calls + print_calls = [str(call) for call in mock_print.call_args_list] + all_printed_text = " ".join(print_calls) + + # Verify policy was NOT printed when setup fails at Phase 3 + assert "S3 Bucket Policy" not in all_printed_text, "Policy should not be printed when Phase 3 fails" + + @patch.object(FeatureGroup, "refresh") + @patch.object(FeatureGroup, "_register_s3_with_lake_formation") + @patch.object(FeatureGroup, "_grant_lake_formation_permissions") + @patch.object(FeatureGroup, "_revoke_iam_allowed_principal") + @patch("builtins.print") + def test_policy_includes_both_allowed_principals( + self, + mock_print, + mock_revoke, + mock_grant, + mock_register, + mock_refresh, + ): + """ + Test that the printed policy includes both the Lake Formation role + and the Feature Store execution role as allowed principals. + """ + from sagemaker.core.shapes import OfflineStoreConfig, S3StorageConfig, DataCatalogConfig + + # Set up Feature Group with required configuration + fg = FeatureGroup(feature_group_name="test-fg") + fg.offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig( + s3_uri="s3://test-bucket/path", + resolved_output_s3_uri="s3://test-bucket/resolved-path/data", + ), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database="test_db", table_name="test_table" + ), + ) + feature_store_role = "arn:aws:iam::123456789012:role/FeatureStoreRole" + fg.role_arn = feature_store_role + fg.feature_group_arn = "arn:aws:sagemaker:us-west-2:123456789012:feature-group/test-fg" + fg.feature_group_status = "Created" + + # Mock successful Lake Formation operations + mock_register.return_value = True + mock_grant.return_value = True + mock_revoke.return_value = True + + # Call enable_lake_formation with service-linked role and show_s3_policy=True + fg.enable_lake_formation(use_service_linked_role=True, show_s3_policy=True) + + # Collect all print calls + print_calls = [str(call) for call in mock_print.call_args_list] + all_printed_text = " ".join(print_calls) + + # Verify Feature Store role is in the printed output + assert feature_store_role in all_printed_text, "Feature Store role should be in printed policy" + + # Verify Lake Formation service-linked role pattern is in the printed output + assert "AWSServiceRoleForLakeFormationDataAccess" in all_printed_text, \ + "Lake Formation service-linked role should be in printed policy" + + @patch.object(FeatureGroup, "refresh") + @patch.object(FeatureGroup, "_register_s3_with_lake_formation") + @patch.object(FeatureGroup, "_grant_lake_formation_permissions") + @patch.object(FeatureGroup, "_revoke_iam_allowed_principal") + @patch("builtins.print") + def test_policy_not_printed_when_show_s3_policy_false( + self, + mock_print, + mock_revoke, + mock_grant, + mock_register, + mock_refresh, + ): + """ + Test that the S3 deny policy is NOT printed when show_s3_policy=False (default). + """ + from sagemaker.core.shapes import OfflineStoreConfig, S3StorageConfig, DataCatalogConfig + + # Set up Feature Group with required configuration + fg = FeatureGroup(feature_group_name="test-fg") + fg.offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig( + s3_uri="s3://test-bucket/path", + resolved_output_s3_uri="s3://test-bucket/resolved-path/data", + ), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database="test_db", table_name="test_table" + ), + ) + fg.role_arn = "arn:aws:iam::123456789012:role/FeatureStoreRole" + fg.feature_group_arn = "arn:aws:sagemaker:us-west-2:123456789012:feature-group/test-fg" + fg.feature_group_status = "Created" + + # Mock successful Lake Formation operations + mock_register.return_value = True + mock_grant.return_value = True + mock_revoke.return_value = True + + # Call enable_lake_formation with show_s3_policy=False (default) + fg.enable_lake_formation(show_s3_policy=False) + + # Collect all print calls + print_calls = [str(call) for call in mock_print.call_args_list] + all_printed_text = " ".join(print_calls) + + # Verify policy was NOT printed + assert "S3 Bucket Policy" not in all_printed_text, "Policy should not be printed when show_s3_policy=False" + assert "Version" not in all_printed_text, "Policy JSON should not be printed when show_s3_policy=False" + + @patch.object(FeatureGroup, "refresh") + @patch.object(FeatureGroup, "_register_s3_with_lake_formation") + @patch.object(FeatureGroup, "_grant_lake_formation_permissions") + @patch.object(FeatureGroup, "_revoke_iam_allowed_principal") + @patch("builtins.print") + def test_policy_not_printed_by_default( + self, + mock_print, + mock_revoke, + mock_grant, + mock_register, + mock_refresh, + ): + """ + Test that the S3 deny policy is NOT printed by default (when show_s3_policy is not specified). + """ + from sagemaker.core.shapes import OfflineStoreConfig, S3StorageConfig, DataCatalogConfig + + # Set up Feature Group with required configuration + fg = FeatureGroup(feature_group_name="test-fg") + fg.offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig( + s3_uri="s3://test-bucket/path", + resolved_output_s3_uri="s3://test-bucket/resolved-path/data", + ), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database="test_db", table_name="test_table" + ), + ) + fg.role_arn = "arn:aws:iam::123456789012:role/FeatureStoreRole" + fg.feature_group_arn = "arn:aws:sagemaker:us-west-2:123456789012:feature-group/test-fg" + fg.feature_group_status = "Created" + + # Mock successful Lake Formation operations + mock_register.return_value = True + mock_grant.return_value = True + mock_revoke.return_value = True + + # Call enable_lake_formation without specifying show_s3_policy (should default to False) + fg.enable_lake_formation() + + # Collect all print calls + print_calls = [str(call) for call in mock_print.call_args_list] + all_printed_text = " ".join(print_calls) + + # Verify policy was NOT printed + assert "S3 Bucket Policy" not in all_printed_text, "Policy should not be printed by default" + assert "Version" not in all_printed_text, "Policy JSON should not be printed by default" From a984e4704520df3416b5028a4674d385e8f97f84 Mon Sep 17 00:00:00 2001 From: Basssem Halim Date: Wed, 28 Jan 2026 17:06:06 -0800 Subject: [PATCH 04/10] docs(feature_store): Add Lake Formation governance example notebook --- .../v3-feature-store-lake-formation.ipynb | 594 ++++++++++++++++++ 1 file changed, 594 insertions(+) create mode 100644 v3-examples/ml-ops-examples/v3-feature-store-lake-formation.ipynb diff --git a/v3-examples/ml-ops-examples/v3-feature-store-lake-formation.ipynb b/v3-examples/ml-ops-examples/v3-feature-store-lake-formation.ipynb new file mode 100644 index 0000000000..4f6efa03c4 --- /dev/null +++ b/v3-examples/ml-ops-examples/v3-feature-store-lake-formation.ipynb @@ -0,0 +1,594 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Feature Store with Lake Formation Governance\n", + "\n", + "This notebook demonstrates two workflows for using SageMaker Feature Store with Lake Formation governance:\n", + "\n", + "1. **Example 1**: Create Feature Group with Lake Formation enabled at creation time\n", + "2. **Example 2**: Create Feature Group first, then enable Lake Formation separately\n", + "\n", + "Both workflows include record ingestion to verify everything works end-to-end.\n", + "\n", + "## Prerequisites\n", + "\n", + "- AWS credentials configured with permissions for SageMaker, S3, Glue, and Lake Formation\n", + "- An S3 bucket for the offline store\n", + "- An IAM role with Feature Store permissions\n", + "\n", + "## Required IAM Permissions\n", + "\n", + "TODO: Add the required IAM policy document here\n", + "\n", + "```json\n", + "{\n", + " \"Version\": \"2012-10-17\",\n", + " \"Statement\": [\n", + " // TODO: Add required permissions\n", + " 1. FS permissions to create FG\n", + " 2. LF permissons\n", + " ]\n", + "}\n", + "```\n", + "\n", + "## Lake Formation Admin Requirements\n", + "\n", + "The person enabling Lake Formation governance must be a **Data Lake Administrator** in Lake Formation. There are two options depending on your organization's setup:\n", + "\n", + "### Option 1: Single User (Data Lake Admin + Feature Store Admin)\n", + "\n", + "If the caller has both:\n", + "- Data Lake Administrator privileges in Lake Formation\n", + "- Permissions to create Feature Groups in SageMaker\n", + "\n", + "Then they can use `FeatureGroup.create()` with `lake_formation_config` to enable governance at creation time (Example 1).\n", + "\n", + "### Option 2: Separate Roles (ML Engineer + Data Lake Admin)\n", + "\n", + "If the person creating the Feature Group is different from the Data Lake Administrator:\n", + "\n", + "1. **ML Engineer** creates the Feature Group without Lake Formation using `FeatureGroup.create()`\n", + "2. **Data Lake Admin** later enables governance by calling `enable_lake_formation()` on the existing Feature Group (Example 2)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Setup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "from datetime import datetime\n", + "from datetime import timezone\n", + "\n", + "import boto3\n", + "from botocore.exceptions import ClientError\n", + "\n", + "# Import the FeatureGroup with Lake Formation support\n", + "from sagemaker.mlops.feature_store.feature_group import FeatureGroup, LakeFormationConfig\n", + "from sagemaker.core.shapes import (\n", + " FeatureDefinition,\n", + " FeatureValue,\n", + " OfflineStoreConfig,\n", + " OnlineStoreConfig,\n", + " S3StorageConfig,\n", + ")\n", + "from sagemaker.core.helper.session_helper import Session as SageMakerSession, get_execution_role" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Configuration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Use SageMaker session to get default bucket and execution role\n", + "sagemaker_session = SageMakerSession()\n", + "S3_BUCKET = sagemaker_session.default_bucket()\n", + "ROLE_ARN = get_execution_role(sagemaker_session)\n", + "REGION = sagemaker_session.boto_session.region_name\n", + "\n", + "print(f\"S3 Bucket: {S3_BUCKET}\")\n", + "print(f\"Role ARN: {ROLE_ARN}\")\n", + "print(f\"Region: {REGION}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Common Feature Definitions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "feature_definitions = [\n", + " FeatureDefinition(feature_name=\"customer_id\", feature_type=\"String\"),\n", + " FeatureDefinition(feature_name=\"event_time\", feature_type=\"String\"),\n", + " FeatureDefinition(feature_name=\"age\", feature_type=\"Integral\"),\n", + " FeatureDefinition(feature_name=\"total_purchases\", feature_type=\"Integral\"),\n", + " FeatureDefinition(feature_name=\"avg_order_value\", feature_type=\"Fractional\"),\n", + "]\n", + "\n", + "print(\"Feature Definitions:\")\n", + "for fd in feature_definitions:\n", + " print(f\" - {fd.feature_name}: {fd.feature_type}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Helper Function: Ingest Records" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def ingest_sample_records(feature_group, num_records=3):\n", + " \"\"\"\n", + " Ingest sample records into the Feature Group.\n", + " \n", + " Args:\n", + " feature_group: The FeatureGroup to ingest records into\n", + " num_records: Number of sample records to ingest\n", + " \"\"\"\n", + " print(f\"\\nIngesting {num_records} sample records...\")\n", + " \n", + " for i in range(num_records):\n", + " event_time = datetime.now(timezone.utc).isoformat()\n", + " record = [\n", + " FeatureValue(feature_name=\"customer_id\", value_as_string=f\"cust_{i+1}\"),\n", + " FeatureValue(feature_name=\"event_time\", value_as_string=event_time),\n", + " FeatureValue(feature_name=\"age\", value_as_string=str(25 + i * 5)),\n", + " FeatureValue(feature_name=\"total_purchases\", value_as_string=str(10 + i * 3)),\n", + " FeatureValue(feature_name=\"avg_order_value\", value_as_string=str(50.0 + i * 10.5)),\n", + " ]\n", + " \n", + " feature_group.put_record(record=record)\n", + " print(f\" Ingested record for customer: cust_{i+1}\")\n", + " \n", + " print(f\"Successfully ingested {num_records} records!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Helper Function: Cleanup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def cleanup_feature_group(fg):\n", + " \"\"\"\n", + " Delete a FeatureGroup and its associated Glue table.\n", + " \n", + " Args:\n", + " fg: The FeatureGroup to delete.\n", + " \"\"\"\n", + " try:\n", + " # Delete the Glue table if it exists\n", + " if fg.offline_store_config is not None:\n", + " try:\n", + " fg.refresh() # Ensure we have latest config\n", + " data_catalog_config = fg.offline_store_config.data_catalog_config\n", + " if data_catalog_config is not None:\n", + " database_name = data_catalog_config.database\n", + " table_name = data_catalog_config.table_name\n", + "\n", + " if database_name and table_name:\n", + " glue_client = boto3.client(\"glue\")\n", + " try:\n", + " glue_client.delete_table(DatabaseName=database_name, Name=table_name)\n", + " print(f\"Deleted Glue table: {database_name}.{table_name}\")\n", + " except ClientError as e:\n", + " # Ignore if table doesn't exist\n", + " if e.response[\"Error\"][\"Code\"] != \"EntityNotFoundException\":\n", + " raise\n", + " except Exception as e:\n", + " # Don't fail cleanup if Glue table deletion fails\n", + " print(f\"Warning: Could not delete Glue table: {e}\")\n", + "\n", + " # Delete the FeatureGroup\n", + " fg.delete()\n", + " print(f\"Deleted Feature Group: {fg.feature_group_name}\")\n", + " except ClientError as e:\n", + " print(f\"Error during cleanup: {e}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "# Example 1: Create Feature Group with Lake Formation Enabled\n", + "\n", + "This example creates a Feature Group with Lake Formation governance enabled at creation time using `LakeFormationConfig`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Generate unique name for example 1\n", + "timestamp = datetime.now().strftime(\"%Y%m%d%H%M%S\")\n", + "FG_NAME_WORKFLOW1 = f\"lf-demo-workflow1-{timestamp}\"\n", + "\n", + "print(f\"Example 1 Feature Group: {FG_NAME_WORKFLOW1}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Configure online and offline stores\n", + "online_store_config = OnlineStoreConfig(enable_online_store=True)\n", + "\n", + "offline_store_config_1 = OfflineStoreConfig(\n", + " s3_storage_config=S3StorageConfig(\n", + " s3_uri=f\"s3://{S3_BUCKET}/feature-store-demo/\"\n", + " )\n", + ")\n", + "\n", + "# Configure Lake Formation - enabled at creation\n", + "lake_formation_config = LakeFormationConfig()\n", + "lake_formation_config.enabled = True\n", + "lake_formation_config.use_service_linked_role = True\n", + "lake_formation_config.show_s3_policy = True\n", + "\n", + "print(\"Store Config:\")\n", + "print(f\" Online Store: enabled\")\n", + "print(f\" Offline Store S3: s3://{S3_BUCKET}/feature-store-demo/\")\n", + "print(\"\\nLake Formation Config:\")\n", + "print(f\" enabled: {lake_formation_config.enabled}\")\n", + "print(f\" use_service_linked_role: {lake_formation_config.use_service_linked_role}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create Feature Group with Lake Formation enabled\n", + "print(\"Creating Feature Group with Lake Formation enabled...\")\n", + "print(\"This will:\")\n", + "print(\" 1. Create the Feature Group with online + offline stores\")\n", + "print(\" 2. Wait for 'Created' status\")\n", + "print(\" 3. Register S3 with Lake Formation\")\n", + "print(\" 4. Grant permissions to execution role\")\n", + "print(\" 5. Revoke IAMAllowedPrincipal permissions\")\n", + "print()\n", + "\n", + "fg_workflow1 = FeatureGroup.create(\n", + " feature_group_name=FG_NAME_WORKFLOW1,\n", + " record_identifier_feature_name=\"customer_id\",\n", + " event_time_feature_name=\"event_time\",\n", + " feature_definitions=feature_definitions,\n", + " online_store_config=online_store_config,\n", + " offline_store_config=offline_store_config_1,\n", + " role_arn=ROLE_ARN,\n", + " description=\"Workflow 1: Lake Formation enabled at creation\",\n", + " lake_formation_config=lake_formation_config, # new field\n", + " region=REGION,\n", + ")\n", + "\n", + "print(f\"\\nFeature Group created: {fg_workflow1.feature_group_name}\")\n", + "print(f\"Status: {fg_workflow1.feature_group_status}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Verify Feature Group status\n", + "fg_workflow1.refresh()\n", + "print(f\"Feature Group: {fg_workflow1.feature_group_name}\")\n", + "print(f\"Status: {fg_workflow1.feature_group_status}\")\n", + "print(f\"ARN: {fg_workflow1.feature_group_arn}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Ingest sample records to verify everything works\n", + "ingest_sample_records(fg_workflow1, num_records=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Retrieve a sample record from the online store\n", + "print(\"Retrieving record for customer 'cust_1' from online store...\")\n", + "response = fg_workflow1.get_record(record_identifier_value_as_string=\"cust_1\")\n", + "\n", + "print(f\"\\nRecord retrieved successfully!\")\n", + "print(f\"Features:\")\n", + "for feature in response.record:\n", + " print(f\" {feature.feature_name}: {feature.value_as_string}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "# Example 2: Create Feature Group, Then Enable Lake Formation\n", + "\n", + "This example creates a Feature Group first without Lake Formation, then enables it separately using `enable_lake_formation()`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Generate unique name for example 2\n", + "timestamp = datetime.now().strftime(\"%Y%m%d%H%M%S\")\n", + "FG_NAME_WORKFLOW2 = f\"lf-demo-workflow2-{timestamp}\"\n", + "\n", + "print(f\"Example 2 Feature Group: {FG_NAME_WORKFLOW2}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Configure online and offline stores\n", + "online_store_config_2 = OnlineStoreConfig(enable_online_store=True)\n", + "\n", + "offline_store_config_2 = OfflineStoreConfig(\n", + " s3_storage_config=S3StorageConfig(\n", + " s3_uri=f\"s3://{S3_BUCKET}/feature-store-demo/\"\n", + " ),\n", + " table_format=\"Iceberg\"\n", + ")\n", + "\n", + "# Step 1: Create Feature Group WITHOUT Lake Formation\n", + "print(\"Step 1: Creating Feature Group without Lake Formation...\")\n", + "\n", + "fg_workflow2 = FeatureGroup.create(\n", + " feature_group_name=FG_NAME_WORKFLOW2,\n", + " record_identifier_feature_name=\"customer_id\",\n", + " event_time_feature_name=\"event_time\",\n", + " feature_definitions=feature_definitions,\n", + " online_store_config=online_store_config_2,\n", + " offline_store_config=offline_store_config_2,\n", + " role_arn=ROLE_ARN,\n", + " description=\"Workflow 2: Lake Formation enabled after creation\",\n", + " region=REGION,\n", + ")\n", + "\n", + "print(f\"Feature Group created: {fg_workflow2.feature_group_name}\")\n", + "print(f\"Status: {fg_workflow2.feature_group_status}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Step 2: Wait for Feature Group to be ready\n", + "print(\"Step 2: Waiting for Feature Group to reach 'Created' status...\")\n", + "fg_workflow2.wait_for_status(target_status=\"Created\", poll=10, timeout=300)\n", + "print(f\"Status: {fg_workflow2.feature_group_status}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Step 3: Enable Lake Formation governance\n", + "print(\"Step 3: Enabling Lake Formation governance...\")\n", + "print(\"This will:\")\n", + "print(\" 1. Register S3 with Lake Formation\")\n", + "print(\" 2. Grant permissions to execution role\")\n", + "print(\" 3. Revoke IAMAllowedPrincipal permissions\")\n", + "print()\n", + "\n", + "result = fg_workflow2.enable_lake_formation( # new method\n", + " use_service_linked_role=True\n", + ")\n", + "\n", + "print(f\"\\nLake Formation setup results:\")\n", + "print(f\" s3_registration: {result['s3_registration']}\")\n", + "print(f\" permissions_granted: {result['permissions_granted']}\")\n", + "print(f\" iam_principal_revoked: {result['iam_principal_revoked']}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Step 4: Ingest sample records to verify everything works\n", + "print(\"Step 4: Ingesting records to verify Lake Formation setup...\")\n", + "ingest_sample_records(fg_workflow2, num_records=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Step 5: Retrieve a sample record from the online store\n", + "print(\"Step 5: Retrieving record for customer 'cust_1' from online store...\")\n", + "response = fg_workflow2.get_record(record_identifier_value_as_string=\"cust_1\")\n", + "\n", + "print(f\"\\nRecord retrieved successfully!\")\n", + "print(f\"Features:\")\n", + "for feature in response.record:\n", + " print(f\" {feature.feature_name}: {feature.value_as_string}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Verify Feature Group status\n", + "fg_workflow2.refresh()\n", + "print(f\"Feature Group: {fg_workflow2.feature_group_name}\")\n", + "print(f\"Status: {fg_workflow2.feature_group_status}\")\n", + "print(f\"ARN: {fg_workflow2.feature_group_arn}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "# Cleanup\n", + "\n", + "Delete the Feature Groups and associated Glue tables created in this demo." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Uncomment to delete the Feature Groups\n", + "cleanup_feature_group(fg_workflow1)\n", + "# cleanup_feature_group(fg_workflow2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "# Summary\n", + "\n", + "This notebook demonstrated two workflows:\n", + "\n", + "**Example 1: Lake Formation at Creation**\n", + "- Use `LakeFormationConfig` with `enabled=True` in `FeatureGroup.create()`\n", + "- Lake Formation is automatically configured after Feature Group creation\n", + "- Both online and offline stores enabled\n", + "\n", + "**Example 2: Enable Lake Formation Later**\n", + "- Create Feature Group normally without Lake Formation\n", + "- Call `enable_lake_formation()` method after creation\n", + "- More control over when Lake Formation is enabled\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "# FAQ:\n", + "\n", + "## What is the S3 deny policy for?\n", + "\n", + "When you enable Lake Formation governance, you control access to data through Lake Formation permissions. However, **IAM roles that already have direct S3 access will continue to have access** to the underlying data files, bypassing Lake Formation entirely.\n", + "\n", + "The S3 deny policy closes this access path by explicitly denying S3 access to all principals except:\n", + "- The Lake Formation service-linked role (for data access)\n", + "- The Feature Store offline store role provided during Feature Group creation\n", + "\n", + "## Why don't we apply the S3 deny policy automatically?\n", + "\n", + "We provide the policy as a **recommendation** rather than applying it automatically for several important reasons:\n", + "\n", + "### 1. Protect existing SageMaker workflows from breaking\n", + "\n", + "Many customers already have SageMaker training and processing jobs wired directly to S3 URIs. An automatic S3 deny could cause those jobs to fail the moment governance is enabled on a table.\n", + "\n", + "### 2. Support different personas and trust levels\n", + "\n", + "Different users have different access needs:\n", + "- **Analysts / BI users** - should only see data through governed surfaces (Lake Formation tables, Athena, Redshift, etc.)\n", + "- **ML / Data engineers** - often need raw S3 access for training, feature engineering, and debugging\n", + "\n", + "### 3. Enable gradual migration to stronger governance\n", + "\n", + "Many customers want to phase in Lake Formation governance:\n", + "1. Start by governing table access only\n", + "2. Later tighten S3 access once they've refactored jobs and validated behavior\n", + "\n", + "### 4. Avoid breaking existing bucket policies\n", + "\n", + "Automatically modifying bucket policies could:\n", + "- Conflict with existing policy statements\n", + "- Lock out users or services unexpectedly\n", + "- Cause cascading failures across multiple applications sharing the bucket\n", + "\n", + "Therefore, the S3 policy is provided as a starting point that should be validated by the user. \n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.14" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From 6af324019b376d456b15de8a85ca91c67d2d6248 Mon Sep 17 00:00:00 2001 From: BassemHalim Date: Thu, 29 Jan 2026 14:45:37 -0800 Subject: [PATCH 05/10] add role policy to notebook --- .../v3-feature-store-lake-formation.ipynb | 97 +++++++++++++++++-- 1 file changed, 89 insertions(+), 8 deletions(-) diff --git a/v3-examples/ml-ops-examples/v3-feature-store-lake-formation.ipynb b/v3-examples/ml-ops-examples/v3-feature-store-lake-formation.ipynb index 4f6efa03c4..f8c5a8ced0 100644 --- a/v3-examples/ml-ops-examples/v3-feature-store-lake-formation.ipynb +++ b/v3-examples/ml-ops-examples/v3-feature-store-lake-formation.ipynb @@ -21,15 +21,89 @@ "\n", "## Required IAM Permissions\n", "\n", - "TODO: Add the required IAM policy document here\n", + "This notebook uses two separate IAM roles:\n", + "1. **Execution Role**: The SageMaker execution role running this notebook\n", + "2. **Offline Store Role**: A dedicated role for Feature Store S3 access\n", + "\n", + "### Execution Role Policy\n", + "\n", + "The execution role needs permissions to manage Feature Groups and configure Lake Formation:\n", "\n", "```json\n", "{\n", " \"Version\": \"2012-10-17\",\n", " \"Statement\": [\n", - " // TODO: Add required permissions\n", - " 1. FS permissions to create FG\n", - " 2. LF permissons\n", + " {\n", + " \"Sid\": \"FeatureGroupManagement\",\n", + " \"Effect\": \"Allow\",\n", + " \"Action\": [\n", + " \"sagemaker:*\"\n", + " ],\n", + " \"Resource\": \"arn:aws:sagemaker:*:*:feature-group/*\"\n", + " },\n", + " {\n", + " \"Sid\": \"LakeFormation\",\n", + " \"Effect\": \"Allow\",\n", + " \"Action\": [\n", + " \"lakeformation:RegisterResource\",\n", + " \"lakeformation:DeregisterResource\",\n", + " \"lakeformation:GrantPermissions\",\n", + " \"lakeformation:RevokePermissions\"\n", + " ],\n", + " \"Resource\": \"*\"\n", + " },\n", + " {\n", + " \"Sid\": \"GlueCatalogRead\",\n", + " \"Effect\": \"Allow\",\n", + " \"Action\": [\n", + " \"glue:GetTable\",\n", + " \"glue:GetDatabase\",\n", + " \"glue:DeleteTable\"\n", + " ],\n", + " \"Resource\": [\n", + " \"arn:aws:glue:*:*:catalog\",\n", + " \"arn:aws:glue:*:*:database/sagemaker_featurestore\",\n", + " \"arn:aws:glue:*:*:table/sagemaker_featurestore/*\"\n", + " ]\n", + " },\n", + " {\n", + " \"Sid\": \"PassOfflineStoreRole\",\n", + " \"Effect\": \"Allow\",\n", + " \"Action\": \"iam:PassRole\",\n", + " \"Resource\": \"arn:aws:iam::*:role/SagemakerFeatureStoreOfflineRole\"\n", + " },\n", + " {\n", + " \"Sid\": \"LakeFormationServiceLinkedRole\",\n", + " \"Effect\": \"Allow\",\n", + " \"Action\": [\n", + " \"iam:GetRole\",\n", + " \"iam:PutRolePolicy\",\n", + " \"iam:GetRolePolicy\"\n", + " ],\n", + " \"Resource\": \"arn:aws:iam::*:role/aws-service-role/lakeformation.amazonaws.com/AWSServiceRoleForLakeFormationDataAccess\"\n", + " },\n", + " {\n", + " \"Sid\": \"S3SagemakerDefaultBucket\",\n", + " \"Effect\": \"Allow\",\n", + " \"Action\": [\n", + " \"s3:CreateBucket\",\n", + " \"s3:GetBucketAcl\",\n", + " \"s3:ListBucket\"\n", + " ],\n", + " \"Resource\": [\n", + " \"arn:aws:s3:::sagemaker-*\"\n", + " ]\n", + " },\n", + " {\n", + " \"Sid\": \"CreateGlueTable\",\n", + " \"Effect\": \"Allow\",\n", + " \"Action\": [\n", + " \"glue:CreateTable\"\n", + " ],\n", + " \"Resource\": [\n", + " \"*\"\n", + " ]\n", + " }\n", " ]\n", "}\n", "```\n", @@ -102,11 +176,18 @@ "# Use SageMaker session to get default bucket and execution role\n", "sagemaker_session = SageMakerSession()\n", "S3_BUCKET = sagemaker_session.default_bucket()\n", - "ROLE_ARN = get_execution_role(sagemaker_session)\n", "REGION = sagemaker_session.boto_session.region_name\n", "\n", + "# Execution role (for running this notebook)\n", + "EXECUTION_ROLE_ARN = get_execution_role(sagemaker_session)\n", + "\n", + "# Offline store role (dedicated role for Feature Store S3 access)\n", + "# Replace with your dedicated offline store role ARN\n", + "OFFLINE_STORE_ROLE_ARN = \"arn:aws:iam:::role/\"\n", + "\n", "print(f\"S3 Bucket: {S3_BUCKET}\")\n", - "print(f\"Role ARN: {ROLE_ARN}\")\n", + "print(f\"Execution Role ARN: {EXECUTION_ROLE_ARN}\")\n", + "print(f\"Offline Store Role ARN: {OFFLINE_STORE_ROLE_ARN}\")\n", "print(f\"Region: {REGION}\")" ] }, @@ -300,7 +381,7 @@ " feature_definitions=feature_definitions,\n", " online_store_config=online_store_config,\n", " offline_store_config=offline_store_config_1,\n", - " role_arn=ROLE_ARN,\n", + " role_arn=OFFLINE_STORE_ROLE_ARN,\n", " description=\"Workflow 1: Lake Formation enabled at creation\",\n", " lake_formation_config=lake_formation_config, # new field\n", " region=REGION,\n", @@ -398,7 +479,7 @@ " feature_definitions=feature_definitions,\n", " online_store_config=online_store_config_2,\n", " offline_store_config=offline_store_config_2,\n", - " role_arn=ROLE_ARN,\n", + " role_arn=OFFLINE_STORE_ROLE_ARN,\n", " description=\"Workflow 2: Lake Formation enabled after creation\",\n", " region=REGION,\n", ")\n", From 34b90a7682991b8b0401f05790d4579f1290afe2 Mon Sep 17 00:00:00 2001 From: Basssem Halim Date: Wed, 4 Feb 2026 15:54:33 -0800 Subject: [PATCH 06/10] chore(docs): update example notebook --- .../mlops/feature_store/feature_group.py | 2 +- .../v3-feature-store-lake-formation.ipynb | 308 +++++++++++++----- 2 files changed, 222 insertions(+), 88 deletions(-) diff --git a/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py b/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py index c5fcb9211a..dd193471eb 100644 --- a/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py +++ b/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py @@ -423,7 +423,7 @@ def enable_lake_formation( """ # Get region from session if not provided if region is None and session is not None: - region = session.region_name() + region = session.region_name # Wait for Created status if requested if wait_for_active: diff --git a/v3-examples/ml-ops-examples/v3-feature-store-lake-formation.ipynb b/v3-examples/ml-ops-examples/v3-feature-store-lake-formation.ipynb index f8c5a8ced0..7cde7ca566 100644 --- a/v3-examples/ml-ops-examples/v3-feature-store-lake-formation.ipynb +++ b/v3-examples/ml-ops-examples/v3-feature-store-lake-formation.ipynb @@ -4,8 +4,100 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Feature Store with Lake Formation Governance\n", + "# Feature Group Lake Formation Governance " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## New SDK API Changes\n", + "\n", + "This release introduces Lake Formation integration through the following additions:\n", + "\n", + "### New Class: `LakeFormationConfig`\n", + "\n", + "A configuration class for Lake Formation governance settings:\n", + "\n", + "```python\n", + "from sagemaker.mlops.feature_store.feature_group import LakeFormationConfig\n", + "\n", + "lake_formation_config = LakeFormationConfig()\n", + "lake_formation_config.enabled = True # Enable Lake Formation governance\n", + "lake_formation_config.use_service_linked_role = True # Use LF service-linked role (default)\n", + "lake_formation_config.registration_role_arn = None # This is the role used by LF to access your Resources\n", + "lake_formation_config.show_s3_policy = True # Print recommended S3 deny policy\n", + "```\n", + "\n", + "### New Parameter in FeatureGroup.create(): lake_formation_config\n", + "Pass a LakeFormationConfig object to enable Lake Formation at creation time:\n", + "```python\n", + "fg = FeatureGroup.create(\n", + " feature_group_name=\"my-feature-group\",\n", + " # ... other parameters ...\n", + " lake_formation_config=lake_formation_config, # OPTIONAL NEW PARAMETER\n", + ")\n", + "```\n", + "\n", + "### New Method: FeatureGroup.enable_lake_formation()\n", + "Enable Lake Formation on an existing Feature Group:\n", + "```python\n", + "fg.enable_lake_formation(\n", + " use_service_linked_role=True, # Use LF service-linked role (default)\n", + " registration_role_arn=None, # Custom role ARN (if not using SLR)\n", + " wait_for_active=False, # Wait for Feature Group to be Created\n", + " show_s3_policy=False, # Print recommended S3 deny policy\n", + ")\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Lake Formation Setup Process\n", + "\n", + "When you enable Lake Formation governance (either at creation time or via `enable_lake_formation()`), the SDK performs the following steps automatically:\n", "\n", + "### Step 1: Register S3 Location with Lake Formation\n", + "\n", + "The offline store's S3 location is registered as a Lake Formation data lake location. This allows Lake Formation to manage access to the underlying data files.\n", + "\n", + "- Uses either the Lake Formation service-linked role (default) or a custom registration role\n", + "- If the location is already registered, this step is skipped\n", + "\n", + "### Step 2: Grant Lake Formation Permissions\n", + "\n", + "The Feature Group's `role_arn` (offline store role) is granted the following permissions on the Glue table via Lake Formation:\n", + "\n", + "- `SELECT` - Read data from the table\n", + "- `INSERT` - Write new records\n", + "- `DELETE` - Remove records\n", + "- `DESCRIBE` - View table metadata\n", + "- `ALTER` - Modify table schema\n", + "\n", + "### Step 3: Revoke IAMAllowedPrincipal Permissions\n", + "\n", + "By default, Glue tables allow access to any IAM principal with appropriate IAM permissions (`IAMAllowedPrincipal`). This step revokes that default permission, ensuring that:\n", + "\n", + "- Access is now controlled exclusively through Lake Formation\n", + "- Only principals explicitly granted permissions via Lake Formation can access the data\n", + "\n", + "### Optional: S3 Deny Policy\n", + "\n", + "When `show_s3_policy=True`, the SDK prints a recommended S3 bucket policy. This policy adds an additional layer of protection by denying direct S3 access to all principals except:\n", + "\n", + "- The Lake Formation service-linked role\n", + "- The Feature Store offline store role\n", + "\n", + "**Note:** The S3 policy is not applied automatically—you must manually add it to your bucket policy if desired.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \n", "This notebook demonstrates two workflows for using SageMaker Feature Store with Lake Formation governance:\n", "\n", "1. **Example 1**: Create Feature Group with Lake Formation enabled at creation time\n", @@ -22,12 +114,33 @@ "## Required IAM Permissions\n", "\n", "This notebook uses two separate IAM roles:\n", - "1. **Execution Role**: The SageMaker execution role running this notebook\n", + "1. **Execution Role**: The SageMaker execution role running this notebook. It requires having Lakeformation Data lake admin permissions and Feature store permissions\n", "2. **Offline Store Role**: A dedicated role for Feature Store S3 access\n", "\n", + "## Lake Formation Admin Requirements\n", + "\n", + "The person enabling Lake Formation governance must be a **Data Lake Administrator** in Lake Formation. There are two options for enabling lakeformation governance depending on your organization's setup:\n", + "\n", + "### Option 1: Single Role (Data Lake Admin + Feature Store Admin)\n", + "\n", + "If the caller has both:\n", + "- Data Lake Administrator privileges in Lake Formation\n", + "- Permissions to create Feature Groups in SageMaker\n", + "\n", + "Then they can use `FeatureGroup.create()` with `lake_formation_config` to enable governance at creation time (Example 1).\n", + "\n", + "### Option 2: Separate Roles (ML Engineer + Data Lake Admin)\n", + "\n", + "If the person creating the Feature Group is different from the Data Lake Administrator:\n", + "\n", + "1. **ML Engineer** creates the Feature Group without Lake Formation using `FeatureGroup.create()`\n", + "2. **Data Lake Admin** later enables governance by calling `enable_lake_formation()` on the existing Feature Group (Example 2)\n", + "\n", + "\n", "### Execution Role Policy\n", "\n", - "The execution role needs permissions to manage Feature Groups and configure Lake Formation:\n", + "You can assume a role with the following policy to run this notebook\n", + "Make sure to update the policy to use the offline store role\n", "\n", "```json\n", "{\n", @@ -70,7 +183,7 @@ " \"Sid\": \"PassOfflineStoreRole\",\n", " \"Effect\": \"Allow\",\n", " \"Action\": \"iam:PassRole\",\n", - " \"Resource\": \"arn:aws:iam::*:role/SagemakerFeatureStoreOfflineRole\"\n", + " \"Resource\": \"arn:aws:iam::*:role/\"\n", " },\n", " {\n", " \"Sid\": \"LakeFormationServiceLinkedRole\",\n", @@ -106,26 +219,7 @@ " }\n", " ]\n", "}\n", - "```\n", - "\n", - "## Lake Formation Admin Requirements\n", - "\n", - "The person enabling Lake Formation governance must be a **Data Lake Administrator** in Lake Formation. There are two options depending on your organization's setup:\n", - "\n", - "### Option 1: Single User (Data Lake Admin + Feature Store Admin)\n", - "\n", - "If the caller has both:\n", - "- Data Lake Administrator privileges in Lake Formation\n", - "- Permissions to create Feature Groups in SageMaker\n", - "\n", - "Then they can use `FeatureGroup.create()` with `lake_formation_config` to enable governance at creation time (Example 1).\n", - "\n", - "### Option 2: Separate Roles (ML Engineer + Data Lake Admin)\n", - "\n", - "If the person creating the Feature Group is different from the Data Lake Administrator:\n", - "\n", - "1. **ML Engineer** creates the Feature Group without Lake Formation using `FeatureGroup.create()`\n", - "2. **Data Lake Admin** later enables governance by calling `enable_lake_formation()` on the existing Feature Group (Example 2)\n" + "```" ] }, { @@ -135,6 +229,24 @@ "## Setup" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This Demo builds on sagemaker v3 features which is not out yet so we need to tell pip to use local version \n", + "\n", + "1. install `pyenv` https://github.com/pyenv/pyenv?tab=readme-ov-file#a-getting-pyenv\n", + "2. install and activate python for example (this code was tested on python 3.10.14)\n", + "```\n", + "pyenv install 3.10.14\n", + "pyenv virtualenv 3.10.14 py3.10.14\n", + "pyenv activate py3.10.14\n", + "```\n", + "3. You will then need to run `pip install -e .` before starting the jupyter notebook to use the local packages\n", + "4. `pip install jupyter notebook`\n", + "5. `jupyter notebook`" + ] + }, { "cell_type": "code", "execution_count": null, @@ -174,6 +286,9 @@ "outputs": [], "source": [ "# Use SageMaker session to get default bucket and execution role\n", + "\n", + "boto_session = boto3.Session()\n", + "new_sagemaker_session = SageMakerSession(boto_session=boto_session)\n", "sagemaker_session = SageMakerSession()\n", "S3_BUCKET = sagemaker_session.default_bucket()\n", "REGION = sagemaker_session.boto_session.region_name\n", @@ -183,7 +298,8 @@ "\n", "# Offline store role (dedicated role for Feature Store S3 access)\n", "# Replace with your dedicated offline store role ARN\n", - "OFFLINE_STORE_ROLE_ARN = \"arn:aws:iam:::role/\"\n", + "# https://docs.aws.amazon.com/sagemaker/latest/dg/feature-store-adding-policies.html\n", + "OFFLINE_STORE_ROLE_ARN = \"arn:aws:iam:::role/\"\n", "\n", "print(f\"S3 Bucket: {S3_BUCKET}\")\n", "print(f\"Execution Role ARN: {EXECUTION_ROLE_ARN}\")\n", @@ -256,56 +372,6 @@ " print(f\"Successfully ingested {num_records} records!\")" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Helper Function: Cleanup" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def cleanup_feature_group(fg):\n", - " \"\"\"\n", - " Delete a FeatureGroup and its associated Glue table.\n", - " \n", - " Args:\n", - " fg: The FeatureGroup to delete.\n", - " \"\"\"\n", - " try:\n", - " # Delete the Glue table if it exists\n", - " if fg.offline_store_config is not None:\n", - " try:\n", - " fg.refresh() # Ensure we have latest config\n", - " data_catalog_config = fg.offline_store_config.data_catalog_config\n", - " if data_catalog_config is not None:\n", - " database_name = data_catalog_config.database\n", - " table_name = data_catalog_config.table_name\n", - "\n", - " if database_name and table_name:\n", - " glue_client = boto3.client(\"glue\")\n", - " try:\n", - " glue_client.delete_table(DatabaseName=database_name, Name=table_name)\n", - " print(f\"Deleted Glue table: {database_name}.{table_name}\")\n", - " except ClientError as e:\n", - " # Ignore if table doesn't exist\n", - " if e.response[\"Error\"][\"Code\"] != \"EntityNotFoundException\":\n", - " raise\n", - " except Exception as e:\n", - " # Don't fail cleanup if Glue table deletion fails\n", - " print(f\"Warning: Could not delete Glue table: {e}\")\n", - "\n", - " # Delete the FeatureGroup\n", - " fg.delete()\n", - " print(f\"Deleted Feature Group: {fg.feature_group_name}\")\n", - " except ClientError as e:\n", - " print(f\"Error during cleanup: {e}\")" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -383,8 +449,9 @@ " offline_store_config=offline_store_config_1,\n", " role_arn=OFFLINE_STORE_ROLE_ARN,\n", " description=\"Workflow 1: Lake Formation enabled at creation\",\n", - " lake_formation_config=lake_formation_config, # new field\n", + " lake_formation_config=lake_formation_config, # new parameter\n", " region=REGION,\n", + " session=boto_session\n", ")\n", "\n", "print(f\"\\nFeature Group created: {fg_workflow1.feature_group_name}\")\n", @@ -401,7 +468,10 @@ "fg_workflow1.refresh()\n", "print(f\"Feature Group: {fg_workflow1.feature_group_name}\")\n", "print(f\"Status: {fg_workflow1.feature_group_status}\")\n", - "print(f\"ARN: {fg_workflow1.feature_group_arn}\")" + "print(f\"ARN: {fg_workflow1.feature_group_arn}\")\n", + "\n", + "DataCatalogConfig = fg_workflow1.offline_store_config.data_catalog_config\n", + "print(f'Table Name: {DataCatalogConfig.table_name}')" ] }, { @@ -411,7 +481,7 @@ "outputs": [], "source": [ "# Ingest sample records to verify everything works\n", - "ingest_sample_records(fg_workflow1, num_records=3)" + "ingest_sample_records(fg_workflow1, num_records=10)" ] }, { @@ -422,7 +492,7 @@ "source": [ "# Retrieve a sample record from the online store\n", "print(\"Retrieving record for customer 'cust_1' from online store...\")\n", - "response = fg_workflow1.get_record(record_identifier_value_as_string=\"cust_1\")\n", + "response = fg_workflow1.get_record(record_identifier_value_as_string=\"cust_3\")\n", "\n", "print(f\"\\nRecord retrieved successfully!\")\n", "print(f\"Features:\")\n", @@ -482,10 +552,11 @@ " role_arn=OFFLINE_STORE_ROLE_ARN,\n", " description=\"Workflow 2: Lake Formation enabled after creation\",\n", " region=REGION,\n", + " session=boto_session\n", ")\n", "\n", "print(f\"Feature Group created: {fg_workflow2.feature_group_name}\")\n", - "print(f\"Status: {fg_workflow2.feature_group_status}\")" + "print(f\"Status: {fg_workflow2.feature_group_status}\")\n" ] }, { @@ -500,6 +571,15 @@ "print(f\"Status: {fg_workflow2.feature_group_status}\")" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fg_workflow2 = FeatureGroup.refresh()" + ] + }, { "cell_type": "code", "execution_count": null, @@ -515,7 +595,8 @@ "print()\n", "\n", "result = fg_workflow2.enable_lake_formation( # new method\n", - " use_service_linked_role=True\n", + " use_service_linked_role=True,\n", + " session=boto_session\n", ")\n", "\n", "print(f\"\\nLake Formation setup results:\")\n", @@ -531,8 +612,9 @@ "outputs": [], "source": [ "# Step 4: Ingest sample records to verify everything works\n", + "# This is still using the first role\n", "print(\"Step 4: Ingesting records to verify Lake Formation setup...\")\n", - "ingest_sample_records(fg_workflow2, num_records=3)" + "ingest_sample_records(fg_workflow2, num_records=4)" ] }, { @@ -561,7 +643,9 @@ "fg_workflow2.refresh()\n", "print(f\"Feature Group: {fg_workflow2.feature_group_name}\")\n", "print(f\"Status: {fg_workflow2.feature_group_status}\")\n", - "print(f\"ARN: {fg_workflow2.feature_group_arn}\")" + "print(f\"ARN: {fg_workflow2.feature_group_arn}\")\n", + "DataCatalogTable = fg_workflow2.offline_store_config.data_catalog_config.table_name\n", + "print(f\"{DataCatalogTable}\")" ] }, { @@ -571,7 +655,57 @@ "---\n", "# Cleanup\n", "\n", - "Delete the Feature Groups and associated Glue tables created in this demo." + "Delete the Feature Groups and **associated Glue tables** created in this demo." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Helper Function: Cleanup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def cleanup_feature_group(fg):\n", + " \"\"\"\n", + " Delete a FeatureGroup and its associated Glue table.\n", + " \n", + " Args:\n", + " fg: The FeatureGroup to delete.\n", + " \"\"\"\n", + " try:\n", + " # Delete the Glue table if it exists\n", + " if fg.offline_store_config is not None:\n", + " try:\n", + " fg.refresh() # Ensure we have latest config\n", + " data_catalog_config = fg.offline_store_config.data_catalog_config\n", + " if data_catalog_config is not None:\n", + " database_name = data_catalog_config.database\n", + " table_name = data_catalog_config.table_name\n", + "\n", + " if database_name and table_name:\n", + " glue_client = boto3.client(\"glue\")\n", + " try:\n", + " glue_client.delete_table(DatabaseName=database_name, Name=table_name)\n", + " print(f\"Deleted Glue table: {database_name}.{table_name}\")\n", + " except ClientError as e:\n", + " # Ignore if table doesn't exist\n", + " if e.response[\"Error\"][\"Code\"] != \"EntityNotFoundException\":\n", + " raise\n", + " except Exception as e:\n", + " # Don't fail cleanup if Glue table deletion fails\n", + " print(f\"Warning: Could not delete Glue table: {e}\")\n", + "\n", + " # Delete the FeatureGroup\n", + " fg.delete()\n", + " print(f\"Deleted Feature Group: {fg.feature_group_name}\")\n", + " except ClientError as e:\n", + " print(f\"Error during cleanup: {e}\")" ] }, { @@ -581,8 +715,8 @@ "outputs": [], "source": [ "# Uncomment to delete the Feature Groups\n", - "cleanup_feature_group(fg_workflow1)\n", - "# cleanup_feature_group(fg_workflow2)" + "# cleanup_feature_group(fg_workflow1)\n", + "cleanup_feature_group(fg_workflow2)" ] }, { @@ -594,7 +728,7 @@ "\n", "This notebook demonstrated two workflows:\n", "\n", - "**Example 1: Lake Formation at Creation**\n", + "**Example 1: Enable Lake Formation Governance at Creation**\n", "- Use `LakeFormationConfig` with `enabled=True` in `FeatureGroup.create()`\n", "- Lake Formation is automatically configured after Feature Group creation\n", "- Both online and offline stores enabled\n", From 164c3134d5185e9efaf06f44f955f2e283ee8d43 Mon Sep 17 00:00:00 2001 From: BassemHalim Date: Fri, 6 Feb 2026 13:24:36 -0800 Subject: [PATCH 07/10] update setup instructions --- .../v3-feature-store-lake-formation.ipynb | 100 +++++++++++++----- 1 file changed, 71 insertions(+), 29 deletions(-) diff --git a/v3-examples/ml-ops-examples/v3-feature-store-lake-formation.ipynb b/v3-examples/ml-ops-examples/v3-feature-store-lake-formation.ipynb index 7cde7ca566..5f689a3c0d 100644 --- a/v3-examples/ml-ops-examples/v3-feature-store-lake-formation.ipynb +++ b/v3-examples/ml-ops-examples/v3-feature-store-lake-formation.ipynb @@ -7,6 +7,25 @@ "# Feature Group Lake Formation Governance " ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This Demo builds on sagemaker v3 features which is not out yet so we need to tell pip to use local version \n", + "\n", + "1. install `pyenv` following the instructions here https://github.com/pyenv/pyenv?tab=readme-ov-file#a-getting-pyenv\n", + "2. setup your shell env for pyenv https://github.com/pyenv/pyenv?tab=readme-ov-file#b-set-up-your-shell-environment-for-pyenv\n", + "3. install and activate python for example (this code was tested on python 3.10.14)\n", + "```\n", + "pyenv install 3.10.14\n", + "pyenv virtualenv 3.10.14 py3.10.14\n", + "pyenv activate py3.10.14\n", + "```\n", + "3. You will then need to run `pip install -e ./sagemaker-mlops` before starting the jupyter notebook to use the local packages\n", + "4. `pip install jupyter notebook`\n", + "5. `jupyter notebook`" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -230,21 +249,43 @@ ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ - "This Demo builds on sagemaker v3 features which is not out yet so we need to tell pip to use local version \n", + "import boto3\n", + "import os\n", "\n", - "1. install `pyenv` https://github.com/pyenv/pyenv?tab=readme-ov-file#a-getting-pyenv\n", - "2. install and activate python for example (this code was tested on python 3.10.14)\n", - "```\n", - "pyenv install 3.10.14\n", - "pyenv virtualenv 3.10.14 py3.10.14\n", - "pyenv activate py3.10.14\n", - "```\n", - "3. You will then need to run `pip install -e .` before starting the jupyter notebook to use the local packages\n", - "4. `pip install jupyter notebook`\n", - "5. `jupyter notebook`" + "boto3.DEFAULT_SESSION = None\n", + "def assume_role(role_arn, session_name=\"AssumedRoleSession\"):\n", + " \"\"\"\n", + " Assume an AWS IAM role and return temporary credentials.\n", + " \n", + " Args:\n", + " role_arn: The ARN of the role to assume\n", + " session_name: A name for the assumed role session\n", + " \n", + " Returns:\n", + " A boto3 session with the assumed role credentials\n", + " \"\"\"\n", + " sts_client = boto3.client('sts')\n", + " \n", + " response = sts_client.assume_role(\n", + " RoleArn=role_arn,\n", + " RoleSessionName=session_name\n", + " )\n", + " \n", + " credentials = response['Credentials']\n", + " \n", + " # Create a new session with the temporary credentials\n", + " session = boto3.Session(\n", + " aws_access_key_id=credentials['AccessKeyId'],\n", + " aws_secret_access_key=credentials['SecretAccessKey'],\n", + " aws_session_token=credentials['SessionToken']\n", + " )\n", + " \n", + " return session" ] }, { @@ -287,22 +328,26 @@ "source": [ "# Use SageMaker session to get default bucket and execution role\n", "\n", - "boto_session = boto3.Session()\n", - "new_sagemaker_session = SageMakerSession(boto_session=boto_session)\n", - "sagemaker_session = SageMakerSession()\n", - "S3_BUCKET = sagemaker_session.default_bucket()\n", - "REGION = sagemaker_session.boto_session.region_name\n", - "\n", "# Execution role (for running this notebook)\n", - "EXECUTION_ROLE_ARN = get_execution_role(sagemaker_session)\n", + "EXECUTION_ROLE_ARN = 'arn:aws:iam:::role/'\n", + "\n", "\n", "# Offline store role (dedicated role for Feature Store S3 access)\n", "# Replace with your dedicated offline store role ARN\n", "# https://docs.aws.amazon.com/sagemaker/latest/dg/feature-store-adding-policies.html\n", - "OFFLINE_STORE_ROLE_ARN = \"arn:aws:iam:::role/\"\n", + "OFFLINE_STORE_ROLE_ARN = \"arn:aws:iam:::role/\"\n", + "\n", + "\n", + "boto_session = assume_role(EXECUTION_ROLE_ARN)\n", + "sagemaker_session = SageMakerSession(boto_session=boto_session)\n", + "sts = boto_session.client('sts')\n", + "\n", + "S3_BUCKET = sagemaker_session.default_bucket()\n", + "REGION = sagemaker_session.boto_session.region_name\n", + "\n", "\n", "print(f\"S3 Bucket: {S3_BUCKET}\")\n", - "print(f\"Execution Role ARN: {EXECUTION_ROLE_ARN}\")\n", + "print(f\"Execution Role ARN:{sts.get_caller_identity()['Arn']}\")\n", "print(f\"Offline Store Role ARN: {OFFLINE_STORE_ROLE_ARN}\")\n", "print(f\"Region: {REGION}\")" ] @@ -572,12 +617,10 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "fg_workflow2 = FeatureGroup.refresh()" + "Here you can optionally assume a different role with just datalake permissions and describe Feature Group permission" ] }, { @@ -593,10 +636,9 @@ "print(\" 2. Grant permissions to execution role\")\n", "print(\" 3. Revoke IAMAllowedPrincipal permissions\")\n", "print()\n", - "\n", + "fg_workflow2 = FeatureGroup.get(FG_NAME_WORKFLOW2)\n", "result = fg_workflow2.enable_lake_formation( # new method\n", " use_service_linked_role=True,\n", - " session=boto_session\n", ")\n", "\n", "print(f\"\\nLake Formation setup results:\")\n", @@ -645,7 +687,7 @@ "print(f\"Status: {fg_workflow2.feature_group_status}\")\n", "print(f\"ARN: {fg_workflow2.feature_group_arn}\")\n", "DataCatalogTable = fg_workflow2.offline_store_config.data_catalog_config.table_name\n", - "print(f\"{DataCatalogTable}\")" + "print(f\"Table Name: {DataCatalogTable}\")" ] }, { @@ -715,7 +757,7 @@ "outputs": [], "source": [ "# Uncomment to delete the Feature Groups\n", - "# cleanup_feature_group(fg_workflow1)\n", + "cleanup_feature_group(fg_workflow1)\n", "cleanup_feature_group(fg_workflow2)" ] }, From 07da9e7d7a4988216772f64efd92472d6b6308f8 Mon Sep 17 00:00:00 2001 From: BassemHalim Date: Fri, 20 Feb 2026 11:10:59 -0800 Subject: [PATCH 08/10] add lf-multiaccount-demo + fix LakeformationConfig constructor --- .../mlops/feature_store/feature_group.py | 2 +- .../FS-lakeformation-cross-account.ipynb | 580 ++++++++++++++++++ .../imgs/fs-lf-cross-account1.png | Bin 0 -> 476328 bytes 3 files changed, 581 insertions(+), 1 deletion(-) create mode 100644 v3-examples/ml-ops-examples/FS-lakeformation-cross-account.ipynb create mode 100644 v3-examples/ml-ops-examples/imgs/fs-lf-cross-account1.png diff --git a/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py b/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py index dd193471eb..d4cff70988 100644 --- a/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py +++ b/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py @@ -26,7 +26,7 @@ logger = logging.getLogger(__name__) -class LakeFormationConfig: +class LakeFormationConfig(Base): """Configuration for Lake Formation governance on Feature Group offline stores. Attributes: diff --git a/v3-examples/ml-ops-examples/FS-lakeformation-cross-account.ipynb b/v3-examples/ml-ops-examples/FS-lakeformation-cross-account.ipynb new file mode 100644 index 0000000000..59f7920998 --- /dev/null +++ b/v3-examples/ml-ops-examples/FS-lakeformation-cross-account.ipynb @@ -0,0 +1,580 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4e7cc789-55ea-4460-a07e-a57ffe6ee4e6", + "metadata": {}, + "source": [ + "1. Create Feature Group in central account with Lakeformation enabled" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "d8f0e80d-bc9b-4c5e-b545-32fff784b8b5", + "metadata": {}, + "source": [ + "# Cross Account Lakeformation governed Feature Group Demo\n", + "\n", + "This is a demo to showcase how cross account access would work with lakeformation(LF) governed Feature Group(FG)\n", + "\n", + "[simpler single account demo](./v3-feature-store-lake-formation.ipynb) \n", + "\n", + "The following scenario will be setup where you have a central account that owns the FG and then you have a producer account to ingest into the FG and another one reading from the FG\n", + "\n", + "![image.png](./imgs/fs-lf-cross-account1.png)" + ] + }, + { + "cell_type": "markdown", + "id": "f0c347d3-2736-4acf-8aff-bc6c9cc7a990", + "metadata": {}, + "source": [ + "## Helper Methods" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d30e0db4-122c-4da4-b33d-6ed3c3a40a3c", + "metadata": {}, + "outputs": [], + "source": [ + "import boto3\n", + "import os\n", + "\n", + "boto3.DEFAULT_SESSION = None\n", + "def assume_role(role_arn, session_name=\"AssumedRoleSession\"):\n", + " \"\"\"\n", + " Assume an AWS IAM role and return temporary credentials.\n", + " \n", + " Args:\n", + " role_arn: The ARN of the role to assume\n", + " session_name: A name for the assumed role session\n", + " \n", + " Returns:\n", + " A boto3 session with the assumed role credentials\n", + " \"\"\"\n", + " sts_client = boto3.client('sts')\n", + " \n", + " response = sts_client.assume_role(\n", + " RoleArn=role_arn,\n", + " RoleSessionName=session_name\n", + " )\n", + " \n", + " credentials = response['Credentials']\n", + " \n", + " # Create a new session with the temporary credentials\n", + " session = boto3.Session(\n", + " aws_access_key_id=credentials['AccessKeyId'],\n", + " aws_secret_access_key=credentials['SecretAccessKey'],\n", + " aws_session_token=credentials['SessionToken']\n", + " )\n", + " \n", + " return session" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bf42a253-bf5e-49f3-96cc-744606cda4f4", + "metadata": {}, + "outputs": [], + "source": [ + "from sagemaker.core.helper.session_helper import Session" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "afc7f261-e7fe-4abc-88c3-cd3b1aa61dd2", + "metadata": {}, + "outputs": [], + "source": [ + "central_account = \"account-1\"\n", + "producer_account = \"account-2\"\n", + "consumer_account = \"account-3\"\n", + "\n", + "acc_to_role_arn = {\n", + " central_account: f\"arn:aws:iam::{central_account}:role/admin\",\n", + " producer_account: f\"arn:aws:iam::{producer_account}:role/Admin\",\n", + " consumer_account: f\"arn:aws:iam::{consumer_account}:role/Admin\"\n", + "}\n", + "\n", + "central_acc_boto_session = assume_role(acc_to_role_arn[central_account])\n", + "central_acc_sagemaker_session = Session(boto_session=central_acc_boto_session)\n", + "\n", + "producer_acc_boto_session = assume_role(acc_to_role_arn[producer_account])\n", + "producer_acc_sagemaker_session = Session(boto_session=producer_acc_boto_session)\n", + "\n", + "consumer_acc_boto_session = assume_role(acc_to_role_arn[consumer_account])\n", + "consumer_acc_sagemaker_session = Session(boto_session=consumer_acc_boto_session)\n" + ] + }, + { + "cell_type": "markdown", + "id": "28a96af6-409a-4756-8cb7-60850342c955", + "metadata": {}, + "source": [ + "## 1. Create Feature Group in central account and enable Lakeformation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4f6a2639-2640-4a51-8fad-886b4d7226da", + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "import boto3\n", + "from botocore.exceptions import ClientError\n", + "# Import the FeatureGroup with Lake Formation support\n", + "from sagemaker.mlops.feature_store.feature_group import FeatureGroup, LakeFormationConfig\n", + "from sagemaker.core.shapes import (\n", + " FeatureDefinition,\n", + " FeatureValue,\n", + " OfflineStoreConfig,\n", + " OnlineStoreConfig,\n", + " S3StorageConfig,\n", + ")\n", + "from sagemaker.core.helper.session_helper import Session as SageMakerSession, get_execution_role\n", + "\n", + "feature_definitions = [\n", + " FeatureDefinition(feature_name=\"customer_id\", feature_type=\"String\"),\n", + " FeatureDefinition(feature_name=\"event_time\", feature_type=\"String\"),\n", + " FeatureDefinition(feature_name=\"age\", feature_type=\"Integral\"),\n", + " FeatureDefinition(feature_name=\"total_purchases\", feature_type=\"Integral\"),\n", + " FeatureDefinition(feature_name=\"avg_order_value\", feature_type=\"Fractional\"),\n", + "]\n", + "\n", + "# Offline store role (dedicated role for Feature Store S3 access)\n", + "# https://docs.aws.amazon.com/sagemaker/latest/dg/feature-store-adding-policies.html\n", + "OFFLINE_STORE_ROLE_ARN = \"your-offline-store-role-arn\"\n", + "\n", + "S3_BUCKET = central_acc_sagemaker_session.default_bucket()\n", + "REGION = central_acc_boto_session.region_name\n", + "\n", + "\n", + "# Configure online and offline stores\n", + "FEATURE_GROUP_NAME='lakeformation-managed-fg-2'\n", + "\n", + "online_store_config = OnlineStoreConfig(enable_online_store=True)\n", + "\n", + "offline_store_config = OfflineStoreConfig(\n", + " s3_storage_config=S3StorageConfig(\n", + " s3_uri=f\"s3://{S3_BUCKET}/feature-store-demo/\"\n", + " )\n", + ")\n", + "\n", + "# Configure Lake Formation - enabled at creation\n", + "lake_formation_config = LakeFormationConfig(\n", + " enabled=True\n", + ")\n", + "\n", + "# create FG in central account and enable LF\n", + "feature_group = FeatureGroup.create(\n", + " feature_group_name=FEATURE_GROUP_NAME,\n", + " record_identifier_feature_name=\"customer_id\",\n", + " event_time_feature_name=\"event_time\",\n", + " feature_definitions=feature_definitions,\n", + " online_store_config=online_store_config,\n", + " offline_store_config=offline_store_config,\n", + " role_arn=OFFLINE_STORE_ROLE_ARN,\n", + " description=\"Feature Group with lakeformation enabled\",\n", + " lake_formation_config=lake_formation_config, # new parameter\n", + " session=central_acc_boto_session \n", + ")\n", + "\n", + "print(f\"\\nFeature Group created: {feature_group.feature_group_name}\")\n", + "# feature_group = FeatureGroup.get(FEATURE_GROUP_NAME)\n", + "central_acc_sagemaker_session.describe_feature_group(FEATURE_GROUP_NAME)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "956b3ed3-7ede-4486-af44-46845b683a09", + "metadata": {}, + "outputs": [], + "source": [ + "feature_group.refresh()\n", + "feature_group_arn = feature_group.feature_group_arn\n", + "data_catalog_config = feature_group.offline_store_config.data_catalog_config\n", + "database_name = str(data_catalog_config.database)\n", + "table_name = str(data_catalog_config.table_name)\n", + "catalog_id = str(data_catalog_config.catalog)\n", + "print(f\"Feature Group ARN: {feature_group_arn}\")\n", + "print(f\"Database: {database_name}\")\n", + "print(f\"Table: {table_name}\")\n", + "print(f\"Catalog: {catalog_id}\")" + ] + }, + { + "cell_type": "markdown", + "id": "4708e998-6ac4-454c-a3ab-3a1f4fd71bc4", + "metadata": {}, + "source": [ + "## 2. Share Feature Group with producer account" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6ea63cc0-7418-440f-8784-9108ca244e6c", + "metadata": {}, + "outputs": [], + "source": [ + "ram_client = central_acc_boto_session.client(\"ram\")\n", + "response = ram_client.create_resource_share(\n", + " name='producer-account-fg-share',\n", + " resourceArns=[\n", + " feature_group_arn\n", + " ],\n", + " principals=[\n", + " str(producer_account)\n", + " ],\n", + " permissionArns=[\n", + " \"arn:aws:ram::aws:permission/AWSRAMPermissionSageMakerFeatureGroupReadWrite\"\n", + " ]\n", + ")\n", + "response" + ] + }, + { + "cell_type": "markdown", + "id": "18df5f35-8efe-4b02-bfbf-d4bcbb6cb9cd", + "metadata": {}, + "source": [ + "### Producer Accepts the RAM share" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2360602b-fdc4-45ea-958e-9dbec0efdd52", + "metadata": {}, + "outputs": [], + "source": [ + "# Producer account accepts the RAM invitation\n", + "ram_client_producer = producer_acc_boto_session.client('ram')\n", + "\n", + "response = ram_client_producer.get_resource_share_invitations()\n", + "pending = [\n", + " inv for inv in response['resourceShareInvitations']\n", + " if inv['status'] == 'PENDING' and inv['senderAccountId'] == str(central_account)\n", + "]\n", + "\n", + "for inv in pending:\n", + " ram_client_producer.accept_resource_share_invitation(\n", + " resourceShareInvitationArn=inv['resourceShareInvitationArn']\n", + " )\n", + " print(f\"Accepted: {inv['resourceShareInvitationArn']}\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b59161c-5016-41ac-b70f-b0375067cdbc", + "metadata": {}, + "outputs": [], + "source": [ + "# Test ingest from producer\n", + "\n", + "from datetime import datetime\n", + "\n", + "# Use the producer session to call PutRecord on the shared Feature Group\n", + "sm_runtime = producer_acc_boto_session.client('sagemaker-featurestore-runtime')\n", + "\n", + "sm_runtime.put_record(\n", + " FeatureGroupName=feature_group_arn,\n", + " Record=[\n", + " {'FeatureName': 'customer_id', 'ValueAsString': 'CUST-001'},\n", + " {'FeatureName': 'event_time', 'ValueAsString': datetime.utcnow().isoformat() + 'Z'},\n", + " {'FeatureName': 'age', 'ValueAsString': '35'},\n", + " {'FeatureName': 'total_purchases', 'ValueAsString': '12'},\n", + " {'FeatureName': 'avg_order_value', 'ValueAsString': '49.99'},\n", + " ]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "486142f8-de45-4029-a08c-e0e1457cb3ea", + "metadata": {}, + "outputs": [], + "source": [ + "# Test getRecord\n", + "sm_runtime.get_record(\n", + " FeatureGroupName=feature_group_arn,\n", + " RecordIdentifierValueAsString='CUST-001'\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "5f531d4a-b668-42a8-a725-94a165ba76f8", + "metadata": {}, + "source": [ + "## 3. Share Glue Table with consumer account using LF" + ] + }, + { + "attachments": { + "d1f0c7d4-d102-42f3-a1fc-b26eeb94a2bf.png": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABqAAAALOCAYAAADGG9JtAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAGoKADAAQAAAABAAACzgAAAADCWs0rAABAAElEQVR4AezdB5gUVdaA4TN5BoaccxIQSaKoGDCvAdOimNNizrprWuE3ryzmsIY1Z1xFUNewpnUVA4oIkkRAcs4ypIk9/znVU93VzfTEnp7ume8+T9s1XVW3br1VjV116p6b1HPA0GKhIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIBAlgeQo1UM1CCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCDgCBKA4ERBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBKIqQAAqqpxUhgACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggQACKcwABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQCCqAgSgospJZQgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgSgOAcQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSiKkAAKqqcVIYAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIEAAinMAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAgqgIEoKLKSWUIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIEoDgHEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEoipAACqqnFSGAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCBAAIpzAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAIKoCBKCiykllCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACBKA4BxBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBKIqQAAqqpxUhgACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggQACKcwABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQCCqAgSgospJZQgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgSgOAcQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSiKkAAKqqcVIYAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIEAAinMAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAgqgIEoKLKSWUIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIEoDgHEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEoipAACqqnFSGAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCBAAIpzAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAIKoCBKCiykllCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACBKA4BxBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBKIqQAAqqpxUhgACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggQACKcwABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQCCqAgSgospJZQgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgSgOAcQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSiKkAAKqqcVIYAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIEAAinMAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAgqgIEoKLKSWUIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIEoDgHEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEoipAACqqnFSGAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCBAAIpzAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAIKoCBKCiykllCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACBKA4BxBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBKIqQAAqqpxUhgACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggQACKcwABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQCCqAgSgospJZQgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgSgOAcQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQSiKkAAKqqcVIYA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br7+slhz9ZWzO2eed1m88NJrM3mq7l9af9014vhjDs868ubbA2P33/257neqlnqQhk/bbbt57N53h1h5pRVmqDWdXfPQI09ls6Leeuf9Ge4X7UIaBF1+4enJDLHuFV177Y134tCjTqix5QnTZfTuufXaaNNm2vKIaX37HnBkTJky679NtNKKyyV7Vl1Tsb/XAYceE88+/3JFu30gQIAAAQKlKmAGVKmOjHYRIECAAAECBAgQIFBdAQFUdeWUq7MCdyd/qN19hWXrbPur0/B0r6s+u+1XnaLzfZl09lM6a65Xzy2iZYsWM3h88umguLXffckMncdi9JixM9wvyoV0qcLTTzom+vTauqJL6fJ2Bx12bHz6+eCKa/PywwbrrhnXXXl+1K9fL3vtTbfeHf88++LZVnHaiX+N3ZLwMD2+/GpIbLfzvpEu5ecgQIAAAQKlLCCAKuXR0TYCBAgQIECAAAECBKojYAm+6qgpU6cFdt25V7ZEV53uRBUb/92w4XHHXQ9UsZTHU4ERI36KZ54bEDfcclcM+fa75NfOgtFxwQ4VOB06tItNNlw3frdX30hn7Xz/w4j4fvgPFfeL8iFdqvDxp56PdPbXOmutns0wat26VfTZfutIQ7gvvvx6nnf1q2++zepbf501snf3WGn5+HrIt/HRJ5/Psq63330/0n/P05lsbZMZVJMmTY50BpWDAAECBAiUsoAl+Ep5dLSNAAECBAgQIECAAIHqCJgBVR01Zeq0wKYbrRcn/P3waNGieZ3ux5w2fkwyK+eMcy+Lp597aU6LeG42Aisu3y2bFbXdNptH8+YzbhSezji75Y57s/2Hfvll2obis3llnbqd/jt04dknVfw7VFY2Nc696Mq4/obba6Qfl5x3amy71abZu9MAbI/fHRIDP/h4lnXtsUvvOPWEo7Nnxo8fH9v02Se+HTpslmXcJECAAAECeQqYAZWnvroJECBAgAABAgQIEKgJAQFUTah6JwEC84VAGmKmM4B269srluu29Ax9Hjv2l7j/ocfjtmSJvg8//myG+3X5Qrell4yrLz0rm/VV3o977n8kTjztvHm+3F2zZk2j303XRLelu2ZVpUHSTnscED/+9HN51TP8rF+/fqTLba6w3DLZvcefei4O+csJMzznAgECBAgQKBUBAVSpjIR2ECBAgAABAgQIECAwrwQswTevJL2H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6gsBAgQIECBAgAABAgQIVCYwduSgePORPSu7Xen1ssm/ZPd+GvJivDm86uUrfXEt3Zg04cdaqkk1BEpfQABV+mOkhQQIECBQIAHLDhRoMHWFAAECBAgQIECAAAECBCoXmDo5Jo3/ofL7s7lTVjYhysZPmM1TbhMgUMoCluAr5dHRNgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAHRQwA6oODpomEyBAgEDdErDsQN0aL60lQIAAAQIECBAgQIAAAQIECBCYewEB1NwbegMBAgQIEJi1gGUHZu3jLgECBAgQIECAAAECBAgQIECAQOEELMFXuCHVIQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAvgICqHz91U6AAAECBAgQIECAAAECBAgQIECAAAECBAgQKJyAAKpwQ6pDBAgQIECAAAECBAgQIECAAAECBAgQIECAAIF8BQRQ+fqrnQABAgQIECBAgAABAgQIECBAgAABAgQIECBQOAEBVOGGVIcIECBAgAABAgQIECBAgAABAgQIECBAgAABAvkKCKDy9Vc7AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKBwAgKowg2pDhEgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE8hUQQOXrr3YCBAgQIECAAAECBAgQIECAAAECBAgQIECAQOEEBFCFG1IdIkCAAAECBAgQIECAAAECBAgQIECAAAECBAjkKyCAytdf7QQIECBAgAABAgQIECBAgAABAgQIECBAgACBwgkIoAo3pDpEgAABAgQIECBAgAABAgQIECBAgAABAgQIEMhXQACVr7/aCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKFExBAFW5IdYgAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgkK+AACpff7UTIECAAAECBAgQIECAAAECBAgQIECAAAECBAonIIAq3JDqEAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgXwEBVL7+aidAgAABAgQIECBAgAABAgQIECBAgAABAgQIFE5AAFW4IdUhAgQIECBAgAABAgQIECBAgAABAgQIECBAgEC+AgKofP3VToAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAonIAAqnBDqkMECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgXwFBFD5+qudAAECBAgQIECAAAECBAgQIECAAAECBAgQIFA4AQFU4YZUhwgQIECAAAECBAgQIECAAAECBAgQIECAAAEC+QoIoPL1VzsBAgQIECBAgAABAgQIECBAgAABAgQIECBAoHACAqjCDakOESBAgAABAgQIECBAgAABAgQIECBAgAABAgTyFRBA5euvdgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBA4QQEUIUbUh0iQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECOQrIIDK11/tBAgQIECAAAECBAgQIECAAAECBAgQIECAAIHCCQigCjekOkSAAAECBAgQIECAAAECBAgQIECAAAECBAgQyFdAAJWvv9oJECBAgAABAgQIECBAgAABAgQIECBAgAABAoUTEEAVbkh1iAABAgQIECBAgAABAgQIECBAgAABAgQIECCQr4AAKl9/tRMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECicggCrckOoQAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBfAQFUvv5qJ0CAAAECBAgQIECAAAECBAgQIECAAAECBAgUTkAAVbgh1SECBAgQIECAAAECBAgQIECAAAECBAgQIECAQL4CAqh8/dVOgAABAgQIECBAgAABAgQIECBAgAABAgQIECicgACqcEOqQwQIECBAgAABAgQIECBAgAABAgQIECBAgACBfAUEUPn6q50AAQIECBAgQIAAAQIECBAgQIAAAQIECBAgUDgBAVThhlSHCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQL5Cgig8vVXOwECBAgQIECAAAECBAgQIECAAAECBAgQIECgcAICqMINqQ4RIECAAAECBAgQIECAAAECBAgQIECAAAECBPIVEEDl6692AgQIECBAgAABAgQIECBAgAABAgQIECBAgEDhBARQhRtSHSJAgAABAgQIECBAgAABAgQIECBAgAABAgQI5CsggMrXX+0ECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgcIJCKAKN6Q6RIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDIV0AAla+/2gkQIECAAAECBAgQIECAAAECBAgQIECAAAEChRMQQBVuSHWIAAECBAgQIECAAAECBAgQIECAAAECBAgQIJCvgAAqX3+1EyBAgAABAgQIECBAgAABAgQIECBAgAABAgQKJyCAKtyQ6hABAgQIECBAgAABAgQIECBAgAABAgQIECBAIF8BAVS+/monQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBROQABVuCHVIQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAvgICqHz91U6AAAECBAgQIECAAAECBAgQIECAAAECBAgQKJyAAKpwQ6pDBAgQIECAAAECBAgQIECAAAECBAgQIECAAIF8BQRQ+fqrnQABAgQIECBAgAABAgQIECBAgAABAgQIECBQOAEBVOGGVIcIECBAgAABAgQIECBAgAABAgQIECBAgAABAvkKCKDy9Vc7AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKBwAgKowg2pDhEgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE8hUQQOXrr3YCBAgQIECAAAECBAgQIECAAAECBAgQIECAQOEEBFCFG1IdIkCAAAECBAgQIECAAAECBAgQIECAAAECBAjkKyCAytdf7QQIECBAgAABAgQIECBAgAABAgQIECBAgACBwgkIoAo3pDpEgAABAgQIECBAgAABAgQIECBAgAABAgQIEMhXQACVr7/aCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKFExBAFW5IdYgAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgkK+AACpff7UTIECAAAECBAgQIECAAAECBAgQIECAAAECBAonIIAq3JDqEAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgXwEBVL7+aidAgAABAgQIECBAgAABAgQIECBAgAABAgQIFE5AAFW4IdUhAgQIECBAgAABAgQIECBAgAABAgQIECBAgEC+AgKofP3VToAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAonIAAqnBDqkMECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgXwFBFD5+qudAAECBAgQIECAAAECBAgQIECAAAECBAgQIFA4AQFU4YZUhwgQIECAAAECBAgQIECAAAECBAgQIECAAAEC+QoIoPL1VzsBAgQIECBAgAABAgQIECBAgAABAgQIECBAoHACAqjCDakOESBAgAABAgQIECBAgAABAgQIECBAgAABAgTyFRBA5euvdgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBA4QQEUIUbUh0iQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECOQrIIDK11/tBAgQIECAAAECBAgQIECAAAECBAgQIECAAIHCCQigCjekOkSAAAECBAgQIECAAAECBAgQIECAAAECBAgQyFdAAJWvv9oJECBAgAABAgQIECBAgAABAgQIECBAgAABAoUTEEAVbkh1iAABAgQIECBAgAABAgQIECBAgAABAgQIECCQr4AAKl9/tRMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECicggCrckOoQAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBfAQFUvv5qJ0CAAAECBAgQIECAAAECBAgQIECAAAECBAgUTkAAVbgh1SECBAgQIECAAAECBAgQIECAAAECBAgQIECAQL4CAqh8/dVOgAABAgQIECBAgAABAgQIECBAgAABAgQIECicgACqcEOqQwQIECBAgAABAgQIECBAgAABAgQIECBAgACBfAUEUPn6q50AAQIECBAgQIAAAQIECBAgQIAAAQIECBAgUDgBAVThhlSHCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQL5Cgig8vVXOwECBAgQIECAAAECBAgQIECAAAECBAgQIECgcAICqMINqQ4RIECAAAECBAgQIECAAAECBAgQIECAAAECBPIVEEDl6692AgQIECBAgAABAgQIECBAgAABAgQIECBAgEDhBARQhRtSHSJAgAABAgQIECBAgAABAgQIECBAgAABAgQI5CsggMrXX+0ECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgcIJCKAKN6Q6RIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDIV0AAla+/2gkQIECAAAECBAgQIECAAAECBAgQIECAAAEChRMQQBVuSHWIAAECBAgQIECAAAECBAgQIECAAAECBAgQIJCvgAAqX3+1EyBAgAABAgQIECBAgAABAgQIECBAgAABAgQKJyCAKtyQ6hABAgQIECBAgAABAgQIECBAgAABAgQIECBAIF8BAVS+/monQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBROQABVuCHVIQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAvgICqHz91U6AAAECBAgQIECAAAECBAgQIECAAAECBAgQKJyAAKpwQ6pDBAgQIECAAAECBAgQIECAAAECBAgQIECAAIF8BQRQ+fqrnQABAgQIECBAgAABAgQIECBAgAABAgQIECBQOAEBVOGGVIcIECBAgAABAgQIECBAgAABAgQIECBAgAABAvkKCKDy9Vc7AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKBwAgKowg2pDhEgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE8hUQQOXrr3YCBAgQIECAAAECBAgQIECAAAECBAgQIECAQOEEBFCFG1IdIkCAAAECBAgQIECAAAECBAgQIECAAAECBAjkKyCAytdf7QQIECBAgAABAgQIECBAgAABAgQIECBAgACBwgkIoAo3pDpEgAABAgQIECBAgAABAgQIECBAgAABAgQIEMhXQACVr7/aCRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKFExBAFW5IdYgAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgkK+AACpff7UTIECAAAECBAgQIECAAAECBAgQIECAAAECBAonIIAq3JDqEAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgXwEBVL7+aidAgAABAgQIECBAgAABAgQIECBAgAABAgQIFE5AAFW4IdUhAgQIECBAgAABAgQIECBAgAABAgQIECBAgEC+AgKofP3VToAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAonIAAqnBDqkMECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgXwFBFD5+qudAAECBAgQIECAAAECBAgQIECAAAECBAgQIFA4AQFU4YZUhwgQIECAAAECBAgQIECAAAECBAgQIECAAAEC+QoIoPL1VzsBAgQIECBAgAABAgQIECBAgAABAgQIECBAoHACAqjCDakOESBAgAABAgQIECBAgAABAgQIECBAgAABAgTyFRBA5euvdgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBA4QQEUIUbUh0iQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECOQrIIDK11/tBAgQIECAAAECBAgQIECAAAECBAgQIECAAIHCCQigCjekOkSAAAECBAgQIECAAAECBAgQIECAAAECBAgQyFdAAJWvv9oJECBAgAABAgQIECBAgAABAgQIECBAgAABAoUTEEAVbkh1iAABAgQIECBAgAABAgQIECBAgAABAgQIECCQr4AAKl9/tRMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECicggCrckOoQAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCBfAQFUvv5qJ0CAAAECBAgQIECAAAECBAgQIECAAAECBAgUTkAAVbgh1SECBAgQIECAAAECBAgQIECAAAECBAgQIECAQL4CAqh8/dVOgAABAgQIECBAgAABAgQIECBAgAABAgQIECicgACqcEOqQwQIECBAgAABAgQIECBAgAABAgQIECBAgACBfAUEUPn6q50AAQIECBAgQIAAAQIECBAgQIAAAQIECBAgUDgBAVThhlSHCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQL5Cgig8vVXOwECBAgQIECAAAECBAgQIECAAAECBAgQIECgcAICqMINqQ4RIECAAAECBAgQIECAAAECBAgQIECAAAECBPIVEEDl6692AgQIECBAgAABAgQIECBAgAABAgQIECBAgEDhBARQhRtSHSJAgAABAgQIECBAgAABAgQIECBAgAABAgQI5CsggMrXX+0ECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgcIJCKAKN6Q6RIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDIV6DeMj02nJpvE9ROgAABAgQIECBAgAABAgQIECBAgAABAgQIECBQJAEzoIo0mvpCgAABAgQIECBAgAABAgQIECBAgAABAgQIECgBAQFUCQyCJhAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEiiQggCrSaOoLAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKAEBARQJTAImkCAAAECBAgQIECAAAECBAgQIECAAAECBAgQKJKAAKpIo6kvBAgQIECAAAECBAgQIECAAAECBAgQIECAAIESEBBAlcAgaAIBAgQIECBAgAABAgQIECBAgAABAgQIECBAoEgCAqgijaa+ECBAgAABAgQIECBAgAABAgQIECBAgAABAgRKQEAAVQKDoAkECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgSIJCKCKNJr6QoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAoAQEBVAkMgiYQIECAAAECBAgQIECAAAECBAgQIECAAAECBIokIIAq0mjqCwECBAgQIECAAAECBAgQIECAAAECBAgQIECgBAQEUCUwCJpAgAABAgQIECBAgAABAgQIECBAgAABAgQIECiSgACqSKOpLwQIECBAgAABAgQIECBAgAABAgQIECBAgACBEhAQQJXAIGgCAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKBIAgKoIo2mvhAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIESkBAAFUCg6AJBAgQIECAAAECBAgQIECAAAECBAgQIECAAIEiCQigijSa+kKAAAECBAgQIECAAAECBAgQIECAAAECBAgQKAEBAVQJDIImECBAgAABAgQIECBAgAABAgQIECBAgAABAgSKJCCAKtJo6gsBAgQIECBAgAABAgQIECBAgAABAgQIECBAoAQEBFAlMAiaQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAoksD/AxNWEy9iPvIAAAAAAElFTkSuQmCC" + } + }, + "cell_type": "markdown", + "id": "ad9e20ae-934a-4b98-b6ab-091c77572c61", + "metadata": {}, + "source": [ + "The central account has an LF tag `data_classification:dev` which we will first add to glue table and grant consumer role permissions to that tag\n", + "\n", + "![image.png](attachment:d1f0c7d4-d102-42f3-a1fc-b26eeb94a2bf.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5506c39d-5b59-436f-82ca-ba1934e60c4d", + "metadata": {}, + "outputs": [], + "source": [ + "lf_client_central = central_acc_boto_session.client('lakeformation')\n", + "lf_client_central.get_data_lake_settings()\n", + "\n", + "lf_client_central.add_lf_tags_to_resource(\n", + " Resource={\n", + " 'Table': {\n", + " 'CatalogId': str(central_account),\n", + " 'DatabaseName': database_name,\n", + " 'Name': table_name\n", + " }\n", + " },\n", + " LFTags=[\n", + " {\n", + " 'CatalogId': str(central_account),\n", + " 'TagKey': 'data_classification',\n", + " 'TagValues': ['dev']\n", + " }\n", + " ]\n", + ")\n", + "print(f\"Tagged table {database_name}.{table_name} with SharedAccess=consumer\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "c0bfc0ff-95be-47a5-b49a-028adc23a8c9", + "metadata": {}, + "source": [ + "Now we need to grant the role in consumer account permissions to the LF tag" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c069580b-6254-4173-a618-2bdf2fbd2889", + "metadata": {}, + "outputs": [], + "source": [ + "lf_client_central.grant_permissions(\n", + " Principal={\n", + " 'DataLakePrincipalIdentifier': acc_to_role_arn[consumer_account]\n", + " },\n", + " Resource={\n", + " 'LFTagPolicy': {\n", + " 'CatalogId': str(central_account),\n", + " 'ResourceType': 'TABLE',\n", + " 'Expression': [\n", + " {\n", + " 'TagKey': 'data_classification',\n", + " 'TagValues': ['dev']\n", + " }\n", + " ]\n", + " }\n", + " },\n", + " Permissions=['SELECT', 'DESCRIBE'],\n", + " PermissionsWithGrantOption=[]\n", + ")\n", + "\n", + "\n", + "print(f\"Granted LF-tag based SELECT/DESCRIBE to consumer account {consumer_account}\")\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "8508880e-a856-4574-8c8a-edbc972c9326", + "metadata": {}, + "source": [ + "Cross account lakeformation grant permissions automatically creates a RAM share so we need to accept that in consumer account" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df5665a2-1817-4366-97a6-7370bb3ebf44", + "metadata": {}, + "outputs": [], + "source": [ + "# Producer account accepts the RAM invitation\n", + "ram_client_consumer = consumer_acc_boto_session.client('ram')\n", + "\n", + "response = ram_client_consumer.get_resource_share_invitations()\n", + "pending = [\n", + " inv for inv in response['resourceShareInvitations']\n", + " if inv['status'] == 'PENDING' and inv['senderAccountId'] == str(central_account)\n", + "]\n", + "for inv in pending:\n", + " ram_client_consumer.accept_resource_share_invitation(\n", + " resourceShareInvitationArn=inv['resourceShareInvitationArn']\n", + " )\n", + " print(f\"Accepted: {inv['resourceShareInvitationArn']}\")" + ] + }, + { + "cell_type": "markdown", + "id": "305acbb5-80b4-4890-adb0-954beba91995", + "metadata": {}, + "source": [ + "## 4. Consumer reads data from the glue table using Athena" + ] + }, + { + "cell_type": "markdown", + "id": "3fa4fe66-4e03-4197-80b5-116f1c591183", + "metadata": {}, + "source": [ + "create a link between glue table in central and the consumer account" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b089a0cf-e69d-461a-91ab-39d3fc17dc7e", + "metadata": {}, + "outputs": [], + "source": [ + "glue_client_consumer = consumer_acc_boto_session.client('glue')\n", + "\n", + "CONSUMER_DB_NAME = 'shared_feature_store_db'\n", + "try:\n", + " glue_client_consumer.create_database(\n", + " DatabaseInput={'Name': CONSUMER_DB_NAME}\n", + " )\n", + " print(f\"Created database: {CONSUMER_DB_NAME}\")\n", + "except glue_client_consumer.exceptions.AlreadyExistsException:\n", + " print(f\"Database {CONSUMER_DB_NAME} already exists\")\n", + "\n", + "try:\n", + " glue_client_consumer.create_table(\n", + " DatabaseName=CONSUMER_DB_NAME,\n", + " TableInput={\n", + " 'Name': f'{table_name}_link',\n", + " 'TargetTable': {\n", + " 'CatalogId': str(central_account),\n", + " 'DatabaseName': database_name,\n", + " 'Name': table_name\n", + " }\n", + " }\n", + " )\n", + " print(f\"Created resource link: {CONSUMER_DB_NAME}.{table_name}_link\")\n", + "except glue_client_consumer.exceptions.AlreadyExistsException:\n", + " print(\"Resource link already exists\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4be3b18e-9682-4edd-bfd1-603932622b0b", + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "\n", + "athena_client = consumer_acc_boto_session.client('athena')\n", + "CONSUMER_S3_BUCKET = consumer_acc_sagemaker_session.default_bucket()\n", + "\n", + "query = f'SELECT * FROM {CONSUMER_DB_NAME}.{table_name}_link LIMIT 10'\n", + "\n", + "response = athena_client.start_query_execution(\n", + " QueryString=query,\n", + " ResultConfiguration={\n", + " 'OutputLocation': f's3://{CONSUMER_S3_BUCKET}/athena-results/'\n", + " }\n", + ")\n", + "\n", + "query_id = response['QueryExecutionId']\n", + "print(f\"Query started: {query_id}\")\n", + "\n", + "while True:\n", + " status = athena_client.get_query_execution(QueryExecutionId=query_id)\n", + " state = status['QueryExecution']['Status']['State']\n", + " if state in ['SUCCEEDED', 'FAILED', 'CANCELLED']:\n", + " break\n", + " print(f\"Status: {state}...\")\n", + " time.sleep(2)\n", + "\n", + "if state == 'SUCCEEDED':\n", + " results = athena_client.get_query_results(QueryExecutionId=query_id)\n", + " for row in results['ResultSet']['Rows']:\n", + " print([col.get('VarCharValue', '') for col in row['Data']])\n", + "else:\n", + " reason = status['QueryExecution']['Status'].get('StateChangeReason', 'unknown')\n", + " print(f\"Query {state}: {reason}\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b54072b5-eed0-41de-b238-a79f8884d1e6", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "py3.10.14", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.14" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": { + "15d7159da97842f289a6eae80d88f367": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "2.0.0", + "model_name": "LayoutModel", + "state": {} + }, + "16cf8427b8774feabe06a535381438ef": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "2.0.0", + "model_name": "LayoutModel", + "state": {} + } + }, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/v3-examples/ml-ops-examples/imgs/fs-lf-cross-account1.png b/v3-examples/ml-ops-examples/imgs/fs-lf-cross-account1.png new file mode 100644 index 0000000000000000000000000000000000000000..a126d2e207d268e65a7e03515a3b6dfde8c7ad67 GIT binary patch literal 476328 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

k4H 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

g0cR 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�(h8P(T8TAtwvCz+Iw;!EI%70bl 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 literal 0 HcmV?d00001 From 914f0fd16321e765accdfe6f174915554769a854 Mon Sep 17 00:00:00 2001 From: BassemHalim Date: Wed, 4 Mar 2026 13:17:02 -0800 Subject: [PATCH 09/10] reusing clients + bug fixes --- .../mlops/feature_store/feature_group.py | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py b/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py index d4cff70988..8b8db82164 100644 --- a/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py +++ b/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py @@ -2,6 +2,7 @@ # Licensed under the Apache License, Version 2.0 """FeatureGroup with Lake Formation support.""" +import json import logging from typing import List, Optional @@ -132,6 +133,7 @@ def _generate_s3_deny_policy( s3_prefix: str, lake_formation_role_arn: str, feature_store_role_arn: str, + region: Optional[str] = None, ) -> dict: """ Generate an S3 deny policy for Lake Formation governance. @@ -144,6 +146,8 @@ def _generate_s3_deny_policy( s3_prefix: S3 prefix path (without bucket name). lake_formation_role_arn: Lake Formation registration role ARN. feature_store_role_arn: Feature Store execution role ARN. + region: AWS region name (e.g., 'us-west-2'). Used to determine the correct + partition for S3 ARNs. If not provided, defaults to 'aws' partition. Returns: S3 bucket policy as a dict with valid JSON structure containing: @@ -152,6 +156,8 @@ def _generate_s3_deny_policy( 1. Deny GetObject, PutObject, DeleteObject on data prefix except allowed principals 2. Deny ListBucket on bucket with prefix condition except allowed principals """ + partition = aws_partition(region) if region else "aws" + policy = { "Version": "2012-10-17", "Statement": [ @@ -160,7 +166,7 @@ def _generate_s3_deny_policy( "Effect": "Deny", "Principal": "*", "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"], - "Resource": f"arn:aws:s3:::{bucket_name}/{s3_prefix}/*", + "Resource": f"arn:{partition}:s3:::{bucket_name}/{s3_prefix}/*", "Condition": { "StringNotEquals": { "aws:PrincipalArn": [ @@ -175,7 +181,7 @@ def _generate_s3_deny_policy( "Effect": "Deny", "Principal": "*", "Action": "s3:ListBucket", - "Resource": f"arn:aws:s3:::{bucket_name}", + "Resource": f"arn:{partition}:s3:::{bucket_name}", "Condition": { "StringLike": {"s3:prefix": f"{s3_prefix}/*"}, "StringNotEquals": { @@ -196,7 +202,11 @@ def _get_lake_formation_client( region: Optional[str] = None, ): """ - Get a Lake Formation client. + Get a Lake Formation client, reusing a cached client when possible. + + The client is cached on the instance keyed by (session, region). Subsequent + calls with the same arguments return the existing client instead of creating + a new one. Args: session: Boto3 session. If not provided, a new session will be created. @@ -205,9 +215,17 @@ def _get_lake_formation_client( Returns: A boto3 Lake Formation client. """ - # TODO: don't create w new client for each call - boto_session = session or Session() - return boto_session.client("lakeformation", region_name=region) + cache_key = (id(session), region) + if not hasattr(self, "_lf_client_cache"): + self._lf_client_cache: dict = {} + + if cache_key not in self._lf_client_cache: + boto_session = session or Session() + self._lf_client_cache[cache_key] = boto_session.client( + "lakeformation", region_name=region + ) + + return self._lf_client_cache[cache_key] def _register_s3_with_lake_formation( self, @@ -242,7 +260,7 @@ def _register_s3_with_lake_formation( # Get region from session if not provided if region is None and session is not None: - region = session.region_name() + region = session.region_name client = self._get_lake_formation_client(session, region) resource_arn = self._s3_uri_to_arn(s3_location, region) @@ -288,7 +306,7 @@ def _revoke_iam_allowed_principal( """ # Get region from session if not provided if region is None and session is not None: - region = session.region_name() + region = session.region_name client = self._get_lake_formation_client(session, region) @@ -341,7 +359,7 @@ def _grant_lake_formation_permissions( """ # Get region from session if not provided if region is None and session is not None: - region = session.region_name() + region = session.region_name client = self._get_lake_formation_client(session, region) permissions = ["SELECT", "INSERT", "DELETE", "DESCRIBE", "ALTER"] @@ -569,11 +587,10 @@ def enable_lake_formation( s3_prefix=s3_prefix, lake_formation_role_arn=lf_role_arn, feature_store_role_arn=role_arn_str, + region=region, ) # Print policy with clear instructions - import json - print("\n" + "=" * 80) print("S3 Bucket Policy Update recommended") print("=" * 80) From d5934884dc86542da4e4a7e315517c0b7b7b209f Mon Sep 17 00:00:00 2001 From: BassemHalim Date: Thu, 5 Mar 2026 09:05:40 -0800 Subject: [PATCH 10/10] feat: add disable_hybrid_access_mode + update tests --- .../mlops/feature_store/feature_group.py | 48 +++-- .../mlops/feature_store/test_lakeformation.py | 178 ++++++++++++++++++ 2 files changed, 211 insertions(+), 15 deletions(-) diff --git a/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py b/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py index 8b8db82164..97863c3f04 100644 --- a/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py +++ b/sagemaker-mlops/src/sagemaker/mlops/feature_store/feature_group.py @@ -42,12 +42,17 @@ class LakeFormationConfig(Base): show_s3_policy: If True, prints the S3 deny policy to the console after successful Lake Formation setup. This policy should be added to your S3 bucket to restrict access to only the allowed principals. Default is False. + disable_hybrid_access_mode: If True, revokes IAMAllowedPrincipal permissions from + the Glue table, moving it to Lake Formation-only access mode. If False, keeps + hybrid access mode where both IAM and Lake Formation control access. + Default is True (LF-only mode). """ enabled: bool = False use_service_linked_role: bool = True registration_role_arn: Optional[str] = None show_s3_policy: bool = False + disable_hybrid_access_mode: bool = True class FeatureGroup(CoreFeatureGroup): @@ -395,6 +400,7 @@ def enable_lake_formation( registration_role_arn: Optional[str] = None, wait_for_active: bool = False, show_s3_policy: bool = False, + disable_hybrid_access_mode: bool = True, ) -> dict: """ Enable Lake Formation governance for this Feature Group's offline store. @@ -404,7 +410,8 @@ def enable_lake_formation( 2. Validates Feature Group status is 'Created' 3. Registers the offline store S3 location as data lake location 4. Grants the execution role permissions on the Glue table - 5. Revokes IAMAllowedPrincipal permissions from the Glue table + 5. Optionally revokes IAMAllowedPrincipal permissions from the Glue table + (controlled by disable_hybrid_access_mode) The role ARN is automatically extracted from the Feature Group's configuration. Each phase depends on the success of the previous phase - if any phase fails, @@ -424,11 +431,15 @@ def enable_lake_formation( show_s3_policy: If True, prints the S3 deny policy to the console after successful Lake Formation setup. This policy should be added to your S3 bucket to restrict access to only the allowed principals. Default is False. + disable_hybrid_access_mode: If True, revokes IAMAllowedPrincipal permissions from + the Glue table, moving it to Lake Formation-only access mode. If False, keeps + hybrid access mode where both IAM and Lake Formation control access. + Default is True. Returns: Dict with status of each Lake Formation operation: - s3_registration: bool - - iam_principal_revoked: bool + - iam_principal_revoked: bool or None (None when disable_hybrid_access_mode=False) - permissions_granted: bool Raises: @@ -548,19 +559,25 @@ def enable_lake_formation( f"Subsequent phases skipped. Results: {results}" ) - # Phase 3: Revoke IAMAllowedPrincipal permissions - try: - results["iam_principal_revoked"] = self._revoke_iam_allowed_principal( - database_name_str, table_name_str, session, region - ) - except Exception as e: - raise RuntimeError( - f"Failed to revoke IAMAllowedPrincipal permissions. Results: {results}. Error: {e}" - ) from e - - if not results["iam_principal_revoked"]: - raise RuntimeError( - f"Failed to revoke IAMAllowedPrincipal permissions. Results: {results}" + # Phase 3: Revoke IAMAllowedPrincipal permissions (if disabling hybrid access mode) + if disable_hybrid_access_mode: + try: + results["iam_principal_revoked"] = self._revoke_iam_allowed_principal( + database_name_str, table_name_str, session, region + ) + except Exception as e: + raise RuntimeError( + f"Failed to revoke IAMAllowedPrincipal permissions. Results: {results}. Error: {e}" + ) from e + + if not results["iam_principal_revoked"]: + raise RuntimeError( + f"Failed to revoke IAMAllowedPrincipal permissions. Results: {results}" + ) + else: + results["iam_principal_revoked"] = None + logger.info( + "Skipping IAMAllowedPrincipal revocation - hybrid access mode preserved." ) logger.info(f"Lake Formation setup complete for {self.feature_group_name}: {results}") @@ -724,5 +741,6 @@ def create( use_service_linked_role=lake_formation_config.use_service_linked_role, registration_role_arn=lake_formation_config.registration_role_arn, show_s3_policy=lake_formation_config.show_s3_policy, + disable_hybrid_access_mode=lake_formation_config.disable_hybrid_access_mode, ) return feature_group diff --git a/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_lakeformation.py b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_lakeformation.py index e4d44df37a..534d4a6406 100644 --- a/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_lakeformation.py +++ b/sagemaker-mlops/tests/unit/sagemaker/mlops/feature_store/test_lakeformation.py @@ -69,6 +69,37 @@ def test_creates_client_with_provided_session(self): mock_session.client.assert_called_with("lakeformation", region_name="us-west-2") assert client == mock_client + def test_caches_client_for_same_session_and_region(self): + """Test that repeated calls with the same session and region reuse the cached client.""" + mock_session = MagicMock() + mock_client = MagicMock() + mock_session.client.return_value = mock_client + + fg = MagicMock(spec=FeatureGroup) + fg._get_lake_formation_client = FeatureGroup._get_lake_formation_client.__get__(fg) + + client1 = fg._get_lake_formation_client(session=mock_session, region="us-west-2") + client2 = fg._get_lake_formation_client(session=mock_session, region="us-west-2") + + assert client1 is client2 + mock_session.client.assert_called_once() + + def test_creates_new_client_for_different_region(self): + """Test that a different region produces a new client.""" + mock_session = MagicMock() + mock_client_west = MagicMock() + mock_client_east = MagicMock() + mock_session.client.side_effect = [mock_client_west, mock_client_east] + + fg = MagicMock(spec=FeatureGroup) + fg._get_lake_formation_client = FeatureGroup._get_lake_formation_client.__get__(fg) + + client1 = fg._get_lake_formation_client(session=mock_session, region="us-west-2") + client2 = fg._get_lake_formation_client(session=mock_session, region="us-east-1") + + assert client1 is not client2 + assert mock_session.client.call_count == 2 + class TestRegisterS3WithLakeFormation: """Tests for _register_s3_with_lake_formation method.""" @@ -942,6 +973,7 @@ def test_enable_lake_formation_called_when_enabled( use_service_linked_role=True, registration_role_arn=None, show_s3_policy=False, + disable_hybrid_access_mode=True, ) # Verify the feature group was returned assert result == mock_fg @@ -1150,11 +1182,157 @@ def test_use_service_linked_role_extraction_from_config( use_service_linked_role=use_slr, registration_role_arn=expected_registration_role, show_s3_policy=False, + disable_hybrid_access_mode=True, ) # Verify the feature group was returned assert result == mock_fg +class TestDisableHybridAccessMode: + """Tests for disable_hybrid_access_mode parameter in enable_lake_formation.""" + + def setup_method(self): + """Set up test fixtures.""" + from sagemaker.core.shapes import OfflineStoreConfig, S3StorageConfig, DataCatalogConfig + + self.fg = FeatureGroup(feature_group_name="test-fg") + self.fg.offline_store_config = OfflineStoreConfig( + s3_storage_config=S3StorageConfig( + s3_uri="s3://test-bucket/path", + resolved_output_s3_uri="s3://test-bucket/resolved-path", + ), + data_catalog_config=DataCatalogConfig( + catalog="AwsDataCatalog", database="test_db", table_name="test_table" + ), + ) + self.fg.role_arn = "arn:aws:iam::123456789012:role/TestRole" + self.fg.feature_group_arn = "arn:aws:sagemaker:us-west-2:123456789012:feature-group/test-fg" + self.fg.feature_group_status = "Created" + + @patch.object(FeatureGroup, "refresh") + @patch.object(FeatureGroup, "_register_s3_with_lake_formation") + @patch.object(FeatureGroup, "_grant_lake_formation_permissions") + @patch.object(FeatureGroup, "_revoke_iam_allowed_principal") + def test_revoke_called_when_disable_hybrid_access_mode_true( + self, mock_revoke, mock_grant, mock_register, mock_refresh + ): + """Test that IAMAllowedPrincipal is revoked when disable_hybrid_access_mode=True (default).""" + mock_register.return_value = True + mock_grant.return_value = True + mock_revoke.return_value = True + + result = self.fg.enable_lake_formation(disable_hybrid_access_mode=True) + + mock_revoke.assert_called_once() + assert result["iam_principal_revoked"] is True + + @patch.object(FeatureGroup, "refresh") + @patch.object(FeatureGroup, "_register_s3_with_lake_formation") + @patch.object(FeatureGroup, "_grant_lake_formation_permissions") + @patch.object(FeatureGroup, "_revoke_iam_allowed_principal") + def test_revoke_skipped_when_disable_hybrid_access_mode_false( + self, mock_revoke, mock_grant, mock_register, mock_refresh + ): + """Test that IAMAllowedPrincipal revocation is skipped when disable_hybrid_access_mode=False.""" + mock_register.return_value = True + mock_grant.return_value = True + + result = self.fg.enable_lake_formation(disable_hybrid_access_mode=False) + + mock_revoke.assert_not_called() + assert result["iam_principal_revoked"] is None + assert result["s3_registration"] is True + assert result["permissions_granted"] is True + + @patch.object(FeatureGroup, "refresh") + @patch.object(FeatureGroup, "_register_s3_with_lake_formation") + @patch.object(FeatureGroup, "_grant_lake_formation_permissions") + @patch.object(FeatureGroup, "_revoke_iam_allowed_principal") + def test_default_disable_hybrid_access_mode_is_true( + self, mock_revoke, mock_grant, mock_register, mock_refresh + ): + """Test that disable_hybrid_access_mode defaults to True (revoke is called by default).""" + mock_register.return_value = True + mock_grant.return_value = True + mock_revoke.return_value = True + + # Call without specifying disable_hybrid_access_mode + result = self.fg.enable_lake_formation() + + mock_revoke.assert_called_once() + assert result["iam_principal_revoked"] is True + + +class TestCreateWithLakeFormationDisableHybridAccessMode: + """Tests for disable_hybrid_access_mode passed through create() via LakeFormationConfig.""" + + @patch("sagemaker.core.resources.Base.get_sagemaker_client") + @patch.object(FeatureGroup, "get") + @patch.object(FeatureGroup, "wait_for_status") + @patch.object(FeatureGroup, "enable_lake_formation") + def test_disable_hybrid_access_mode_false_passed_through_create( + self, mock_enable_lf, mock_wait, mock_get, mock_get_client + ): + """Test that disable_hybrid_access_mode=False is passed through create() to enable_lake_formation.""" + from sagemaker.core.shapes import FeatureDefinition, OfflineStoreConfig, S3StorageConfig + + mock_client = MagicMock() + mock_client.create_feature_group.return_value = { + "FeatureGroupArn": "arn:aws:sagemaker:us-west-2:123456789012:feature-group/test" + } + mock_get_client.return_value = mock_client + + mock_fg = MagicMock(spec=FeatureGroup) + mock_fg.wait_for_status = mock_wait + mock_fg.enable_lake_formation = mock_enable_lf + mock_get.return_value = mock_fg + + feature_definitions = [ + FeatureDefinition(feature_name="record_id", feature_type="String"), + FeatureDefinition(feature_name="event_time", feature_type="String"), + ] + + lf_config = LakeFormationConfig() + lf_config.enabled = True + lf_config.disable_hybrid_access_mode = False + + FeatureGroup.create( + feature_group_name="test-fg", + record_identifier_feature_name="record_id", + event_time_feature_name="event_time", + feature_definitions=feature_definitions, + offline_store_config=OfflineStoreConfig( + s3_storage_config=S3StorageConfig(s3_uri="s3://bucket/path") + ), + role_arn="arn:aws:iam::123456789012:role/TestRole", + lake_formation_config=lf_config, + ) + + mock_enable_lf.assert_called_once_with( + session=None, + region=None, + use_service_linked_role=True, + registration_role_arn=None, + show_s3_policy=False, + disable_hybrid_access_mode=False, + ) + + +class TestLakeFormationConfigDefaults: + """Tests for LakeFormationConfig default values.""" + + def test_disable_hybrid_access_mode_defaults_to_true(self): + """Test that LakeFormationConfig.disable_hybrid_access_mode defaults to True.""" + config = LakeFormationConfig() + assert config.disable_hybrid_access_mode is True + + def test_disable_hybrid_access_mode_can_be_set_to_false(self): + """Test that LakeFormationConfig.disable_hybrid_access_mode can be set to False.""" + config = LakeFormationConfig() + config.disable_hybrid_access_mode = False + assert config.disable_hybrid_access_mode is False + + class TestExtractAccountIdFromArn: """Tests for _extract_account_id_from_arn static method."""