ob-metaflow-extensions 1.1.163rc7__tar.gz → 1.1.165__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ob-metaflow-extensions might be problematic. Click here for more details.
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/PKG-INFO +1 -1
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/__init__.py +35 -19
- ob_metaflow_extensions-1.1.165/metaflow_extensions/outerbounds/plugins/aws/__init__.py +4 -0
- ob_metaflow_extensions-1.1.165/metaflow_extensions/outerbounds/plugins/aws/assume_role.py +3 -0
- ob_metaflow_extensions-1.1.165/metaflow_extensions/outerbounds/plugins/aws/assume_role_decorator.py +65 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/toplevel/global_aliases_for_metaflow_package.py +23 -2
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/ob_metaflow_extensions.egg-info/PKG-INFO +1 -1
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/ob_metaflow_extensions.egg-info/SOURCES.txt +3 -2
- ob_metaflow_extensions-1.1.165/ob_metaflow_extensions.egg-info/requires.txt +3 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/setup.py +2 -2
- ob_metaflow_extensions-1.1.163rc7/metaflow_extensions/outerbounds/plugins/fast_bakery/baker.py +0 -110
- ob_metaflow_extensions-1.1.163rc7/metaflow_extensions/outerbounds/toplevel/ob_internal.py +0 -1
- ob_metaflow_extensions-1.1.163rc7/ob_metaflow_extensions.egg-info/requires.txt +0 -3
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/README.md +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/config/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/apps/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/apps/app_utils.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/apps/consts.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/apps/deploy_decorator.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/apps/supervisord_utils.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/auth_server.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/card_utilities/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/card_utilities/async_cards.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/card_utilities/extra_components.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/card_utilities/injector.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/coreweave.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/nebius.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/fast_bakery/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/fast_bakery/docker_environment.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/fast_bakery/fast_bakery.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/fast_bakery/fast_bakery_cli.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/fast_bakery/fast_bakery_decorator.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/kubernetes/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/kubernetes/kubernetes_client.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/kubernetes/pod_killer.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/nim/card.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/nim/nim_decorator.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/nim/nim_manager.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/nim/utils.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/nvcf/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/nvcf/constants.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/nvcf/exceptions.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/nvcf/heartbeat_store.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/nvcf/nvcf.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/nvcf/nvcf_cli.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/nvcf/nvcf_decorator.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/nvcf/utils.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/nvct/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/nvct/exceptions.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/nvct/nvct.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/nvct/nvct_cli.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/nvct/nvct_decorator.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/nvct/nvct_runner.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/nvct/utils.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/ollama/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/ollama/constants.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/ollama/exceptions.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/ollama/ollama.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/ollama/status_card.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/perimeters.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/profilers/deco_injector.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/profilers/gpu_profile_decorator.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/secrets/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/secrets/secrets.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/snowflake/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/snowflake/snowflake.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/snowpark/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_cli.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_client.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_decorator.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_exceptions.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_job.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_service_spec.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/tensorboard/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/plugins/torchtune/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/profilers/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/profilers/gpu.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/remote_config.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/toplevel/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/toplevel/plugins/azure/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/toplevel/plugins/gcp/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/toplevel/plugins/kubernetes/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/toplevel/plugins/ollama/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/toplevel/plugins/snowflake/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/metaflow_extensions/outerbounds/toplevel/plugins/torchtune/__init__.py +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/ob_metaflow_extensions.egg-info/dependency_links.txt +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/ob_metaflow_extensions.egg-info/top_level.txt +0 -0
- {ob_metaflow_extensions-1.1.163rc7 → ob_metaflow_extensions-1.1.165}/setup.cfg +0 -0
|
@@ -41,6 +41,9 @@ def get_boto3_session(role_arn=None, session_vars=None):
|
|
|
41
41
|
import boto3
|
|
42
42
|
import botocore
|
|
43
43
|
from metaflow_extensions.outerbounds.plugins.auth_server import get_token
|
|
44
|
+
from metaflow_extensions.outerbounds.plugins.aws.assume_role import (
|
|
45
|
+
OBP_ASSUME_ROLE_ARN_ENV_VAR,
|
|
46
|
+
)
|
|
44
47
|
|
|
45
48
|
from hashlib import sha256
|
|
46
49
|
from metaflow.util import get_username
|
|
@@ -49,6 +52,10 @@ def get_boto3_session(role_arn=None, session_vars=None):
|
|
|
49
52
|
|
|
50
53
|
token_info = get_token("/generate/aws")
|
|
51
54
|
|
|
55
|
+
# Check if the assume_role decorator has set a role ARN via environment variable
|
|
56
|
+
# This takes precedence over CSPR role
|
|
57
|
+
decorator_role_arn = os.environ.get(OBP_ASSUME_ROLE_ARN_ENV_VAR)
|
|
58
|
+
|
|
52
59
|
# Write token to a file. The file name is derived from the user name
|
|
53
60
|
# so it works with multiple users on the same machine.
|
|
54
61
|
#
|
|
@@ -69,12 +76,13 @@ def get_boto3_session(role_arn=None, session_vars=None):
|
|
|
69
76
|
if token_info.get("cspr_role_arn"):
|
|
70
77
|
cspr_role = token_info["cspr_role_arn"]
|
|
71
78
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
79
|
+
# If assume_role decorator is used, prioritize it over CSPR role
|
|
80
|
+
effective_role = decorator_role_arn or cspr_role
|
|
81
|
+
if effective_role:
|
|
82
|
+
# If we have either a decorator role or CSPR role, set up AWS config
|
|
75
83
|
# with two profiles. One to get credentials for the task role
|
|
76
84
|
# in exchange for the OIDC token, and second to assume the
|
|
77
|
-
#
|
|
85
|
+
# effective role using the task role credentials.
|
|
78
86
|
import configparser
|
|
79
87
|
from io import StringIO
|
|
80
88
|
|
|
@@ -86,9 +94,9 @@ def get_boto3_session(role_arn=None, session_vars=None):
|
|
|
86
94
|
"web_identity_token_file": token_file,
|
|
87
95
|
}
|
|
88
96
|
|
|
89
|
-
#
|
|
90
|
-
aws_config["profile
|
|
91
|
-
"role_arn":
|
|
97
|
+
# Effective role profile (decorator role or CSPR role)
|
|
98
|
+
aws_config["profile effective"] = {
|
|
99
|
+
"role_arn": effective_role,
|
|
92
100
|
"source_profile": "task",
|
|
93
101
|
}
|
|
94
102
|
|
|
@@ -104,7 +112,7 @@ def get_boto3_session(role_arn=None, session_vars=None):
|
|
|
104
112
|
tmp_aws_config_file = f.name
|
|
105
113
|
os.rename(tmp_aws_config_file, aws_config_file)
|
|
106
114
|
os.environ["AWS_CONFIG_FILE"] = aws_config_file
|
|
107
|
-
os.environ["AWS_PROFILE"] = "
|
|
115
|
+
os.environ["AWS_PROFILE"] = "effective"
|
|
108
116
|
else:
|
|
109
117
|
os.environ["AWS_WEB_IDENTITY_TOKEN_FILE"] = token_file
|
|
110
118
|
os.environ["AWS_ROLE_ARN"] = token_info["role_arn"]
|
|
@@ -116,21 +124,29 @@ def get_boto3_session(role_arn=None, session_vars=None):
|
|
|
116
124
|
if token_info.get("region"):
|
|
117
125
|
os.environ["AWS_DEFAULT_REGION"] = token_info["region"]
|
|
118
126
|
|
|
119
|
-
if
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
#
|
|
124
|
-
session = boto3.session.Session(profile_name="
|
|
127
|
+
if effective_role:
|
|
128
|
+
if role_arn == decorator_role_arn or role_arn == USE_CSPR_ROLE_ARN_IF_SET:
|
|
129
|
+
# We have either a decorator role or CSPR role, use the effective profile
|
|
130
|
+
# The generated AWS config will be used here since we set the
|
|
131
|
+
# AWS_CONFIG_FILE environment variable above.
|
|
132
|
+
session = boto3.session.Session(profile_name="effective")
|
|
125
133
|
else:
|
|
126
134
|
session = boto3.session.Session(profile_name="task")
|
|
127
135
|
else:
|
|
136
|
+
# No decorator role or CSPR role, use default session
|
|
128
137
|
# Not using AWS config, just AWS_WEB_IDENTITY_TOKEN_FILE + AWS_ROLE_ARN
|
|
129
138
|
session = boto3.session.Session()
|
|
130
139
|
|
|
131
|
-
if
|
|
132
|
-
|
|
133
|
-
|
|
140
|
+
if (
|
|
141
|
+
role_arn
|
|
142
|
+
and role_arn != USE_CSPR_ROLE_ARN_IF_SET
|
|
143
|
+
and role_arn != decorator_role_arn
|
|
144
|
+
):
|
|
145
|
+
# If the user provided a role_arn that's different from the decorator role,
|
|
146
|
+
# we assume that role using the current session credentials.
|
|
147
|
+
# This works for both cases:
|
|
148
|
+
# 1. No decorator role: Task role -> Secrets role
|
|
149
|
+
# 2. With decorator role: Decorator role -> Secrets role
|
|
134
150
|
fetcher = botocore.credentials.AssumeRoleCredentialFetcher(
|
|
135
151
|
client_creator=session._session.create_client,
|
|
136
152
|
source_credentials=session._session.get_credentials(),
|
|
@@ -146,8 +162,8 @@ def get_boto3_session(role_arn=None, session_vars=None):
|
|
|
146
162
|
else:
|
|
147
163
|
# If the user didn't provide a role_arn, or if the role_arn
|
|
148
164
|
# is set to USE_CSPR_ROLE_ARN_IF_SET, we return the default
|
|
149
|
-
# session which would use the
|
|
150
|
-
#
|
|
165
|
+
# session which would use the effective role (decorator or CSPR) if set,
|
|
166
|
+
# or the task role otherwise.
|
|
151
167
|
return session
|
|
152
168
|
|
|
153
169
|
|
ob_metaflow_extensions-1.1.165/metaflow_extensions/outerbounds/plugins/aws/assume_role_decorator.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from metaflow.user_configs.config_decorators import (
|
|
2
|
+
MutableFlow,
|
|
3
|
+
MutableStep,
|
|
4
|
+
CustomFlowDecorator,
|
|
5
|
+
)
|
|
6
|
+
from .assume_role import OBP_ASSUME_ROLE_ARN_ENV_VAR
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class assume_role(CustomFlowDecorator):
|
|
10
|
+
"""
|
|
11
|
+
Flow-level decorator for assuming AWS IAM roles.
|
|
12
|
+
|
|
13
|
+
When applied to a flow, all steps in the flow will automatically use the specified IAM role-arn
|
|
14
|
+
as their source principal.
|
|
15
|
+
|
|
16
|
+
Usage:
|
|
17
|
+
------
|
|
18
|
+
@assume_role(role_arn="arn:aws:iam::123456789012:role/my-iam-role")
|
|
19
|
+
class MyFlow(FlowSpec):
|
|
20
|
+
@step
|
|
21
|
+
def start(self):
|
|
22
|
+
import boto3
|
|
23
|
+
client = boto3.client("dynamodb") # Automatically uses the role in the flow decorator
|
|
24
|
+
self.next(self.end)
|
|
25
|
+
|
|
26
|
+
@step
|
|
27
|
+
def end(self):
|
|
28
|
+
from metaflow import get_aws_client
|
|
29
|
+
client = get_aws_client("dynamodb") # Automatically uses the role in the flow decorator
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def init(self, *args, **kwargs):
|
|
33
|
+
self.role_arn = kwargs.get("role_arn", None)
|
|
34
|
+
|
|
35
|
+
if self.role_arn is None:
|
|
36
|
+
raise ValueError(
|
|
37
|
+
"`role_arn` keyword argument is required for the assume_role decorator"
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
if not self.role_arn.startswith("arn:aws:iam::"):
|
|
41
|
+
raise ValueError(
|
|
42
|
+
"`role_arn` must be a valid AWS IAM role ARN starting with 'arn:aws:iam::'"
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
def evaluate(self, mutable_flow: MutableFlow) -> None:
|
|
46
|
+
"""
|
|
47
|
+
This method is called by Metaflow to apply the decorator to the flow.
|
|
48
|
+
It sets up environment variables that will be used by the AWS client
|
|
49
|
+
to automatically assume the specified role.
|
|
50
|
+
"""
|
|
51
|
+
# Import environment decorator at runtime to avoid circular imports
|
|
52
|
+
from metaflow import environment
|
|
53
|
+
|
|
54
|
+
# Set the role ARN as an environment variable that will be picked up
|
|
55
|
+
# by the get_aws_client function
|
|
56
|
+
def _setup_role_assumption(step: MutableStep) -> None:
|
|
57
|
+
# We'll inject the role assumption by adding an environment decorator
|
|
58
|
+
# The role will be available through an environment variable
|
|
59
|
+
step.add_decorator(
|
|
60
|
+
environment, vars={OBP_ASSUME_ROLE_ARN_ENV_VAR: self.role_arn}
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
# Apply the role assumption setup to all steps in the flow
|
|
64
|
+
for _, step in mutable_flow.steps:
|
|
65
|
+
_setup_role_assumption(step)
|
|
@@ -20,8 +20,19 @@ def get_aws_client(
|
|
|
20
20
|
module, with_error=False, role_arn=None, session_vars=None, client_params=None
|
|
21
21
|
):
|
|
22
22
|
import metaflow.plugins.aws.aws_client
|
|
23
|
+
import os
|
|
23
24
|
|
|
24
25
|
from metaflow_extensions.outerbounds.plugins import USE_CSPR_ROLE_ARN_IF_SET
|
|
26
|
+
from metaflow_extensions.outerbounds.plugins.aws.assume_role import (
|
|
27
|
+
OBP_ASSUME_ROLE_ARN_ENV_VAR,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
# Check if the assume_role decorator has set a role ARN via environment variable
|
|
31
|
+
# This takes precedence over CSPR but not over explicitly passed role_arn
|
|
32
|
+
if role_arn is None:
|
|
33
|
+
decorator_role_arn = os.environ.get(OBP_ASSUME_ROLE_ARN_ENV_VAR)
|
|
34
|
+
if decorator_role_arn:
|
|
35
|
+
role_arn = decorator_role_arn
|
|
25
36
|
|
|
26
37
|
return metaflow.plugins.aws.aws_client.get_aws_client(
|
|
27
38
|
module,
|
|
@@ -42,10 +53,20 @@ def get_aws_client(
|
|
|
42
53
|
def S3(*args, **kwargs):
|
|
43
54
|
import sys
|
|
44
55
|
import metaflow.plugins.datatools.s3
|
|
56
|
+
import os
|
|
45
57
|
from metaflow_extensions.outerbounds.plugins import USE_CSPR_ROLE_ARN_IF_SET
|
|
58
|
+
from metaflow_extensions.outerbounds.plugins.aws.assume_role import (
|
|
59
|
+
OBP_ASSUME_ROLE_ARN_ENV_VAR,
|
|
60
|
+
)
|
|
46
61
|
|
|
62
|
+
# Check if the assume_role decorator has set a role ARN via environment variable
|
|
63
|
+
# This takes precedence over CSPR but not over explicitly passed role
|
|
47
64
|
if "role" not in kwargs or kwargs["role"] is None:
|
|
48
|
-
|
|
65
|
+
decorator_role_arn = os.environ.get(OBP_ASSUME_ROLE_ARN_ENV_VAR)
|
|
66
|
+
if decorator_role_arn:
|
|
67
|
+
kwargs["role"] = decorator_role_arn
|
|
68
|
+
else:
|
|
69
|
+
kwargs["role"] = USE_CSPR_ROLE_ARN_IF_SET
|
|
49
70
|
|
|
50
71
|
return metaflow.plugins.datatools.s3.S3(*args, **kwargs)
|
|
51
72
|
|
|
@@ -53,4 +74,4 @@ def S3(*args, **kwargs):
|
|
|
53
74
|
from .. import profilers
|
|
54
75
|
from ..plugins.snowflake import Snowflake
|
|
55
76
|
from ..plugins.checkpoint_datastores import nebius_checkpoints, coreweave_checkpoints
|
|
56
|
-
from . import
|
|
77
|
+
from ..plugins.aws import assume_role
|
|
@@ -11,6 +11,9 @@ metaflow_extensions/outerbounds/plugins/apps/app_utils.py
|
|
|
11
11
|
metaflow_extensions/outerbounds/plugins/apps/consts.py
|
|
12
12
|
metaflow_extensions/outerbounds/plugins/apps/deploy_decorator.py
|
|
13
13
|
metaflow_extensions/outerbounds/plugins/apps/supervisord_utils.py
|
|
14
|
+
metaflow_extensions/outerbounds/plugins/aws/__init__.py
|
|
15
|
+
metaflow_extensions/outerbounds/plugins/aws/assume_role.py
|
|
16
|
+
metaflow_extensions/outerbounds/plugins/aws/assume_role_decorator.py
|
|
14
17
|
metaflow_extensions/outerbounds/plugins/card_utilities/__init__.py
|
|
15
18
|
metaflow_extensions/outerbounds/plugins/card_utilities/async_cards.py
|
|
16
19
|
metaflow_extensions/outerbounds/plugins/card_utilities/extra_components.py
|
|
@@ -19,7 +22,6 @@ metaflow_extensions/outerbounds/plugins/checkpoint_datastores/__init__.py
|
|
|
19
22
|
metaflow_extensions/outerbounds/plugins/checkpoint_datastores/coreweave.py
|
|
20
23
|
metaflow_extensions/outerbounds/plugins/checkpoint_datastores/nebius.py
|
|
21
24
|
metaflow_extensions/outerbounds/plugins/fast_bakery/__init__.py
|
|
22
|
-
metaflow_extensions/outerbounds/plugins/fast_bakery/baker.py
|
|
23
25
|
metaflow_extensions/outerbounds/plugins/fast_bakery/docker_environment.py
|
|
24
26
|
metaflow_extensions/outerbounds/plugins/fast_bakery/fast_bakery.py
|
|
25
27
|
metaflow_extensions/outerbounds/plugins/fast_bakery/fast_bakery_cli.py
|
|
@@ -71,7 +73,6 @@ metaflow_extensions/outerbounds/profilers/__init__.py
|
|
|
71
73
|
metaflow_extensions/outerbounds/profilers/gpu.py
|
|
72
74
|
metaflow_extensions/outerbounds/toplevel/__init__.py
|
|
73
75
|
metaflow_extensions/outerbounds/toplevel/global_aliases_for_metaflow_package.py
|
|
74
|
-
metaflow_extensions/outerbounds/toplevel/ob_internal.py
|
|
75
76
|
metaflow_extensions/outerbounds/toplevel/plugins/azure/__init__.py
|
|
76
77
|
metaflow_extensions/outerbounds/toplevel/plugins/gcp/__init__.py
|
|
77
78
|
metaflow_extensions/outerbounds/toplevel/plugins/kubernetes/__init__.py
|
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_namespace_packages
|
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
version = "1.1.
|
|
5
|
+
version = "1.1.165"
|
|
6
6
|
this_directory = Path(__file__).parent
|
|
7
7
|
long_description = (this_directory / "README.md").read_text()
|
|
8
8
|
|
|
@@ -18,6 +18,6 @@ setup(
|
|
|
18
18
|
install_requires=[
|
|
19
19
|
"boto3",
|
|
20
20
|
"kubernetes",
|
|
21
|
-
"ob-metaflow == 2.15.
|
|
21
|
+
"ob-metaflow == 2.15.17.1",
|
|
22
22
|
],
|
|
23
23
|
)
|
ob_metaflow_extensions-1.1.163rc7/metaflow_extensions/outerbounds/plugins/fast_bakery/baker.py
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import threading
|
|
2
|
-
import time
|
|
3
|
-
import sys
|
|
4
|
-
from typing import Dict, Optional, Any, Callable
|
|
5
|
-
from functools import partial
|
|
6
|
-
from metaflow.exception import MetaflowException
|
|
7
|
-
from metaflow.metaflow_config import FAST_BAKERY_URL
|
|
8
|
-
|
|
9
|
-
from .fast_bakery import FastBakery, FastBakeryApiResponse, FastBakeryException
|
|
10
|
-
from .docker_environment import cache_request
|
|
11
|
-
|
|
12
|
-
BAKERY_METAFILE = ".imagebakery-cache"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class BakerException(MetaflowException):
|
|
16
|
-
headline = "Ran into an error while baking image"
|
|
17
|
-
|
|
18
|
-
def __init__(self, msg):
|
|
19
|
-
super(BakerException, self).__init__(msg)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def bake_image(
|
|
23
|
-
cache_file_path: str,
|
|
24
|
-
ref: Optional[str] = None,
|
|
25
|
-
python: Optional[str] = None,
|
|
26
|
-
pypi_packages: Optional[Dict[str, str]] = None,
|
|
27
|
-
conda_packages: Optional[Dict[str, str]] = None,
|
|
28
|
-
base_image: Optional[str] = None,
|
|
29
|
-
logger: Optional[Callable[[str], Any]] = None,
|
|
30
|
-
) -> FastBakeryApiResponse:
|
|
31
|
-
"""
|
|
32
|
-
Bakes a Docker image with the specified dependencies.
|
|
33
|
-
|
|
34
|
-
Args:
|
|
35
|
-
cache_file_path: Path to the cache file
|
|
36
|
-
ref: Reference identifier for this bake (for logging purposes)
|
|
37
|
-
python: Python version to use
|
|
38
|
-
pypi_packages: Dictionary of PyPI packages and versions
|
|
39
|
-
conda_packages: Dictionary of Conda packages and versions
|
|
40
|
-
base_image: Base Docker image to use
|
|
41
|
-
logger: Optional logger function to output progress
|
|
42
|
-
|
|
43
|
-
Returns:
|
|
44
|
-
FastBakeryApiResponse: The response from the bakery service
|
|
45
|
-
|
|
46
|
-
Raises:
|
|
47
|
-
BakerException: If the baking process fails
|
|
48
|
-
"""
|
|
49
|
-
# Default logger if none provided
|
|
50
|
-
if logger is None:
|
|
51
|
-
logger = partial(print, file=sys.stderr)
|
|
52
|
-
|
|
53
|
-
# Thread lock for logging
|
|
54
|
-
logger_lock = threading.Lock()
|
|
55
|
-
images_baked = 0
|
|
56
|
-
|
|
57
|
-
@cache_request(cache_file_path)
|
|
58
|
-
def _cached_bake(
|
|
59
|
-
ref=None,
|
|
60
|
-
python=None,
|
|
61
|
-
pypi_packages=None,
|
|
62
|
-
conda_packages=None,
|
|
63
|
-
base_image=None,
|
|
64
|
-
):
|
|
65
|
-
try:
|
|
66
|
-
bakery = FastBakery(url=FAST_BAKERY_URL)
|
|
67
|
-
bakery._reset_payload()
|
|
68
|
-
bakery.python_version(python)
|
|
69
|
-
bakery.pypi_packages(pypi_packages)
|
|
70
|
-
bakery.conda_packages(conda_packages)
|
|
71
|
-
bakery.base_image(base_image)
|
|
72
|
-
# bakery.ignore_cache()
|
|
73
|
-
|
|
74
|
-
with logger_lock:
|
|
75
|
-
logger(f"🍳 Baking [{ref}] ...")
|
|
76
|
-
logger(f" 🐍 Python: {python}")
|
|
77
|
-
|
|
78
|
-
if pypi_packages:
|
|
79
|
-
logger(f" 📦 PyPI packages:")
|
|
80
|
-
for package, version in pypi_packages.items():
|
|
81
|
-
logger(f" 🔧 {package}: {version}")
|
|
82
|
-
|
|
83
|
-
if conda_packages:
|
|
84
|
-
logger(f" 📦 Conda packages:")
|
|
85
|
-
for package, version in conda_packages.items():
|
|
86
|
-
logger(f" 🔧 {package}: {version}")
|
|
87
|
-
|
|
88
|
-
logger(f" 🏗️ Base image: {base_image}")
|
|
89
|
-
|
|
90
|
-
start_time = time.time()
|
|
91
|
-
res = bakery.bake()
|
|
92
|
-
# TODO: Get actual bake time from bakery
|
|
93
|
-
bake_time = time.time() - start_time
|
|
94
|
-
|
|
95
|
-
with logger_lock:
|
|
96
|
-
logger(f"🏁 Baked [{ref}] in {bake_time:.2f} seconds!")
|
|
97
|
-
nonlocal images_baked
|
|
98
|
-
images_baked += 1
|
|
99
|
-
return res
|
|
100
|
-
except FastBakeryException as ex:
|
|
101
|
-
raise BakerException(f"Bake [{ref}] failed: {str(ex)}")
|
|
102
|
-
|
|
103
|
-
# Call the cached bake function with the provided parameters
|
|
104
|
-
return _cached_bake(
|
|
105
|
-
ref=ref,
|
|
106
|
-
python=python,
|
|
107
|
-
pypi_packages=pypi_packages,
|
|
108
|
-
conda_packages=conda_packages,
|
|
109
|
-
base_image=base_image,
|
|
110
|
-
)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from ..plugins.fast_bakery.baker import bake_image
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|