outerbounds 0.3.175rc0__py3-none-any.whl → 0.3.175rc1__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/apps/app_cli.py +12 -0
- outerbounds/apps/capsule.py +8 -2
- outerbounds/apps/cli_to_config.py +1 -1
- outerbounds/apps/config_schema.yaml +10 -1
- outerbounds/command_groups/cli.py +2 -0
- outerbounds/command_groups/flowprojects_cli.py +137 -0
- {outerbounds-0.3.175rc0.dist-info → outerbounds-0.3.175rc1.dist-info}/METADATA +3 -3
- {outerbounds-0.3.175rc0.dist-info → outerbounds-0.3.175rc1.dist-info}/RECORD +10 -9
- {outerbounds-0.3.175rc0.dist-info → outerbounds-0.3.175rc1.dist-info}/WHEEL +0 -0
- {outerbounds-0.3.175rc0.dist-info → outerbounds-0.3.175rc1.dist-info}/entry_points.txt +0 -0
outerbounds/apps/app_cli.py
CHANGED
@@ -231,6 +231,18 @@ def common_deploy_options(func):
|
|
231
231
|
help="Maximum number of replicas to deploy",
|
232
232
|
default=None,
|
233
233
|
)
|
234
|
+
@click.option(
|
235
|
+
"--description",
|
236
|
+
type=str,
|
237
|
+
help="The description of the app to deploy.",
|
238
|
+
default=None,
|
239
|
+
)
|
240
|
+
@click.option(
|
241
|
+
"--app-type",
|
242
|
+
type=str,
|
243
|
+
help="The type of app to deploy.",
|
244
|
+
default=None,
|
245
|
+
)
|
234
246
|
@wraps(func)
|
235
247
|
def wrapper(*args, **kwargs):
|
236
248
|
return func(*args, **kwargs)
|
outerbounds/apps/capsule.py
CHANGED
@@ -172,10 +172,16 @@ class CapsuleInput:
|
|
172
172
|
_scheduling_config["computePools"] = [
|
173
173
|
{"name": x} for x in app_config.get_state("compute_pools")
|
174
174
|
]
|
175
|
-
|
175
|
+
_description = app_config.get_state("description")
|
176
|
+
_app_type = app_config.get_state("app_type")
|
177
|
+
_final_info = {}
|
178
|
+
if _description:
|
179
|
+
_final_info["description"] = _description
|
180
|
+
if _app_type:
|
181
|
+
_final_info["endpointType"] = _app_type
|
176
182
|
return {
|
177
183
|
"perimeter": app_config.get_state("perimeter"),
|
178
|
-
|
184
|
+
**_final_info,
|
179
185
|
"codePackagePath": app_config.get_state("code_package_url"),
|
180
186
|
"image": app_config.get_state("image"),
|
181
187
|
"resourceIntegrations": [
|
@@ -6,7 +6,7 @@ def build_config_from_options(options):
|
|
6
6
|
config = {}
|
7
7
|
|
8
8
|
# Set basic fields
|
9
|
-
for key in ["name", "port", "image", "compute_pools"]:
|
9
|
+
for key in ["name", "port", "image", "compute_pools", "description", "app_type"]:
|
10
10
|
if options.get(key):
|
11
11
|
config[key] = options[key]
|
12
12
|
|
@@ -33,11 +33,20 @@ properties:
|
|
33
33
|
example:
|
34
34
|
- foo: bar
|
35
35
|
- x: y
|
36
|
+
description: # Only used in `deploy` command
|
37
|
+
allow_union: true
|
38
|
+
type: string
|
39
|
+
description: The description of the app to deploy.
|
40
|
+
example: "This is a description of my app."
|
41
|
+
app_type: # Only used in `deploy` command
|
42
|
+
allow_union: true
|
43
|
+
type: string
|
44
|
+
description: The User defined type of app to deploy. Its only used for bookkeeping purposes.
|
45
|
+
example: "MyCustomAgent"
|
36
46
|
image: # Only used in `deploy` command
|
37
47
|
allow_union: true # We will overrwite the image if specified on the CLI.
|
38
48
|
type: string
|
39
49
|
description: The Docker image to deploy with the App.
|
40
|
-
example: "python:3.10-slim"
|
41
50
|
secrets: # Used in `run` command
|
42
51
|
allow_union: true
|
43
52
|
type: array
|
@@ -7,6 +7,7 @@ from . import (
|
|
7
7
|
tutorials_cli,
|
8
8
|
fast_bakery_cli,
|
9
9
|
secrets_cli,
|
10
|
+
flowprojects_cli,
|
10
11
|
)
|
11
12
|
|
12
13
|
|
@@ -20,6 +21,7 @@ from . import (
|
|
20
21
|
tutorials_cli.cli,
|
21
22
|
fast_bakery_cli.cli,
|
22
23
|
secrets_cli.cli,
|
24
|
+
flowprojects_cli.cli,
|
23
25
|
],
|
24
26
|
)
|
25
27
|
def cli(**kwargs):
|
@@ -0,0 +1,137 @@
|
|
1
|
+
import json
|
2
|
+
import os
|
3
|
+
import sys
|
4
|
+
import requests
|
5
|
+
|
6
|
+
from ..utils import metaflowconfig
|
7
|
+
from outerbounds._vendor import click
|
8
|
+
|
9
|
+
|
10
|
+
@click.group()
|
11
|
+
def cli(**kwargs):
|
12
|
+
pass
|
13
|
+
|
14
|
+
|
15
|
+
@cli.group(help="Commands for pushing Deployments metadata.", hidden=True)
|
16
|
+
def flowproject(**kwargs):
|
17
|
+
pass
|
18
|
+
|
19
|
+
|
20
|
+
@flowproject.command()
|
21
|
+
@click.option(
|
22
|
+
"-d",
|
23
|
+
"--config-dir",
|
24
|
+
default=os.path.expanduser(os.environ.get("METAFLOW_HOME", "~/.metaflowconfig")),
|
25
|
+
help="Path to Metaflow configuration directory",
|
26
|
+
show_default=True,
|
27
|
+
)
|
28
|
+
@click.option(
|
29
|
+
"-p",
|
30
|
+
"--profile",
|
31
|
+
default=os.environ.get("METAFLOW_PROFILE", ""),
|
32
|
+
help="The named metaflow profile in which your workstation exists",
|
33
|
+
)
|
34
|
+
@click.option("--id", help="The ID for this deployment")
|
35
|
+
def get_metadata(config_dir, profile, id):
|
36
|
+
api_url = metaflowconfig.get_sanitized_url_from_config(
|
37
|
+
config_dir, profile, "OBP_API_SERVER"
|
38
|
+
)
|
39
|
+
perimeter = _get_perimeter()
|
40
|
+
headers = _get_request_headers()
|
41
|
+
|
42
|
+
project, branch = _parse_id(id)
|
43
|
+
|
44
|
+
# GET the latest flowproject config in order to modify it
|
45
|
+
# /v1/perimeters/:perimeter/:project/:branch/flowprojects/latest
|
46
|
+
response = requests.get(
|
47
|
+
url=f"{api_url}/v1/perimeters/{perimeter}/projects/{project}/branches/{branch}/latestflowproject",
|
48
|
+
headers=headers,
|
49
|
+
)
|
50
|
+
if response.status_code >= 500:
|
51
|
+
raise Exception("API request failed.")
|
52
|
+
|
53
|
+
body = response.json()
|
54
|
+
if response.status_code >= 400:
|
55
|
+
raise Exception("request failed: %s" % body)
|
56
|
+
|
57
|
+
out = json.dumps(body)
|
58
|
+
|
59
|
+
print(out, file=sys.stdout)
|
60
|
+
|
61
|
+
|
62
|
+
@flowproject.command()
|
63
|
+
@click.option(
|
64
|
+
"-d",
|
65
|
+
"--config-dir",
|
66
|
+
default=os.path.expanduser(os.environ.get("METAFLOW_HOME", "~/.metaflowconfig")),
|
67
|
+
help="Path to Metaflow configuration directory",
|
68
|
+
show_default=True,
|
69
|
+
)
|
70
|
+
@click.option(
|
71
|
+
"-p",
|
72
|
+
"--profile",
|
73
|
+
default=os.environ.get("METAFLOW_PROFILE", ""),
|
74
|
+
help="The named metaflow profile in which your workstation exists",
|
75
|
+
)
|
76
|
+
@click.argument("json_str")
|
77
|
+
def set_metadata(config_dir, profile, json_str):
|
78
|
+
api_url = metaflowconfig.get_sanitized_url_from_config(
|
79
|
+
config_dir, profile, "OBP_API_SERVER"
|
80
|
+
)
|
81
|
+
|
82
|
+
perimeter = _get_perimeter()
|
83
|
+
headers = _get_request_headers()
|
84
|
+
payload = json.loads(json_str)
|
85
|
+
|
86
|
+
# POST the updated flowproject config
|
87
|
+
# /v1/perimeters/:perimeter/flowprojects
|
88
|
+
response = requests.post(
|
89
|
+
url=f"{api_url}/v1/perimeters/{perimeter}/flowprojects",
|
90
|
+
json=payload,
|
91
|
+
headers=headers,
|
92
|
+
)
|
93
|
+
if response.status_code >= 500:
|
94
|
+
raise Exception("API request failed. %s" % response.text)
|
95
|
+
|
96
|
+
if response.status_code >= 400:
|
97
|
+
raise Exception("request failed: %s" % response.text)
|
98
|
+
body = response.json()
|
99
|
+
|
100
|
+
print(body, file=sys.stdout)
|
101
|
+
|
102
|
+
|
103
|
+
def _get_request_headers():
|
104
|
+
headers = {"Content-Type": "application/json", "Connection": "keep-alive"}
|
105
|
+
try:
|
106
|
+
from metaflow.metaflow_config import SERVICE_HEADERS
|
107
|
+
|
108
|
+
headers = {**headers, **(SERVICE_HEADERS or {})}
|
109
|
+
except ImportError:
|
110
|
+
headers = headers
|
111
|
+
|
112
|
+
return headers
|
113
|
+
|
114
|
+
|
115
|
+
def _get_perimeter():
|
116
|
+
# Get current perimeter
|
117
|
+
from metaflow_extensions.outerbounds.remote_config import init_config # type: ignore
|
118
|
+
|
119
|
+
conf = init_config()
|
120
|
+
if "OBP_PERIMETER" in conf:
|
121
|
+
perimeter = conf["OBP_PERIMETER"]
|
122
|
+
else:
|
123
|
+
# if the perimeter is not in metaflow config, try to get it from the environment
|
124
|
+
perimeter = os.environ.get("OBP_PERIMETER", None)
|
125
|
+
if perimeter is None:
|
126
|
+
raise Exception("Perimeter not found in config, but is required.")
|
127
|
+
|
128
|
+
return perimeter
|
129
|
+
|
130
|
+
|
131
|
+
def _parse_id(id: str):
|
132
|
+
parts = id.split("/")
|
133
|
+
if len(parts) != 2:
|
134
|
+
raise Exception("ID should consist of two parts: project/branch")
|
135
|
+
|
136
|
+
project, branch = parts
|
137
|
+
return project, branch
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: outerbounds
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.175rc1
|
4
4
|
Summary: More Data Science, Less Administration
|
5
5
|
License: Proprietary
|
6
6
|
Keywords: data science,machine learning,MLOps
|
@@ -29,8 +29,8 @@ Requires-Dist: google-cloud-secret-manager (>=2.20.0,<3.0.0) ; extra == "gcp"
|
|
29
29
|
Requires-Dist: google-cloud-storage (>=2.14.0,<3.0.0) ; extra == "gcp"
|
30
30
|
Requires-Dist: metaflow-checkpoint (==0.2.1)
|
31
31
|
Requires-Dist: ob-metaflow (==2.15.14.1)
|
32
|
-
Requires-Dist: ob-metaflow-extensions (==1.1.
|
33
|
-
Requires-Dist: ob-metaflow-stubs (==6.0.3.
|
32
|
+
Requires-Dist: ob-metaflow-extensions (==1.1.161rc1)
|
33
|
+
Requires-Dist: ob-metaflow-stubs (==6.0.3.175rc1)
|
34
34
|
Requires-Dist: opentelemetry-distro (>=0.41b0) ; extra == "otel"
|
35
35
|
Requires-Dist: opentelemetry-exporter-otlp-proto-http (>=1.20.0) ; extra == "otel"
|
36
36
|
Requires-Dist: opentelemetry-instrumentation-requests (>=0.41b0) ; extra == "otel"
|
@@ -40,15 +40,15 @@ outerbounds/_vendor/yaml/scanner.py,sha256=ZcI8IngR56PaQ0m27WU2vxCqmDCuRjz-hr7pi
|
|
40
40
|
outerbounds/_vendor/yaml/serializer.py,sha256=8wFZRy9SsQSktF_f9OOroroqsh4qVUe53ry07P9UgCc,4368
|
41
41
|
outerbounds/_vendor/yaml/tokens.py,sha256=JBSu38wihGr4l73JwbfMA7Ks1-X84g8-NskTz7KwPmA,2578
|
42
42
|
outerbounds/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
43
|
-
outerbounds/apps/app_cli.py,sha256=
|
43
|
+
outerbounds/apps/app_cli.py,sha256=zJFjoO6wPjRoKOPywWZ7NqXt4HwlHfPMQ6AquvKKAus,17833
|
44
44
|
outerbounds/apps/app_config.py,sha256=KBmW9grhiuG9XZG-R0GZkM-024cjj6ztGzOX_2wZW34,11291
|
45
45
|
outerbounds/apps/artifacts.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
46
|
-
outerbounds/apps/capsule.py,sha256=
|
47
|
-
outerbounds/apps/cli_to_config.py,sha256=
|
46
|
+
outerbounds/apps/capsule.py,sha256=BRUBF8WV_lm4QCnxxPQ6jlikdKS_bvf41pwrRqgWIpQ,13608
|
47
|
+
outerbounds/apps/cli_to_config.py,sha256=hV6rfPgCiAX03O363GkvdjSIJBt3-oSbL6F2sTUucFE,3195
|
48
48
|
outerbounds/apps/code_package/__init__.py,sha256=8McF7pgx8ghvjRnazp2Qktlxi9yYwNiwESSQrk-2oW8,68
|
49
49
|
outerbounds/apps/code_package/code_packager.py,sha256=SQDBXKwizzpag5GpwoZpvvkyPOodRSQwk2ecAAfO0HI,23316
|
50
50
|
outerbounds/apps/code_package/examples.py,sha256=aF8qKIJxCVv_ugcShQjqUsXKKKMsm1oMkQIl8w3QKuw,4016
|
51
|
-
outerbounds/apps/config_schema.yaml,sha256=
|
51
|
+
outerbounds/apps/config_schema.yaml,sha256=bN7mXlVddqN8G4jq6qBpVXl_qFJdOYrmj8E4OY23Rr8,8641
|
52
52
|
outerbounds/apps/dependencies.py,sha256=SqvdFQdFZZW0wXX_CHMHCrfE0TwaRkTvGCRbQ2Mx3q0,3935
|
53
53
|
outerbounds/apps/deployer.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
54
54
|
outerbounds/apps/experimental/__init__.py,sha256=12L_FzZyzv162uo4I6cmlrxat7feUtIu_kxbObTJZTA,3059
|
@@ -58,8 +58,9 @@ outerbounds/apps/validations.py,sha256=AVEw9eCvkzqq1m5ZC8btaWrSR6kWYKzarELfrASuA
|
|
58
58
|
outerbounds/cli_main.py,sha256=e9UMnPysmc7gbrimq2I4KfltggyU7pw59Cn9aEguVcU,74
|
59
59
|
outerbounds/command_groups/__init__.py,sha256=QPWtj5wDRTINDxVUL7XPqG3HoxHNvYOg08EnuSZB2Hc,21
|
60
60
|
outerbounds/command_groups/apps_cli.py,sha256=weXYgUbTVIxMSweLVdod_C1laiB32YKwYhf22OfqQJE,20815
|
61
|
-
outerbounds/command_groups/cli.py,sha256=
|
61
|
+
outerbounds/command_groups/cli.py,sha256=I8b0zyY_xhZfmaLgJcgR98YXxgirkUK7xsjknEd4nfc,534
|
62
62
|
outerbounds/command_groups/fast_bakery_cli.py,sha256=5kja7v6C651XAY6dsP_IkBPJQgfU4hA4S9yTOiVPhW0,6213
|
63
|
+
outerbounds/command_groups/flowprojects_cli.py,sha256=gFAA_zUIyhD092Hd7IW5InuIxOqdwRJsHgyWQjy8LZw,3792
|
63
64
|
outerbounds/command_groups/local_setup_cli.py,sha256=tuuqJRXQ_guEwOuQSIf9wkUU0yg8yAs31myGViAK15s,36364
|
64
65
|
outerbounds/command_groups/perimeters_cli.py,sha256=iF_Uw7ROiSctf6FgoJEy30iDBLVE1j9FKuR3shgJRmc,19050
|
65
66
|
outerbounds/command_groups/secrets_cli.py,sha256=Vgn_aiTo76a0s5hCJhNWEOrCVhyYeivD08ooQxz0y7c,2952
|
@@ -71,7 +72,7 @@ outerbounds/utils/metaflowconfig.py,sha256=l2vJbgPkLISU-XPGZFaC8ZKmYFyJemlD6bwB-
|
|
71
72
|
outerbounds/utils/schema.py,sha256=lMUr9kNgn9wy-sO_t_Tlxmbt63yLeN4b0xQXbDUDj4A,2331
|
72
73
|
outerbounds/utils/utils.py,sha256=4Z8cszNob_8kDYCLNTrP-wWads_S_MdL3Uj3ju4mEsk,501
|
73
74
|
outerbounds/vendor.py,sha256=gRLRJNXtZBeUpPEog0LOeIsl6GosaFFbCxUvR4bW6IQ,5093
|
74
|
-
outerbounds-0.3.
|
75
|
-
outerbounds-0.3.
|
76
|
-
outerbounds-0.3.
|
77
|
-
outerbounds-0.3.
|
75
|
+
outerbounds-0.3.175rc1.dist-info/METADATA,sha256=BzZlrHhvLf-__NA2SX6gihlFIgGuXyJ-VhzpVrjSi3Q,1846
|
76
|
+
outerbounds-0.3.175rc1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
77
|
+
outerbounds-0.3.175rc1.dist-info/entry_points.txt,sha256=7ye0281PKlvqxu15rjw60zKg2pMsXI49_A8BmGqIqBw,47
|
78
|
+
outerbounds-0.3.175rc1.dist-info/RECORD,,
|
File without changes
|
File without changes
|