outerbounds 0.3.109rc1__py3-none-any.whl → 0.3.111__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- outerbounds/command_groups/apps_cli.py +92 -228
- {outerbounds-0.3.109rc1.dist-info → outerbounds-0.3.111.dist-info}/METADATA +5 -5
- {outerbounds-0.3.109rc1.dist-info → outerbounds-0.3.111.dist-info}/RECORD +5 -5
- {outerbounds-0.3.109rc1.dist-info → outerbounds-0.3.111.dist-info}/WHEEL +0 -0
- {outerbounds-0.3.109rc1.dist-info → outerbounds-0.3.111.dist-info}/entry_points.txt +0 -0
@@ -1,15 +1,16 @@
|
|
1
|
-
import json
|
2
1
|
import os
|
3
2
|
from os import path
|
4
3
|
from outerbounds._vendor import click
|
5
4
|
import requests
|
5
|
+
import time
|
6
|
+
import random
|
6
7
|
|
7
8
|
from ..utils import metaflowconfig
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
|
10
|
+
APP_READY_POLL_TIMEOUT_SECONDS = 300
|
11
|
+
# Even after our backend validates that the app routes are ready, it takes a few seconds for
|
12
|
+
# the app to be accessible via the browser. Till we hunt down this delay, add an extra buffer.
|
13
|
+
APP_READY_EXTRA_BUFFER_SECONDS = 30
|
13
14
|
|
14
15
|
|
15
16
|
@click.group()
|
@@ -48,14 +49,7 @@ def app(**kwargs):
|
|
48
49
|
help="Name of your app",
|
49
50
|
type=str,
|
50
51
|
)
|
51
|
-
|
52
|
-
"-o",
|
53
|
-
"--output",
|
54
|
-
default="",
|
55
|
-
help="Show output in the specified format.",
|
56
|
-
type=click.Choice(["json", ""]),
|
57
|
-
)
|
58
|
-
def start(config_dir=None, profile=None, port=-1, name="", output=""):
|
52
|
+
def start(config_dir=None, profile=None, port=-1, name=""):
|
59
53
|
if len(name) == 0 or len(name) >= 20:
|
60
54
|
click.secho(
|
61
55
|
"App name should not be more than 20 characters long.",
|
@@ -71,49 +65,16 @@ def start(config_dir=None, profile=None, port=-1, name="", output=""):
|
|
71
65
|
)
|
72
66
|
return
|
73
67
|
|
74
|
-
start_app_response = OuterboundsCommandResponse()
|
75
|
-
|
76
|
-
validate_workstation_step = CommandStatus(
|
77
|
-
"ValidateRunningOnWorkstation",
|
78
|
-
OuterboundsCommandStatus.OK,
|
79
|
-
"Command is being run on a workstation.",
|
80
|
-
)
|
81
|
-
|
82
|
-
list_workstations_step = CommandStatus(
|
83
|
-
"ListWorkstations",
|
84
|
-
OuterboundsCommandStatus.OK,
|
85
|
-
"List of workstations fetched.",
|
86
|
-
)
|
87
|
-
|
88
|
-
validate_request = CommandStatus(
|
89
|
-
"ValidateRequest",
|
90
|
-
OuterboundsCommandStatus.OK,
|
91
|
-
"Start app request is valid.",
|
92
|
-
)
|
93
|
-
|
94
|
-
start_app_step = CommandStatus(
|
95
|
-
"StartApp",
|
96
|
-
OuterboundsCommandStatus.OK,
|
97
|
-
f"App {name} started on port {port}!",
|
98
|
-
)
|
99
|
-
|
100
68
|
if "WORKSTATION_ID" not in os.environ:
|
101
|
-
validate_workstation_step.update(
|
102
|
-
OuterboundsCommandStatus.FAIL,
|
103
|
-
"All outerbounds app commands can only be run from a workstation.",
|
104
|
-
"",
|
105
|
-
)
|
106
|
-
start_app_response.add_step(validate_workstation_step)
|
107
69
|
click.secho(
|
108
70
|
"All outerbounds app commands can only be run from a workstation.",
|
109
71
|
fg="red",
|
110
72
|
err=True,
|
111
73
|
)
|
112
|
-
|
113
|
-
if output == "json":
|
114
|
-
click.echo(json.dumps(start_app_response.as_dict(), indent=4))
|
115
74
|
return
|
116
75
|
|
76
|
+
workstation_id = os.environ["WORKSTATION_ID"]
|
77
|
+
|
117
78
|
try:
|
118
79
|
try:
|
119
80
|
metaflow_token = metaflowconfig.get_metaflow_token_from_config(
|
@@ -127,15 +88,8 @@ def start(config_dir=None, profile=None, port=-1, name="", output=""):
|
|
127
88
|
f"{api_url}/v1/workstations", headers={"x-api-key": metaflow_token}
|
128
89
|
)
|
129
90
|
workstations_response.raise_for_status()
|
130
|
-
start_app_response.add_step(list_workstations_step)
|
131
91
|
except:
|
132
92
|
click.secho("Failed to list workstations!", fg="red", err=True)
|
133
|
-
list_workstations_step.update(
|
134
|
-
OuterboundsCommandStatus.FAIL, "Failed to list workstations!", ""
|
135
|
-
)
|
136
|
-
start_app_response.add_step(list_workstations_step)
|
137
|
-
if output == "json":
|
138
|
-
click.echo(json.dumps(start_app_response.as_dict(), indent=4))
|
139
93
|
return
|
140
94
|
|
141
95
|
workstations_json = workstations_response.json()["workstations"]
|
@@ -148,20 +102,8 @@ def start(config_dir=None, profile=None, port=-1, name="", output=""):
|
|
148
102
|
)
|
149
103
|
except ValueError as e:
|
150
104
|
click.secho(str(e), fg="red", err=True)
|
151
|
-
validate_request.update(
|
152
|
-
OuterboundsCommandStatus.FAIL,
|
153
|
-
str(e),
|
154
|
-
"",
|
155
|
-
)
|
156
|
-
start_app_response.add_step(validate_request)
|
157
|
-
if output == "json":
|
158
|
-
click.echo(
|
159
|
-
json.dumps(start_app_response.as_dict(), indent=4)
|
160
|
-
)
|
161
105
|
return
|
162
106
|
|
163
|
-
start_app_response.add_step(validate_request)
|
164
|
-
|
165
107
|
for named_port in workstation["spec"]["named_ports"]:
|
166
108
|
if int(named_port["port"]) == port:
|
167
109
|
if named_port["enabled"] and named_port["name"] == name:
|
@@ -171,22 +113,15 @@ def start(config_dir=None, profile=None, port=-1, name="", output=""):
|
|
171
113
|
err=True,
|
172
114
|
)
|
173
115
|
click.secho(
|
174
|
-
f"App URL: {api_url.replace('api', 'ui')}/apps/{
|
116
|
+
f"App URL: {api_url.replace('api', 'ui')}/apps/{workstation_id}/{name}/",
|
175
117
|
fg="green",
|
176
118
|
err=True,
|
177
119
|
)
|
178
|
-
start_app_response.add_step(start_app_step)
|
179
|
-
if output == "json":
|
180
|
-
click.echo(
|
181
|
-
json.dumps(
|
182
|
-
start_app_response.as_dict(), indent=4
|
183
|
-
)
|
184
|
-
)
|
185
120
|
return
|
186
121
|
else:
|
187
122
|
try:
|
188
123
|
response = requests.put(
|
189
|
-
f"{api_url}/v1/workstations/update/{
|
124
|
+
f"{api_url}/v1/workstations/update/{workstation_id}/namedports",
|
190
125
|
headers={"x-api-key": metaflow_token},
|
191
126
|
json={
|
192
127
|
"port": port,
|
@@ -196,46 +131,40 @@ def start(config_dir=None, profile=None, port=-1, name="", output=""):
|
|
196
131
|
)
|
197
132
|
|
198
133
|
response.raise_for_status()
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
f"App URL: {api_url.replace('api', 'ui')}/apps/{os.environ['WORKSTATION_ID']}/{name}/",
|
206
|
-
fg="green",
|
207
|
-
err=True,
|
134
|
+
poll_success = wait_for_app_port_to_be_accessible(
|
135
|
+
api_url,
|
136
|
+
metaflow_token,
|
137
|
+
workstation_id,
|
138
|
+
name,
|
139
|
+
APP_READY_POLL_TIMEOUT_SECONDS,
|
208
140
|
)
|
141
|
+
if poll_success:
|
142
|
+
click.secho(
|
143
|
+
f"App {name} started on port {port}!",
|
144
|
+
fg="green",
|
145
|
+
err=True,
|
146
|
+
)
|
147
|
+
click.secho(
|
148
|
+
f"App URL: {api_url.replace('api', 'ui')}/apps/{os.environ['WORKSTATION_ID']}/{name}/",
|
149
|
+
fg="green",
|
150
|
+
err=True,
|
151
|
+
)
|
152
|
+
else:
|
153
|
+
click.secho(
|
154
|
+
f"The app could not be deployed in {APP_READY_POLL_TIMEOUT_SECONDS / 60} minutes. Please try again later.",
|
155
|
+
fg="red",
|
156
|
+
err=True,
|
157
|
+
)
|
158
|
+
return
|
209
159
|
except Exception:
|
210
160
|
click.secho(
|
211
161
|
f"Failed to start app {name} on port {port}!",
|
212
162
|
fg="red",
|
213
163
|
err=True,
|
214
164
|
)
|
215
|
-
start_app_step.update(
|
216
|
-
OuterboundsCommandStatus.FAIL,
|
217
|
-
f"Failed to start app {name} on port {port}!",
|
218
|
-
"",
|
219
|
-
)
|
220
|
-
|
221
|
-
start_app_response.add_step(start_app_step)
|
222
|
-
if output == "json":
|
223
|
-
click.echo(
|
224
|
-
json.dumps(
|
225
|
-
start_app_response.as_dict(), indent=4
|
226
|
-
)
|
227
|
-
)
|
228
165
|
return
|
229
166
|
except Exception as e:
|
230
167
|
click.secho(f"Failed to start app {name} on port {port}!", fg="red", err=True)
|
231
|
-
start_app_step.update(
|
232
|
-
OuterboundsCommandStatus.FAIL,
|
233
|
-
f"Failed to start app {name} on port {port}!",
|
234
|
-
"",
|
235
|
-
)
|
236
|
-
start_app_response.add_step(start_app_step)
|
237
|
-
if output == "json":
|
238
|
-
click.secho(json.dumps(start_app_response.as_dict(), indent=4))
|
239
168
|
|
240
169
|
|
241
170
|
@app.command(help="Stop an app using its port number")
|
@@ -266,14 +195,7 @@ def start(config_dir=None, profile=None, port=-1, name="", output=""):
|
|
266
195
|
default="",
|
267
196
|
type=str,
|
268
197
|
)
|
269
|
-
|
270
|
-
"-o",
|
271
|
-
"--output",
|
272
|
-
default="",
|
273
|
-
help="Show output in the specified format.",
|
274
|
-
type=click.Choice(["json", ""]),
|
275
|
-
)
|
276
|
-
def stop(config_dir=None, profile=None, port=-1, name="", output=""):
|
198
|
+
def stop(config_dir=None, profile=None, port=-1, name=""):
|
277
199
|
if port == -1 and not name:
|
278
200
|
click.secho(
|
279
201
|
"Please provide either a port number or a name to stop the app.",
|
@@ -289,47 +211,13 @@ def stop(config_dir=None, profile=None, port=-1, name="", output=""):
|
|
289
211
|
)
|
290
212
|
return
|
291
213
|
|
292
|
-
stop_app_response = OuterboundsCommandResponse()
|
293
|
-
|
294
|
-
validate_workstation_step = CommandStatus(
|
295
|
-
"ValidateRunningOnWorkstation",
|
296
|
-
OuterboundsCommandStatus.OK,
|
297
|
-
"Command is being run on a workstation.",
|
298
|
-
)
|
299
|
-
|
300
|
-
list_workstations_step = CommandStatus(
|
301
|
-
"ListWorkstations",
|
302
|
-
OuterboundsCommandStatus.OK,
|
303
|
-
"List of workstations fetched.",
|
304
|
-
)
|
305
|
-
|
306
|
-
validate_port_exists = CommandStatus(
|
307
|
-
"ValidatePortExists",
|
308
|
-
OuterboundsCommandStatus.OK,
|
309
|
-
"Port exists on workstation",
|
310
|
-
)
|
311
|
-
|
312
|
-
stop_app_step = CommandStatus(
|
313
|
-
"StopApp",
|
314
|
-
OuterboundsCommandStatus.OK,
|
315
|
-
f"App stopped on port {port}!",
|
316
|
-
)
|
317
|
-
|
318
214
|
if "WORKSTATION_ID" not in os.environ:
|
319
|
-
validate_workstation_step.update(
|
320
|
-
OuterboundsCommandStatus.FAIL,
|
321
|
-
"All outerbounds app commands can only be run from a workstation.",
|
322
|
-
"",
|
323
|
-
)
|
324
|
-
stop_app_response.add_step(validate_workstation_step)
|
325
215
|
click.secho(
|
326
216
|
"All outerbounds app commands can only be run from a workstation.",
|
327
217
|
fg="red",
|
328
218
|
err=True,
|
329
219
|
)
|
330
220
|
|
331
|
-
if output == "json":
|
332
|
-
click.echo(json.dumps(stop_app_response.as_dict(), indent=4))
|
333
221
|
return
|
334
222
|
|
335
223
|
try:
|
@@ -345,15 +233,8 @@ def stop(config_dir=None, profile=None, port=-1, name="", output=""):
|
|
345
233
|
f"{api_url}/v1/workstations", headers={"x-api-key": metaflow_token}
|
346
234
|
)
|
347
235
|
workstations_response.raise_for_status()
|
348
|
-
stop_app_response.add_step(list_workstations_step)
|
349
236
|
except:
|
350
237
|
click.secho("Failed to list workstations!", fg="red", err=True)
|
351
|
-
list_workstations_step.update(
|
352
|
-
OuterboundsCommandStatus.FAIL, "Failed to list workstations!", ""
|
353
|
-
)
|
354
|
-
stop_app_response.add_step(list_workstations_step)
|
355
|
-
if output == "json":
|
356
|
-
click.echo(json.dumps(stop_app_response.as_dict(), indent=4))
|
357
238
|
return
|
358
239
|
|
359
240
|
app_found = False
|
@@ -367,7 +248,6 @@ def stop(config_dir=None, profile=None, port=-1, name="", output=""):
|
|
367
248
|
or named_port["name"] == name
|
368
249
|
):
|
369
250
|
app_found = True
|
370
|
-
stop_app_response.add_step(validate_port_exists)
|
371
251
|
if named_port["enabled"]:
|
372
252
|
try:
|
373
253
|
response = requests.put(
|
@@ -391,19 +271,6 @@ def stop(config_dir=None, profile=None, port=-1, name="", output=""):
|
|
391
271
|
fg="red",
|
392
272
|
err=True,
|
393
273
|
)
|
394
|
-
stop_app_step.update(
|
395
|
-
OuterboundsCommandStatus.FAIL,
|
396
|
-
f"Failed to stop app {named_port['name']} on port {named_port['port']}!",
|
397
|
-
"",
|
398
|
-
)
|
399
|
-
|
400
|
-
stop_app_response.add_step(stop_app_step)
|
401
|
-
if output == "json":
|
402
|
-
click.echo(
|
403
|
-
json.dumps(
|
404
|
-
stop_app_response.as_dict(), indent=4
|
405
|
-
)
|
406
|
-
)
|
407
274
|
return
|
408
275
|
|
409
276
|
if app_found:
|
@@ -417,9 +284,6 @@ def stop(config_dir=None, profile=None, port=-1, name="", output=""):
|
|
417
284
|
fg="green",
|
418
285
|
err=True,
|
419
286
|
)
|
420
|
-
stop_app_response.add_step(stop_app_step)
|
421
|
-
if output == "json":
|
422
|
-
click.echo(json.dumps(stop_app_response.as_dict(), indent=4))
|
423
287
|
return
|
424
288
|
|
425
289
|
err_message = (
|
@@ -433,26 +297,11 @@ def stop(config_dir=None, profile=None, port=-1, name="", output=""):
|
|
433
297
|
fg="red",
|
434
298
|
err=True,
|
435
299
|
)
|
436
|
-
|
437
|
-
validate_port_exists.update(
|
438
|
-
OuterboundsCommandStatus.FAIL,
|
439
|
-
err_message,
|
440
|
-
"",
|
441
|
-
)
|
442
|
-
stop_app_response.add_step(validate_port_exists)
|
443
|
-
if output == "json":
|
444
|
-
click.echo(json.dumps(stop_app_response.as_dict(), indent=4))
|
445
300
|
except Exception as e:
|
446
301
|
click.secho(f"Failed to stop app on port {port}!", fg="red", err=True)
|
447
|
-
stop_app_step.update(
|
448
|
-
OuterboundsCommandStatus.FAIL, f"Failed to stop on port {port}!", ""
|
449
|
-
)
|
450
|
-
stop_app_response.add_step(stop_app_step)
|
451
|
-
if output == "json":
|
452
|
-
click.echo(json.dumps(stop_app_response.as_dict(), indent=4))
|
453
302
|
|
454
303
|
|
455
|
-
@app.command(help="
|
304
|
+
@app.command(help="List all apps on the workstation")
|
456
305
|
@click.option(
|
457
306
|
"-d",
|
458
307
|
"--config-dir",
|
@@ -466,43 +315,14 @@ def stop(config_dir=None, profile=None, port=-1, name="", output=""):
|
|
466
315
|
default=os.environ.get("METAFLOW_PROFILE", ""),
|
467
316
|
help="The named metaflow profile in which your workstation exists",
|
468
317
|
)
|
469
|
-
|
470
|
-
"-o",
|
471
|
-
"--output",
|
472
|
-
default="",
|
473
|
-
help="Show output in the specified format.",
|
474
|
-
type=click.Choice(["json", ""]),
|
475
|
-
)
|
476
|
-
def list(config_dir=None, profile=None, output=""):
|
477
|
-
list_app_response = OuterboundsCommandResponse()
|
478
|
-
|
479
|
-
validate_workstation_step = CommandStatus(
|
480
|
-
"ValidateRunningOnWorkstation",
|
481
|
-
OuterboundsCommandStatus.OK,
|
482
|
-
"Command is being run on a workstation.",
|
483
|
-
)
|
484
|
-
|
485
|
-
list_workstations_step = CommandStatus(
|
486
|
-
"ListWorkstations",
|
487
|
-
OuterboundsCommandStatus.OK,
|
488
|
-
"List of workstations fetched.",
|
489
|
-
)
|
490
|
-
|
318
|
+
def list(config_dir=None, profile=None):
|
491
319
|
if "WORKSTATION_ID" not in os.environ:
|
492
|
-
validate_workstation_step.update(
|
493
|
-
OuterboundsCommandStatus.FAIL,
|
494
|
-
"All outerbounds app commands can only be run from a workstation.",
|
495
|
-
"",
|
496
|
-
)
|
497
|
-
list_app_response.add_step(validate_workstation_step)
|
498
320
|
click.secho(
|
499
321
|
"All outerbounds app commands can only be run from a workstation.",
|
500
322
|
fg="red",
|
501
323
|
err=True,
|
502
324
|
)
|
503
325
|
|
504
|
-
if output == "json":
|
505
|
-
click.echo(json.dumps(list_app_response.as_dict(), indent=4))
|
506
326
|
return
|
507
327
|
|
508
328
|
try:
|
@@ -518,15 +338,8 @@ def list(config_dir=None, profile=None, output=""):
|
|
518
338
|
f"{api_url}/v1/workstations", headers={"x-api-key": metaflow_token}
|
519
339
|
)
|
520
340
|
workstations_response.raise_for_status()
|
521
|
-
list_app_response.add_step(list_workstations_step)
|
522
341
|
except:
|
523
342
|
click.secho("Failed to list workstations!", fg="red", err=True)
|
524
|
-
list_workstations_step.update(
|
525
|
-
OuterboundsCommandStatus.FAIL, "Failed to list workstations!", ""
|
526
|
-
)
|
527
|
-
list_app_response.add_step(list_workstations_step)
|
528
|
-
if output == "json":
|
529
|
-
click.echo(json.dumps(list_app_response.as_dict(), indent=4))
|
530
343
|
return
|
531
344
|
|
532
345
|
workstations_json = workstations_response.json()["workstations"]
|
@@ -562,8 +375,6 @@ def list(config_dir=None, profile=None, output=""):
|
|
562
375
|
click.echo("\n", err=True)
|
563
376
|
except Exception as e:
|
564
377
|
click.secho(f"Failed to list apps!", fg="red", err=True)
|
565
|
-
if output == "json":
|
566
|
-
click.echo(json.dumps(list_app_response.as_dict(), indent=4))
|
567
378
|
|
568
379
|
|
569
380
|
def ensure_app_start_request_is_valid(existing_named_ports, port: int, name: str):
|
@@ -583,4 +394,57 @@ def ensure_app_start_request_is_valid(existing_named_ports, port: int, name: str
|
|
583
394
|
)
|
584
395
|
|
585
396
|
|
397
|
+
def wait_for_app_port_to_be_accessible(
|
398
|
+
api_url, metaflow_token, workstation_id, app_name, poll_timeout_seconds
|
399
|
+
) -> bool:
|
400
|
+
num_retries_per_request = 3
|
401
|
+
start_time = time.time()
|
402
|
+
retry_delay = 1.0
|
403
|
+
poll_interval = 10
|
404
|
+
wait_message = f"App {app_name} is currently being deployed..."
|
405
|
+
while time.time() - start_time < poll_timeout_seconds:
|
406
|
+
for _ in range(num_retries_per_request):
|
407
|
+
try:
|
408
|
+
workstations_response = requests.get(
|
409
|
+
f"{api_url}/v1/workstations", headers={"x-api-key": metaflow_token}
|
410
|
+
)
|
411
|
+
workstations_response.raise_for_status()
|
412
|
+
if is_app_ready(workstations_response.json(), workstation_id, app_name):
|
413
|
+
click.secho(
|
414
|
+
wait_message,
|
415
|
+
fg="yellow",
|
416
|
+
err=True,
|
417
|
+
)
|
418
|
+
time.sleep(APP_READY_EXTRA_BUFFER_SECONDS)
|
419
|
+
return True
|
420
|
+
else:
|
421
|
+
click.secho(
|
422
|
+
wait_message,
|
423
|
+
fg="yellow",
|
424
|
+
err=True,
|
425
|
+
)
|
426
|
+
time.sleep(poll_interval)
|
427
|
+
except (
|
428
|
+
requests.exceptions.ConnectionError,
|
429
|
+
requests.exceptions.ReadTimeout,
|
430
|
+
):
|
431
|
+
time.sleep(retry_delay)
|
432
|
+
retry_delay *= 2 # Double the delay for the next attempt
|
433
|
+
retry_delay += random.uniform(0, 1) # Add jitter
|
434
|
+
retry_delay = min(retry_delay, 10)
|
435
|
+
return False
|
436
|
+
|
437
|
+
|
438
|
+
def is_app_ready(response_json: dict, workstation_id: str, app_name: str) -> bool:
|
439
|
+
"""Checks if the app is ready in the given workstation's response."""
|
440
|
+
workstations = response_json.get("workstations", [])
|
441
|
+
for workstation in workstations:
|
442
|
+
if workstation.get("instance_id") == workstation_id:
|
443
|
+
hosted_apps = workstation.get("status", {}).get("hosted_apps", [])
|
444
|
+
for hosted_app in hosted_apps:
|
445
|
+
if hosted_app.get("name") == app_name:
|
446
|
+
return bool(hosted_app.get("ready"))
|
447
|
+
return False
|
448
|
+
|
449
|
+
|
586
450
|
cli.add_command(app, name="app")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: outerbounds
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.111
|
4
4
|
Summary: More Data Science, Less Administration
|
5
5
|
License: Proprietary
|
6
6
|
Keywords: data science,machine learning,MLOps
|
@@ -25,10 +25,10 @@ Requires-Dist: google-api-core (>=2.16.1,<3.0.0) ; extra == "gcp"
|
|
25
25
|
Requires-Dist: google-auth (>=2.27.0,<3.0.0) ; extra == "gcp"
|
26
26
|
Requires-Dist: google-cloud-secret-manager (>=2.20.0,<3.0.0) ; extra == "gcp"
|
27
27
|
Requires-Dist: google-cloud-storage (>=2.14.0,<3.0.0) ; extra == "gcp"
|
28
|
-
Requires-Dist: metaflow-checkpoint (==0.0
|
29
|
-
Requires-Dist: ob-metaflow (==2.12.25.
|
30
|
-
Requires-Dist: ob-metaflow-extensions (==1.1.
|
31
|
-
Requires-Dist: ob-metaflow-stubs (==6.0.3.
|
28
|
+
Requires-Dist: metaflow-checkpoint (==0.1.0)
|
29
|
+
Requires-Dist: ob-metaflow (==2.12.25.2)
|
30
|
+
Requires-Dist: ob-metaflow-extensions (==1.1.99)
|
31
|
+
Requires-Dist: ob-metaflow-stubs (==6.0.3.111)
|
32
32
|
Requires-Dist: opentelemetry-distro (==0.41b0)
|
33
33
|
Requires-Dist: opentelemetry-exporter-otlp-proto-http (==1.20.0)
|
34
34
|
Requires-Dist: opentelemetry-instrumentation-requests (==0.41b0)
|
@@ -41,7 +41,7 @@ outerbounds/_vendor/yaml/serializer.py,sha256=8wFZRy9SsQSktF_f9OOroroqsh4qVUe53r
|
|
41
41
|
outerbounds/_vendor/yaml/tokens.py,sha256=JBSu38wihGr4l73JwbfMA7Ks1-X84g8-NskTz7KwPmA,2578
|
42
42
|
outerbounds/cli_main.py,sha256=e9UMnPysmc7gbrimq2I4KfltggyU7pw59Cn9aEguVcU,74
|
43
43
|
outerbounds/command_groups/__init__.py,sha256=QPWtj5wDRTINDxVUL7XPqG3HoxHNvYOg08EnuSZB2Hc,21
|
44
|
-
outerbounds/command_groups/apps_cli.py,sha256=
|
44
|
+
outerbounds/command_groups/apps_cli.py,sha256=8jmQufa0bK2sfRfs7DiWjoJ1oWiqZAixsL4Dte_KY4Y,17201
|
45
45
|
outerbounds/command_groups/cli.py,sha256=q0hdJO4biD3iEOdyJcxnRkeleA8AKAhx842kQ49I6kk,365
|
46
46
|
outerbounds/command_groups/local_setup_cli.py,sha256=tuuqJRXQ_guEwOuQSIf9wkUU0yg8yAs31myGViAK15s,36364
|
47
47
|
outerbounds/command_groups/perimeters_cli.py,sha256=iF_Uw7ROiSctf6FgoJEy30iDBLVE1j9FKuR3shgJRmc,19050
|
@@ -53,7 +53,7 @@ outerbounds/utils/metaflowconfig.py,sha256=l2vJbgPkLISU-XPGZFaC8ZKmYFyJemlD6bwB-
|
|
53
53
|
outerbounds/utils/schema.py,sha256=lMUr9kNgn9wy-sO_t_Tlxmbt63yLeN4b0xQXbDUDj4A,2331
|
54
54
|
outerbounds/utils/utils.py,sha256=4Z8cszNob_8kDYCLNTrP-wWads_S_MdL3Uj3ju4mEsk,501
|
55
55
|
outerbounds/vendor.py,sha256=gRLRJNXtZBeUpPEog0LOeIsl6GosaFFbCxUvR4bW6IQ,5093
|
56
|
-
outerbounds-0.3.
|
57
|
-
outerbounds-0.3.
|
58
|
-
outerbounds-0.3.
|
59
|
-
outerbounds-0.3.
|
56
|
+
outerbounds-0.3.111.dist-info/METADATA,sha256=v6zcvET5H7gPPNFcR-Gqy_QDh6EB_XYq0N6htQdfVBA,1735
|
57
|
+
outerbounds-0.3.111.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
58
|
+
outerbounds-0.3.111.dist-info/entry_points.txt,sha256=7ye0281PKlvqxu15rjw60zKg2pMsXI49_A8BmGqIqBw,47
|
59
|
+
outerbounds-0.3.111.dist-info/RECORD,,
|
File without changes
|
File without changes
|