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.
@@ -1,5 +1,12 @@
1
1
  from outerbounds._vendor import click
2
- from . import local_setup_cli, workstations_cli, perimeters_cli, apps_cli, tutorials_cli
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.148
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=q0hdJO4biD3iEOdyJcxnRkeleA8AKAhx842kQ49I6kk,365
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.148.dist-info/METADATA,sha256=B-WOn49R1PJVU8kMR-4RhVcrN8KEEUwdnAFQ80S5iCw,1761
57
- outerbounds-0.3.148.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
58
- outerbounds-0.3.148.dist-info/entry_points.txt,sha256=7ye0281PKlvqxu15rjw60zKg2pMsXI49_A8BmGqIqBw,47
59
- outerbounds-0.3.148.dist-info/RECORD,,
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,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.0
2
+ Generator: poetry-core 1.4.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any