ob-metaflow-extensions 1.1.162__tar.gz → 1.1.163__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.

Files changed (88) hide show
  1. {ob-metaflow-extensions-1.1.162/ob_metaflow_extensions.egg-info → ob_metaflow_extensions-1.1.163}/PKG-INFO +2 -2
  2. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/__init__.py +27 -18
  3. ob_metaflow_extensions-1.1.163/metaflow_extensions/outerbounds/plugins/aws/__init__.py +4 -0
  4. ob_metaflow_extensions-1.1.163/metaflow_extensions/outerbounds/plugins/aws/assume_role.py +3 -0
  5. ob_metaflow_extensions-1.1.163/metaflow_extensions/outerbounds/plugins/aws/assume_role_decorator.py +65 -0
  6. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/toplevel/global_aliases_for_metaflow_package.py +23 -1
  7. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163/ob_metaflow_extensions.egg-info}/PKG-INFO +1 -1
  8. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/ob_metaflow_extensions.egg-info/SOURCES.txt +3 -0
  9. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/setup.py +2 -2
  10. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/README.md +0 -0
  11. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/__init__.py +0 -0
  12. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/config/__init__.py +0 -0
  13. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/apps/__init__.py +0 -0
  14. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/apps/app_utils.py +0 -0
  15. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/apps/consts.py +0 -0
  16. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/apps/deploy_decorator.py +0 -0
  17. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/apps/supervisord_utils.py +0 -0
  18. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/auth_server.py +0 -0
  19. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/card_utilities/__init__.py +0 -0
  20. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/card_utilities/async_cards.py +0 -0
  21. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/card_utilities/extra_components.py +0 -0
  22. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/card_utilities/injector.py +0 -0
  23. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/__init__.py +0 -0
  24. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/coreweave.py +0 -0
  25. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/nebius.py +0 -0
  26. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/fast_bakery/__init__.py +0 -0
  27. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/fast_bakery/docker_environment.py +0 -0
  28. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/fast_bakery/fast_bakery.py +0 -0
  29. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/fast_bakery/fast_bakery_cli.py +0 -0
  30. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/fast_bakery/fast_bakery_decorator.py +0 -0
  31. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/kubernetes/__init__.py +0 -0
  32. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/kubernetes/kubernetes_client.py +0 -0
  33. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/kubernetes/pod_killer.py +0 -0
  34. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/nim/card.py +0 -0
  35. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/nim/nim_decorator.py +0 -0
  36. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/nim/nim_manager.py +0 -0
  37. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/nim/utils.py +0 -0
  38. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/nvcf/__init__.py +0 -0
  39. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/nvcf/constants.py +0 -0
  40. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/nvcf/exceptions.py +0 -0
  41. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/nvcf/heartbeat_store.py +0 -0
  42. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/nvcf/nvcf.py +0 -0
  43. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/nvcf/nvcf_cli.py +0 -0
  44. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/nvcf/nvcf_decorator.py +0 -0
  45. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/nvcf/utils.py +0 -0
  46. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/nvct/__init__.py +0 -0
  47. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/nvct/exceptions.py +0 -0
  48. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/nvct/nvct.py +0 -0
  49. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/nvct/nvct_cli.py +0 -0
  50. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/nvct/nvct_decorator.py +0 -0
  51. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/nvct/nvct_runner.py +0 -0
  52. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/nvct/utils.py +0 -0
  53. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/ollama/__init__.py +0 -0
  54. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/ollama/constants.py +0 -0
  55. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/ollama/exceptions.py +0 -0
  56. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/ollama/ollama.py +0 -0
  57. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/ollama/status_card.py +0 -0
  58. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/perimeters.py +0 -0
  59. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/profilers/deco_injector.py +0 -0
  60. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/profilers/gpu_profile_decorator.py +0 -0
  61. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/secrets/__init__.py +0 -0
  62. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/secrets/secrets.py +0 -0
  63. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/snowflake/__init__.py +0 -0
  64. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/snowflake/snowflake.py +0 -0
  65. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/snowpark/__init__.py +0 -0
  66. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark.py +0 -0
  67. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_cli.py +0 -0
  68. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_client.py +0 -0
  69. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_decorator.py +0 -0
  70. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_exceptions.py +0 -0
  71. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_job.py +0 -0
  72. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_service_spec.py +0 -0
  73. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/tensorboard/__init__.py +0 -0
  74. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/plugins/torchtune/__init__.py +0 -0
  75. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/profilers/__init__.py +0 -0
  76. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/profilers/gpu.py +0 -0
  77. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/remote_config.py +0 -0
  78. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/toplevel/__init__.py +0 -0
  79. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/toplevel/plugins/azure/__init__.py +0 -0
  80. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/toplevel/plugins/gcp/__init__.py +0 -0
  81. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/toplevel/plugins/kubernetes/__init__.py +0 -0
  82. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/toplevel/plugins/ollama/__init__.py +0 -0
  83. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/toplevel/plugins/snowflake/__init__.py +0 -0
  84. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/metaflow_extensions/outerbounds/toplevel/plugins/torchtune/__init__.py +0 -0
  85. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/ob_metaflow_extensions.egg-info/dependency_links.txt +0 -0
  86. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/ob_metaflow_extensions.egg-info/requires.txt +0 -0
  87. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/ob_metaflow_extensions.egg-info/top_level.txt +0 -0
  88. {ob-metaflow-extensions-1.1.162 → ob_metaflow_extensions-1.1.163}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
