outerbounds 0.3.148__py3-none-any.whl → 0.3.149__py3-none-any.whl
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.
- outerbounds/command_groups/cli.py +9 -1
- outerbounds/command_groups/fast_bakery_cli.py +204 -0
- {outerbounds-0.3.148.dist-info → outerbounds-0.3.149.dist-info}/METADATA +1 -2
- {outerbounds-0.3.148.dist-info → outerbounds-0.3.149.dist-info}/RECORD +6 -5
- {outerbounds-0.3.148.dist-info → outerbounds-0.3.149.dist-info}/WHEEL +1 -1
- {outerbounds-0.3.148.dist-info → outerbounds-0.3.149.dist-info}/entry_points.txt +0 -0
@@ -1,5 +1,12 @@
|
|
1
1
|
from outerbounds._vendor import click
|
2
|
-
from . import
|
2
|
+
from . import (
|
3
|
+
local_setup_cli,
|
4
|
+
workstations_cli,
|
5
|
+
perimeters_cli,
|
6
|
+
apps_cli,
|
7
|
+
tutorials_cli,
|
8
|
+
fast_bakery_cli,
|
9
|
+
)
|
3
10
|
|
4
11
|
|
5
12
|
@click.command(
|
@@ -10,6 +17,7 @@ from . import local_setup_cli, workstations_cli, perimeters_cli, apps_cli, tutor
|
|
10
17
|
perimeters_cli.cli,
|
11
18
|
apps_cli.cli,
|
12
19
|
tutorials_cli.cli,
|
20
|
+
fast_bakery_cli.cli,
|
13
21
|
],
|
14
22
|
)
|
15
23
|
def cli(**kwargs):
|
@@ -0,0 +1,204 @@
|
|
1
|
+
import json
|
2
|
+
import base64
|
3
|
+
import boto3
|
4
|
+
import requests
|
5
|
+
|
6
|
+
from os import path, environ
|
7
|
+
from sys import exit
|
8
|
+
from outerbounds._vendor import click
|
9
|
+
|
10
|
+
from ..utils import metaflowconfig
|
11
|
+
|
12
|
+
|
13
|
+
@click.group()
|
14
|
+
def cli(**kwargs):
|
15
|
+
pass
|
16
|
+
|
17
|
+
|
18
|
+
@click.group(help="Commands for interacting with Fast Bakery.")
|
19
|
+
def fast_bakery(**kwargs):
|
20
|
+
pass
|
21
|
+
|
22
|
+
|
23
|
+
def get_aws_token(config_dir: str, profile: str):
|
24
|
+
metaflow_token = metaflowconfig.get_metaflow_token_from_config(config_dir, profile)
|
25
|
+
auth_url = metaflowconfig.get_sanitized_url_from_config(
|
26
|
+
config_dir, profile, "OBP_AUTH_SERVER"
|
27
|
+
)
|
28
|
+
|
29
|
+
aws_response = requests.get(
|
30
|
+
f"{auth_url}//generate/aws",
|
31
|
+
headers={"x-api-key": metaflow_token},
|
32
|
+
)
|
33
|
+
|
34
|
+
if aws_response.status_code != 200:
|
35
|
+
click.secho(
|
36
|
+
"Failed to retrieve AWS credentials. Fast-Bakery is currently only supported in AWS Deployments. Please reach out to your Outerbounds support team if you need additional assistance.",
|
37
|
+
fg="red",
|
38
|
+
err=True,
|
39
|
+
)
|
40
|
+
exit(1)
|
41
|
+
|
42
|
+
return aws_response.json()
|
43
|
+
|
44
|
+
|
45
|
+
def check_valid_registry_url(registry_url: str, config_dir: str, profile: str):
|
46
|
+
auth_url = metaflowconfig.get_sanitized_url_from_config(
|
47
|
+
config_dir, profile, "OBP_AUTH_SERVER"
|
48
|
+
)
|
49
|
+
|
50
|
+
# Extract the domain parts after the first section
|
51
|
+
registry_domain = registry_url.split(".", 1)[1] if "." in registry_url else ""
|
52
|
+
auth_domain = auth_url.split(".", 1)[1] if "." in auth_url else ""
|
53
|
+
|
54
|
+
if registry_url.startswith(("http://", "https://")):
|
55
|
+
click.secho(
|
56
|
+
f"Invalid Fast Bakery Registry URL: {registry_url}. URL should not start with http:// or https://",
|
57
|
+
fg="red",
|
58
|
+
err=True,
|
59
|
+
)
|
60
|
+
exit(1)
|
61
|
+
|
62
|
+
if not registry_domain:
|
63
|
+
click.secho(
|
64
|
+
f"Invalid Fast Bakery Registry URL: {registry_url}",
|
65
|
+
fg="red",
|
66
|
+
err=True,
|
67
|
+
)
|
68
|
+
exit(1)
|
69
|
+
|
70
|
+
if registry_domain != auth_domain:
|
71
|
+
click.secho(
|
72
|
+
f"Invalid Fast Bakery Domain: {registry_domain}",
|
73
|
+
fg="red",
|
74
|
+
err=True,
|
75
|
+
)
|
76
|
+
exit(1)
|
77
|
+
|
78
|
+
return True
|
79
|
+
|
80
|
+
|
81
|
+
def get_docker_auth_data(auth_token_response: dict):
|
82
|
+
role_arn = auth_token_response.get("role_arn")
|
83
|
+
token = auth_token_response.get("token")
|
84
|
+
region = auth_token_response.get("region")
|
85
|
+
|
86
|
+
sts_client = boto3.client("sts", region_name=region)
|
87
|
+
response = sts_client.assume_role_with_web_identity(
|
88
|
+
RoleArn=role_arn,
|
89
|
+
RoleSessionName="FastBakerySession",
|
90
|
+
WebIdentityToken=token,
|
91
|
+
DurationSeconds=3600,
|
92
|
+
)
|
93
|
+
credentials = response["Credentials"]
|
94
|
+
auth_data = {
|
95
|
+
"AccessKeyId": credentials["AccessKeyId"],
|
96
|
+
"SecretAccessKey": credentials["SecretAccessKey"],
|
97
|
+
"SessionToken": credentials["SessionToken"],
|
98
|
+
"Expiration": credentials["Expiration"].isoformat() + "Z",
|
99
|
+
"Version": 1,
|
100
|
+
}
|
101
|
+
return auth_data
|
102
|
+
|
103
|
+
|
104
|
+
@fast_bakery.command(
|
105
|
+
help="""
|
106
|
+
Get a docker login password for Fast Bakery. Example usage:
|
107
|
+
outerbounds fast-bakery get-login-password | docker login --username fastreg --password-stdin <fast-bakery-registry-url>
|
108
|
+
|
109
|
+
Note: The username must be set to 'fastreg'.
|
110
|
+
"""
|
111
|
+
)
|
112
|
+
@click.option(
|
113
|
+
"-d",
|
114
|
+
"--config-dir",
|
115
|
+
default=path.expanduser(environ.get("METAFLOW_HOME", "~/.metaflowconfig")),
|
116
|
+
help="Path to Metaflow configuration directory",
|
117
|
+
show_default=True,
|
118
|
+
)
|
119
|
+
@click.option(
|
120
|
+
"-p",
|
121
|
+
"--profile",
|
122
|
+
default=environ.get("METAFLOW_PROFILE", ""),
|
123
|
+
help="The named metaflow profile in which your workstation exists",
|
124
|
+
)
|
125
|
+
def get_login_password(config_dir=None, profile=None):
|
126
|
+
auth_token_response = get_aws_token(config_dir, profile)
|
127
|
+
auth_data = get_docker_auth_data(auth_token_response)
|
128
|
+
auth_base64 = base64.b64encode(json.dumps(auth_data).encode("utf-8")).decode(
|
129
|
+
"utf-8"
|
130
|
+
)
|
131
|
+
# Output the password
|
132
|
+
click.echo(auth_base64)
|
133
|
+
|
134
|
+
|
135
|
+
@fast_bakery.command(
|
136
|
+
help="""
|
137
|
+
Configure docker login credentials for Fast Bakery. Example usage:
|
138
|
+
outerbounds fast-bakery configure-docker-login
|
139
|
+
"""
|
140
|
+
)
|
141
|
+
@click.option(
|
142
|
+
"-d",
|
143
|
+
"--config-dir",
|
144
|
+
default=path.expanduser(environ.get("METAFLOW_HOME", "~/.metaflowconfig")),
|
145
|
+
help="Path to Metaflow configuration directory",
|
146
|
+
show_default=True,
|
147
|
+
)
|
148
|
+
@click.option(
|
149
|
+
"-p",
|
150
|
+
"--profile",
|
151
|
+
default=environ.get("METAFLOW_PROFILE", ""),
|
152
|
+
help="The named metaflow profile in which your workstation exists",
|
153
|
+
)
|
154
|
+
@click.option(
|
155
|
+
"--registry-url",
|
156
|
+
help="The fast-bakery registry url you would like to configured docker auth for",
|
157
|
+
)
|
158
|
+
@click.option(
|
159
|
+
"--output",
|
160
|
+
help="The output file you would like to save the docker config to. Defaults to $HOME/.docker/config.json",
|
161
|
+
)
|
162
|
+
def configure_docker_login(registry_url, output, config_dir=None, profile=None):
|
163
|
+
if registry_url is None:
|
164
|
+
click.secho(
|
165
|
+
"Missing a required argument: --registry-url <fast-bakery-registry-url>",
|
166
|
+
fg="red",
|
167
|
+
err=True,
|
168
|
+
)
|
169
|
+
return
|
170
|
+
|
171
|
+
check_valid_registry_url(registry_url, config_dir, profile)
|
172
|
+
auth_token_response = get_aws_token(config_dir, profile)
|
173
|
+
auth_data = get_docker_auth_data(auth_token_response)
|
174
|
+
auth_json = json.dumps(auth_data, separators=(",", ":"))
|
175
|
+
docker_config = {
|
176
|
+
registry_url: {
|
177
|
+
"auth": base64.b64encode(
|
178
|
+
f"fastreg:{base64.b64encode(auth_json.encode()).decode()}".encode()
|
179
|
+
).decode(),
|
180
|
+
"username": "fastreg", # This is currently hardcoded in the Fast Bakery Registry implementation.
|
181
|
+
"password": base64.b64encode(auth_json.encode()).decode(),
|
182
|
+
}
|
183
|
+
}
|
184
|
+
|
185
|
+
docker_config = {"auths": {}}
|
186
|
+
if output is None:
|
187
|
+
home = path.expanduser("~")
|
188
|
+
output = path.join(home, ".docker", "config.json")
|
189
|
+
|
190
|
+
if path.exists(output):
|
191
|
+
with open(output, "r") as f:
|
192
|
+
existing_docker_config = json.load(f)
|
193
|
+
|
194
|
+
if "auths" not in existing_docker_config:
|
195
|
+
existing_docker_config["auths"] = {}
|
196
|
+
|
197
|
+
existing_docker_config["auths"][registry_url] = docker_config
|
198
|
+
with open(output, "w") as f:
|
199
|
+
json.dump(docker_config, f, indent=4)
|
200
|
+
|
201
|
+
click.secho(f"Docker config saved to {output}", fg="green", err=True)
|
202
|
+
|
203
|
+
|
204
|
+
cli.add_command(fast_bakery, name="fast-bakery")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: outerbounds
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.149
|
4
4
|
Summary: More Data Science, Less Administration
|
5
5
|
License: Proprietary
|
6
6
|
Keywords: data science,machine learning,MLOps
|
@@ -14,7 +14,6 @@ Classifier: Programming Language :: Python :: 3.8
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.9
|
15
15
|
Classifier: Programming Language :: Python :: 3.10
|
16
16
|
Classifier: Programming Language :: Python :: 3.11
|
17
|
-
Classifier: Programming Language :: Python :: 3.12
|
18
17
|
Provides-Extra: azure
|
19
18
|
Provides-Extra: gcp
|
20
19
|
Provides-Extra: snowflake
|
@@ -42,7 +42,8 @@ outerbounds/_vendor/yaml/tokens.py,sha256=JBSu38wihGr4l73JwbfMA7Ks1-X84g8-NskTz7
|
|
42
42
|
outerbounds/cli_main.py,sha256=e9UMnPysmc7gbrimq2I4KfltggyU7pw59Cn9aEguVcU,74
|
43
43
|
outerbounds/command_groups/__init__.py,sha256=QPWtj5wDRTINDxVUL7XPqG3HoxHNvYOg08EnuSZB2Hc,21
|
44
44
|
outerbounds/command_groups/apps_cli.py,sha256=8jmQufa0bK2sfRfs7DiWjoJ1oWiqZAixsL4Dte_KY4Y,17201
|
45
|
-
outerbounds/command_groups/cli.py,sha256=
|
45
|
+
outerbounds/command_groups/cli.py,sha256=YsDS-AKhhwwSH65mgNsmjeg1U2bk202V5NpIYnXEdb8,440
|
46
|
+
outerbounds/command_groups/fast_bakery_cli.py,sha256=aIFRuJo9v9Wfh0meXVe01OCYc9Pnmwr0oMMZ_VcBtBo,6243
|
46
47
|
outerbounds/command_groups/local_setup_cli.py,sha256=tuuqJRXQ_guEwOuQSIf9wkUU0yg8yAs31myGViAK15s,36364
|
47
48
|
outerbounds/command_groups/perimeters_cli.py,sha256=iF_Uw7ROiSctf6FgoJEy30iDBLVE1j9FKuR3shgJRmc,19050
|
48
49
|
outerbounds/command_groups/tutorials_cli.py,sha256=UInFyiMqtscHFfi8YQwiY_6Sdw9quJOtRu5OukEBccw,3522
|
@@ -53,7 +54,7 @@ outerbounds/utils/metaflowconfig.py,sha256=l2vJbgPkLISU-XPGZFaC8ZKmYFyJemlD6bwB-
|
|
53
54
|
outerbounds/utils/schema.py,sha256=lMUr9kNgn9wy-sO_t_Tlxmbt63yLeN4b0xQXbDUDj4A,2331
|
54
55
|
outerbounds/utils/utils.py,sha256=4Z8cszNob_8kDYCLNTrP-wWads_S_MdL3Uj3ju4mEsk,501
|
55
56
|
outerbounds/vendor.py,sha256=gRLRJNXtZBeUpPEog0LOeIsl6GosaFFbCxUvR4bW6IQ,5093
|
56
|
-
outerbounds-0.3.
|
57
|
-
outerbounds-0.3.
|
58
|
-
outerbounds-0.3.
|
59
|
-
outerbounds-0.3.
|
57
|
+
outerbounds-0.3.149.dist-info/WHEEL,sha256=vVCvjcmxuUltf8cYhJ0sJMRDLr1XsPuxEId8YDzbyCY,88
|
58
|
+
outerbounds-0.3.149.dist-info/entry_points.txt,sha256=7ye0281PKlvqxu15rjw60zKg2pMsXI49_A8BmGqIqBw,47
|
59
|
+
outerbounds-0.3.149.dist-info/METADATA,sha256=8Eg_ZpUpJHRbQwk7L28tcEKqJFUBFYVYuaR3NewW6vE,1710
|
60
|
+
outerbounds-0.3.149.dist-info/RECORD,,
|
File without changes
|