Skip to content
This repository was archived by the owner on Nov 6, 2023. It is now read-only.

Commit 9635d71

Browse files
authored
feat(s3): use bucket name for data_source_oddrn (#45)
1 parent a541284 commit 9635d71

8 files changed

Lines changed: 494 additions & 509 deletions

File tree

collector_config.yaml

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
1-
default_pulling_interval: 10
2-
token:
1+
# Description: Configuration file for the collector. Find more examples in config_examples folder.
2+
3+
default_pulling_interval: 60
4+
token: <token>
35
platform_host_url: "http://localhost:8080"
46
plugins:
57
- type: s3
68
name: s3_adapter
7-
aws_access_key_id:
8-
aws_secret_access_key:
9-
datasets:
10-
- bucket: my_bucket
11-
prefix: prefix
9+
# aws_access_key_id: <aws_access_key_id>
10+
# aws_secret_access_key: <aws_secret_access_key>
11+
# aws_region: <aws_region>
12+
# aws_session_token: <aws_session_token>
13+
# aws_role_arn: <aws_role_arn>
14+
# aws_role_session_name: <aws_role_session_name>
15+
# profile_name: <profile_name>
16+
# endpoint_url: <endpoint_url>
17+
dataset_config:
18+
- bucket: <bucket_name>
19+
prefix: <optional_prefix>

config_examples/s3.yaml

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,49 @@
11
# S3 collector-config.yaml example
2-
# Note: The following example is for AWS S3. For S3 compatible storage, see the example below.
32
# All AWS S3 parameters are optional according to default behavior of boto3.
3+
# If not provided, boto3 will search for credentials in environment variables, ~/.aws/credentials and ~/.aws/config
4+
45
platform_host_url: http://localhost:8080
5-
default_pulling_interval: 10 # Can be omitted to run collector once
6+
default_pulling_interval: 60 # Pulling interval in minutes. Can be omitted to run collector once
67
token: "" # Token that must be retrieved from the platform
78
plugins:
89
- type: s3
910
name: s3_adapter
1011
aws_secret_access_key: <aws_secret_access_key> # Optional.
1112
aws_access_key_id: <aws_access_key_id> # Optional.
12-
aws_session_token: <aws_session_token> # Optional.
13+
aws_session_token: <aws_session_token> # Optional. Required if using temporary credentials.
1314
aws_region: <aws_region> # Optional.
15+
aws_role_arn: <aws_role_arn> # Optional. Required for assuming role with temporary credentials.
16+
aws_role_session_name: <aws_role_session_name> # Optional. Required for assuming role with temporary credentials.
17+
profile_name: <profile_name> # Optional.
1418
filename_filter: # Optional. Default filter allows each file to be ingested to platform.
1519
include: [ '.*.parquet' ]
1620
exclude: [ 'dev_.*' ]
17-
datasets:
18-
# Recursive fetch for all objects in the bucket.
19-
- bucket: my_bucket
20-
# Explicitly specify the prefix to file.
21-
- bucket: my_bucket
22-
prefix: folder/subfolder/file.csv
23-
# When we want to use the folder as a dataset. Very useful for partitioned datasets.
24-
# I.e it can be Hive partitioned dataset with structure like this:
25-
# s3://my_bucket/partitioned_data/year=2019/month=01/...
26-
- bucket: my_bucket
27-
prefix: partitioned_data/
28-
folder_as_dataset:
29-
file_format: parquet
30-
flavor: hive
31-
32-
#field_names must be provided if partition flavor was not used. I.e for structure like this:
33-
# s3://my_bucket/partitioned_data/year/...
34-
- bucket: my_bucket
35-
prefix: partitioned_data/
36-
folder_as_dataset:
37-
file_format: csv
38-
field_names: ['year']
39-
40-
# S3 compatible collector-config.yaml example, for example for Minio we need to specify endpoint_url
41-
platform_host_url: "http://localhost:8080"
42-
default_pulling_interval: 10
43-
token: ""
44-
plugins:
21+
dataset_config:
22+
bucket: my_bucket
23+
prefix: folder/subfolder/file.csv # Optional. Default is empty string.
24+
# When we want to use the folder as a dataset. Very useful for partitioned datasets.
25+
- type: s3
26+
name: s3_partitioned_adapter
27+
aws_secret_access_key: <aws_secret_access_key> # Optional.
28+
aws_access_key_id: <aws_access_key_id> # Optional.
29+
aws_session_token: <aws_session_token> # Optional. Required if using temporary credentials.
30+
aws_region: <aws_region> # Optional.
31+
aws_role_arn: <aws_role_arn> # Optional. Required for assuming role with temporary credentials.
32+
aws_role_session_name: <aws_role_session_name> # Optional. Required for assuming role with temporary credentials.
33+
profile_name: <profile_name> # Optional.
34+
dataset_config:
35+
bucket: my_bucket
36+
prefix: partitioned_data/
37+
folder_as_dataset:
38+
file_format: parquet # Format of the files in the folder. Can be parquet csv, tsv.
39+
flavor: hive # Optional. Default is hive. Can be hive or presto.
40+
field_names: ['year', 'month'] # Optional. Must be provided if flavor is other than hive. I.e. structure s3://my_bucket/partitioned_data/year/...
41+
# When S3 storage is compatible with AWS S3 API, for example Minio.
4542
- type: s3
4643
name: s3_minio_adapter
4744
endpoint_url: http://localhost:9000
4845
aws_secret_access_key: minioadmin
4946
aws_access_key_id: minioadmin
50-
datasets:
51-
- bucket: my_bucket
52-
prefix: partitioned_data
47+
dataset_config:
48+
bucket: my_bucket
5349

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,32 @@
1-
import traceback as tb
21
from typing import Iterable, Union
32

4-
from odd_collector_sdk.domain.adapter import AbstractAdapter
3+
from odd_collector_sdk.domain.adapter import BaseAdapter
54
from odd_models.models import DataEntityList
65
from oddrn_generator.generators import Generator, S3Generator
76

87
from odd_collector_aws.domain.plugin import S3Plugin
98
from odd_collector_aws.utils.create_generator import create_generator
109

1110
from .file_system import FileSystem
12-
from .logger import logger
1311
from .mapper.bucket import map_bucket
1412

1513

16-
class Adapter(AbstractAdapter):
14+
class Adapter(BaseAdapter):
1715
config: S3Plugin
1816
generator: Union[Generator, S3Generator]
1917

2018
def __init__(self, config: S3Plugin) -> None:
21-
self.config = config
22-
self.generator = create_generator(S3Generator, config)
19+
super().__init__(config)
2320
self.fs = FileSystem(config)
2421

25-
def get_data_source_oddrn(self) -> str:
26-
return self.generator.get_data_source_oddrn()
22+
def create_generator(self) -> Generator:
23+
return create_generator(S3Generator, self.config)
2724

2825
def get_data_entity_list(self) -> Iterable[DataEntityList]:
29-
for dataset_config in self.config.datasets:
30-
try:
31-
bucket = self.fs.get_bucket(dataset_config)
32-
data_entities = map_bucket(bucket, self.generator)
33-
34-
yield DataEntityList(
35-
data_source_oddrn=self.get_data_source_oddrn(),
36-
items=list(data_entities),
37-
)
38-
except Exception as e:
39-
logger.error(
40-
f"Error while processing bucket {dataset_config.bucket}: {e}."
41-
" SKIPPING."
42-
)
43-
logger.debug(tb.format_exc())
44-
continue
26+
bucket = self.fs.get_bucket(self.config.dataset_config)
27+
data_entities = map_bucket(bucket, self.generator)
28+
29+
yield DataEntityList(
30+
data_source_oddrn=self.get_data_source_oddrn(),
31+
items=list(data_entities),
32+
)

odd_collector_aws/domain/plugin.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from odd_collector_sdk.domain.filter import Filter
44
from odd_collector_sdk.domain.plugin import Plugin
55
from odd_collector_sdk.types import PluginFactory
6-
from pydantic import BaseModel, Field
6+
from pydantic import BaseModel, Field, validator
77

88
from odd_collector_aws.domain.dataset_config import DatasetConfig
99

@@ -73,9 +73,16 @@ class S3DeltaPlugin(AwsPlugin):
7373
class S3Plugin(AwsPlugin):
7474
type: Literal["s3"]
7575
endpoint_url: Optional[str] = None
76-
datasets: list[DatasetConfig]
76+
datasets: Optional[list[DatasetConfig]] = None
77+
dataset_config: DatasetConfig
7778
filename_filter: Optional[Filter] = Filter()
7879

80+
@validator("datasets", pre=True)
81+
def validate_datasets(cls, v):
82+
if v:
83+
raise ValueError("datasets field is deprecated, use dataset_config instead")
84+
85+
7986

8087
class QuicksightPlugin(AwsPlugin):
8188
type: Literal["quicksight"]

odd_collector_aws/logger.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
from odd_collector_sdk.logger import logger
2+
3+
logger = logger

odd_collector_aws/utils/create_generator.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import logging
2-
from typing import Type, TypeVar
2+
from typing import Type, TypeVar, cast
33

44
from botocore.exceptions import ClientError
55
from oddrn_generator import Generator
66
from oddrn_generator.generators import S3CustomGenerator, S3Generator
77

88
from odd_collector_aws.aws.aws_client import Aws
9-
from odd_collector_aws.domain.plugin import AwsPlugin
9+
from odd_collector_aws.domain.plugin import AwsPlugin, S3Plugin
1010
from odd_collector_aws.errors import AccountIdError
1111

1212
T = TypeVar("T", bound=Generator)
@@ -16,10 +16,13 @@ def create_generator(generator_cls: Type[T], aws_plugin: AwsPlugin) -> T:
1616
aws_client = Aws(aws_plugin)
1717

1818
if generator_cls == S3Generator:
19-
if aws_plugin.endpoint_url:
20-
return S3CustomGenerator(endpoint=aws_plugin.endpoint_url)
19+
config = cast(S3Plugin, aws_plugin)
20+
bucket = config.dataset_config.bucket
2121

22-
return generator_cls()
22+
if config.endpoint_url:
23+
return S3CustomGenerator(endpoint=config.endpoint_url, buckets=bucket)
24+
25+
return generator_cls(buckets=bucket)
2326

2427
account_id = aws_plugin.aws_account_id
2528

0 commit comments

Comments
 (0)