- Name: ob-metaflow-extensions
3
- Version: 1.1.162
2
+ Name: ob_metaflow_extensions
3
+ Version: 1.1.163
4
4
  Summary: Outerbounds Platform Extensions for Metaflow
5
5
  Author: Outerbounds, Inc.
6
6
  License: Commercial
@@ -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
- if cspr_role:
73
- # If CSPR role is set, we set it as the default role to assume
74
- # for the AWS SDK. We do this by writing an AWS config file
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
- # CSPR role using the task role credentials.
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
- # CSPR role profile (default)
90
- aws_config["profile cspr"] = {
91
- "role_arn": cspr_role,
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"] = "cspr"
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,22 @@ 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 cspr_role:
120
- # The generated AWS config will be used here since we set the
121
- # AWS_CONFIG_FILE environment variable above.
122
- if role_arn == USE_CSPR_ROLE_ARN_IF_SET:
123
- # Otherwise start from the default profile, assuming CSPR role
124
- session = boto3.session.Session(profile_name="cspr")
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 role_arn and role_arn != USE_CSPR_ROLE_ARN_IF_SET:
140
+ if role_arn and role_arn != USE_CSPR_ROLE_ARN_IF_SET and decorator_role_arn != None:
132
141
  # If the user provided a role_arn, we assume that role
133
- # using the task role credentials. CSPR role is not used.
142
+ # using the task role credentials. This overrides everything else.
134
143
  fetcher = botocore.credentials.AssumeRoleCredentialFetcher(
135
144
  client_creator=session._session.create_client,
136
145
  source_credentials=session._session.get_credentials(),
@@ -146,8 +155,8 @@ def get_boto3_session(role_arn=None, session_vars=None):
146
155
  else:
147
156
  # If the user didn't provide a role_arn, or if the role_arn
148
157
  # is set to USE_CSPR_ROLE_ARN_IF_SET, we return the default
149
- # session which would use the CSPR role if it is set on the
150
- # server, and the task role otherwise.
158
+ # session which would use the effective role (decorator or CSPR) if set,
159
+ # or the task role otherwise.
151
160
  return session
152
161
 
153
162
 
@@ -0,0 +1,4 @@
1
+ from .assume_role_decorator import assume_role
2
+ from .assume_role import OBP_ASSUME_ROLE_ARN_ENV_VAR
3
+
4
+ __mf_promote_submodules__ = ["plugins.aws"]
@@ -0,0 +1,3 @@
1
+ # Environment variable name used by the assume_role decorator to pass
2
+ # the role ARN to AWS client functions
3
+ OBP_ASSUME_ROLE_ARN_ENV_VAR = "OBP_ASSUME_ROLE_ARN"
@@ -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
- kwargs["role"] = USE_CSPR_ROLE_ARN_IF_SET
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,3 +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
77
+ from ..plugins.aws import assume_role
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ob-metaflow-extensions
3
- Version: 1.1.162
3
+ Version: 1.1.163
4
4
  Summary: Outerbounds Platform Extensions for Metaflow
5
5
  Author: Outerbounds, Inc.
6
6
  License: Commercial
@@ -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
@@ -2,12 +2,12 @@ from setuptools import setup, find_namespace_packages
2
2
  from pathlib import Path
3
3
 
4
4
 
5
- version = "1.1.162"
5
+ version = "1.1.163"
6
6
  this_directory = Path(__file__).parent
7
7
  long_description = (this_directory / "README.md").read_text()
8
8
 
9
9
  setup(
10
- name="ob-metaflow-extensions",
10
+ name="ob_metaflow_extensions",
11
11
  version=version,
12
12
  description="Outerbounds Platform Extensions for Metaflow",
13
13
  author="Outerbounds, Inc.",