outerbounds 0.3.183rc1__py3-none-any.whl → 0.3.185__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/__init__.py +1 -3
- outerbounds/command_groups/apps_cli.py +6 -2
- {outerbounds-0.3.183rc1.dist-info → outerbounds-0.3.185.dist-info}/METADATA +3 -3
- {outerbounds-0.3.183rc1.dist-info → outerbounds-0.3.185.dist-info}/RECORD +6 -29
- outerbounds-0.3.185.dist-info/entry_points.txt +3 -0
- outerbounds/_vendor/spinner/__init__.py +0 -4
- outerbounds/_vendor/spinner/spinners.py +0 -478
- outerbounds/_vendor/spinner.LICENSE +0 -21
- outerbounds/apps/__init__.py +0 -0
- outerbounds/apps/_state_machine.py +0 -472
- outerbounds/apps/app_cli.py +0 -1514
- outerbounds/apps/app_config.py +0 -296
- outerbounds/apps/artifacts.py +0 -0
- outerbounds/apps/capsule.py +0 -839
- outerbounds/apps/cli_to_config.py +0 -99
- outerbounds/apps/click_importer.py +0 -24
- outerbounds/apps/code_package/__init__.py +0 -3
- outerbounds/apps/code_package/code_packager.py +0 -610
- outerbounds/apps/code_package/examples.py +0 -125
- outerbounds/apps/config_schema.yaml +0 -269
- outerbounds/apps/config_schema_autogen.json +0 -336
- outerbounds/apps/dependencies.py +0 -115
- outerbounds/apps/deployer.py +0 -0
- outerbounds/apps/experimental/__init__.py +0 -110
- outerbounds/apps/perimeters.py +0 -45
- outerbounds/apps/secrets.py +0 -164
- outerbounds/apps/utils.py +0 -234
- outerbounds/apps/validations.py +0 -22
- outerbounds-0.3.183rc1.dist-info/entry_points.txt +0 -3
- {outerbounds-0.3.183rc1.dist-info → outerbounds-0.3.185.dist-info}/WHEEL +0 -0
@@ -1,336 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"title": "Outerbounds App Configuration Schema",
|
3
|
-
"description": "Schema for defining Outerbounds Apps configuration. This schema is what we will end up using on the CLI/programmatic interface.\nHow to read this schema:\n 1. If the a property has `allow_union`:true then it will allow overrides from the cli.\n 2. If a property has `experimental` set to true then a lot its validations may-be skipped and parsing handled somewhere else.\n\nThe YAML based schema file is for Humans to change and consume. The JSON based schema file is what gets autogenerated based on pre-commit\nhooks so that we can use within the outerbounds package. The reasons for two distinct types of files it that YAML provides the ability to\nadd comments and make readability easier. While JSON is so that we can reduce the dependency on YAML when working with apps within both\nMetaflow and OB package.\n",
|
4
|
-
"version": "1.0.0",
|
5
|
-
"type": "object",
|
6
|
-
"required": [
|
7
|
-
"name",
|
8
|
-
"port"
|
9
|
-
],
|
10
|
-
"properties": {
|
11
|
-
"name": {
|
12
|
-
"allow_union": true,
|
13
|
-
"type": "string",
|
14
|
-
"description": "The name of the app to deploy.",
|
15
|
-
"maxLength": 20,
|
16
|
-
"example": "myapp"
|
17
|
-
},
|
18
|
-
"port": {
|
19
|
-
"allow_union": false,
|
20
|
-
"type": "integer",
|
21
|
-
"description": "Port where the app is hosted. When deployed this will be port on which we will deploy the app.",
|
22
|
-
"minimum": 1,
|
23
|
-
"maximum": 65535,
|
24
|
-
"example": 8000
|
25
|
-
},
|
26
|
-
"tags": {
|
27
|
-
"allow_union": true,
|
28
|
-
"type": "array",
|
29
|
-
"description": "The tags of the app to deploy.",
|
30
|
-
"items": {
|
31
|
-
"type": "object"
|
32
|
-
},
|
33
|
-
"example": [
|
34
|
-
{
|
35
|
-
"foo": "bar"
|
36
|
-
},
|
37
|
-
{
|
38
|
-
"x": "y"
|
39
|
-
}
|
40
|
-
]
|
41
|
-
},
|
42
|
-
"description": {
|
43
|
-
"allow_union": true,
|
44
|
-
"type": "string",
|
45
|
-
"description": "The description of the app to deploy.",
|
46
|
-
"example": "This is a description of my app."
|
47
|
-
},
|
48
|
-
"force_upgrade": {
|
49
|
-
"allow_union": true,
|
50
|
-
"type": "boolean",
|
51
|
-
"description": "Whether to force upgrade the app even if it is currently being upgraded.",
|
52
|
-
"example": true
|
53
|
-
},
|
54
|
-
"app_type": {
|
55
|
-
"allow_union": true,
|
56
|
-
"type": "string",
|
57
|
-
"description": "The User defined type of app to deploy. Its only used for bookkeeping purposes.",
|
58
|
-
"example": "MyCustomAgent"
|
59
|
-
},
|
60
|
-
"image": {
|
61
|
-
"allow_union": true,
|
62
|
-
"type": "string",
|
63
|
-
"description": "The Docker image to deploy with the App."
|
64
|
-
},
|
65
|
-
"secrets": {
|
66
|
-
"allow_union": true,
|
67
|
-
"type": "array",
|
68
|
-
"description": "Outerbounds integrations to attach to the app. You can use the value you set in the `@secrets` decorator in your code.",
|
69
|
-
"items": {
|
70
|
-
"type": "string"
|
71
|
-
},
|
72
|
-
"example": [
|
73
|
-
"hf-token"
|
74
|
-
]
|
75
|
-
},
|
76
|
-
"environment": {
|
77
|
-
"allow_union": true,
|
78
|
-
"type": "object",
|
79
|
-
"description": "Environment variables to deploy with the App.",
|
80
|
-
"additionalProperties": {
|
81
|
-
"oneOf": [
|
82
|
-
{
|
83
|
-
"type": "string"
|
84
|
-
},
|
85
|
-
{
|
86
|
-
"type": "number"
|
87
|
-
},
|
88
|
-
{
|
89
|
-
"type": "boolean"
|
90
|
-
},
|
91
|
-
{
|
92
|
-
"type": "object"
|
93
|
-
},
|
94
|
-
{
|
95
|
-
"type": "array"
|
96
|
-
}
|
97
|
-
]
|
98
|
-
},
|
99
|
-
"example": {
|
100
|
-
"DEBUG": true,
|
101
|
-
"DATABASE_CONFIG": {
|
102
|
-
"host": "localhost",
|
103
|
-
"port": 5432
|
104
|
-
},
|
105
|
-
"ALLOWED_ORIGINS": [
|
106
|
-
"http://localhost:3000",
|
107
|
-
"https://myapp.com"
|
108
|
-
]
|
109
|
-
}
|
110
|
-
},
|
111
|
-
"dependencies": {
|
112
|
-
"allow_union": false,
|
113
|
-
"type": "object",
|
114
|
-
"description": "The dependencies to attach to the app. Only one of the properties can be specified.\n",
|
115
|
-
"properties": {
|
116
|
-
"from_requirements_file": {
|
117
|
-
"type": "string",
|
118
|
-
"description": "The path to the requirements.txt file to attach to the app.",
|
119
|
-
"example": "requirements.txt"
|
120
|
-
},
|
121
|
-
"from_pyproject_toml": {
|
122
|
-
"type": "string",
|
123
|
-
"description": "The path to the pyproject.toml file to attach to the app.",
|
124
|
-
"example": "pyproject.toml"
|
125
|
-
},
|
126
|
-
"python": {
|
127
|
-
"type": "string",
|
128
|
-
"description": "The Python version to use for the app.\n",
|
129
|
-
"example": "3.10"
|
130
|
-
},
|
131
|
-
"pypi": {
|
132
|
-
"type": "object",
|
133
|
-
"description": "A dictionary of pypi dependencies to attach to the app.\nThe key is the package name and the value is the version.\n",
|
134
|
-
"example": {
|
135
|
-
"numpy": "1.23.0",
|
136
|
-
"pandas": ""
|
137
|
-
}
|
138
|
-
},
|
139
|
-
"conda": {
|
140
|
-
"type": "object",
|
141
|
-
"description": "A dictionary of pypi dependencies to attach to the app.\nThe key is the package name and the value is the version.\n",
|
142
|
-
"example": {
|
143
|
-
"numpy": "1.23.0",
|
144
|
-
"pandas": ""
|
145
|
-
}
|
146
|
-
}
|
147
|
-
}
|
148
|
-
},
|
149
|
-
"package": {
|
150
|
-
"allow_union": false,
|
151
|
-
"type": "object",
|
152
|
-
"description": "Configurations associated with packaging the app.\n",
|
153
|
-
"properties": {
|
154
|
-
"src_path": {
|
155
|
-
"type": "string",
|
156
|
-
"description": "The path to the source code to deploy with the App.",
|
157
|
-
"example": "./"
|
158
|
-
},
|
159
|
-
"suffixes": {
|
160
|
-
"type": "array",
|
161
|
-
"description": "A list of suffixes to add to the source code to deploy with the App.\n",
|
162
|
-
"items": {
|
163
|
-
"type": "string"
|
164
|
-
},
|
165
|
-
"example": [
|
166
|
-
".py",
|
167
|
-
".ipynb"
|
168
|
-
]
|
169
|
-
}
|
170
|
-
}
|
171
|
-
},
|
172
|
-
"commands": {
|
173
|
-
"allow_union": false,
|
174
|
-
"type": "array",
|
175
|
-
"description": "A list of commands to run the app with. Cannot be configured from the CLI. Only used in `run` command.",
|
176
|
-
"items": {
|
177
|
-
"type": "string"
|
178
|
-
},
|
179
|
-
"example": [
|
180
|
-
"python app.py",
|
181
|
-
"python app.py --foo bar"
|
182
|
-
]
|
183
|
-
},
|
184
|
-
"resources": {
|
185
|
-
"allow_union": true,
|
186
|
-
"type": "object",
|
187
|
-
"properties": {
|
188
|
-
"cpu": {
|
189
|
-
"type": "string",
|
190
|
-
"description": "CPU resource request and limit.",
|
191
|
-
"example": "500m",
|
192
|
-
"default": "1"
|
193
|
-
},
|
194
|
-
"memory": {
|
195
|
-
"type": "string",
|
196
|
-
"description": "Memory resource request and limit.",
|
197
|
-
"example": "512Mi",
|
198
|
-
"default": "4Gi"
|
199
|
-
},
|
200
|
-
"gpu": {
|
201
|
-
"type": "string",
|
202
|
-
"description": "GPU resource request and limit.",
|
203
|
-
"example": "1"
|
204
|
-
},
|
205
|
-
"storage": {
|
206
|
-
"type": "string",
|
207
|
-
"description": "Storage resource request and limit.",
|
208
|
-
"example": "1Gi",
|
209
|
-
"default": "10Gi"
|
210
|
-
}
|
211
|
-
}
|
212
|
-
},
|
213
|
-
"replicas": {
|
214
|
-
"allow_union": true,
|
215
|
-
"type": "object",
|
216
|
-
"description": "The number of replicas to deploy the app with.\n",
|
217
|
-
"properties": {
|
218
|
-
"min": {
|
219
|
-
"type": "integer",
|
220
|
-
"description": "The minimum number of replicas to deploy the app with.",
|
221
|
-
"example": 1
|
222
|
-
},
|
223
|
-
"max": {
|
224
|
-
"type": "integer",
|
225
|
-
"description": "The maximum number of replicas to deploy the app with.",
|
226
|
-
"example": 10
|
227
|
-
}
|
228
|
-
}
|
229
|
-
},
|
230
|
-
"health_check": {
|
231
|
-
"type": "object",
|
232
|
-
"allow_union": false,
|
233
|
-
"properties": {
|
234
|
-
"enabled": {
|
235
|
-
"type": "boolean",
|
236
|
-
"description": "Whether to enable health checks.",
|
237
|
-
"example": true,
|
238
|
-
"default": false
|
239
|
-
},
|
240
|
-
"path": {
|
241
|
-
"type": "string",
|
242
|
-
"description": "The path for health checks.",
|
243
|
-
"example": "/health"
|
244
|
-
},
|
245
|
-
"initial_delay_seconds": {
|
246
|
-
"type": "integer",
|
247
|
-
"description": "Number of seconds to wait before performing the first health check.",
|
248
|
-
"example": 10
|
249
|
-
},
|
250
|
-
"period_seconds": {
|
251
|
-
"type": "integer",
|
252
|
-
"description": "How often to perform the health check.",
|
253
|
-
"example": 30
|
254
|
-
}
|
255
|
-
}
|
256
|
-
},
|
257
|
-
"compute_pools": {
|
258
|
-
"allow_union": true,
|
259
|
-
"type": "array",
|
260
|
-
"description": "A list of compute pools to deploy the app to.\n",
|
261
|
-
"items": {
|
262
|
-
"type": "string"
|
263
|
-
},
|
264
|
-
"example": [
|
265
|
-
"default",
|
266
|
-
"large"
|
267
|
-
]
|
268
|
-
},
|
269
|
-
"auth": {
|
270
|
-
"allow_union": false,
|
271
|
-
"type": "object",
|
272
|
-
"description": "Auth related configurations.\n",
|
273
|
-
"properties": {
|
274
|
-
"type": {
|
275
|
-
"type": "string",
|
276
|
-
"description": "The type of authentication to use for the app.\n",
|
277
|
-
"enum": [
|
278
|
-
"API",
|
279
|
-
"Browser"
|
280
|
-
]
|
281
|
-
},
|
282
|
-
"public": {
|
283
|
-
"type": "boolean",
|
284
|
-
"description": "Whether the app is public or not.\n",
|
285
|
-
"default": true
|
286
|
-
}
|
287
|
-
}
|
288
|
-
},
|
289
|
-
"project": {
|
290
|
-
"type": "string",
|
291
|
-
"description": "The project name to deploy the app to.",
|
292
|
-
"experimental": true,
|
293
|
-
"allow_union": true
|
294
|
-
},
|
295
|
-
"branch": {
|
296
|
-
"type": "string",
|
297
|
-
"description": "The branch name to deploy the app to.",
|
298
|
-
"experimental": true,
|
299
|
-
"allow_union": true
|
300
|
-
},
|
301
|
-
"models": {
|
302
|
-
"type": "array",
|
303
|
-
"description": "model asset ids to include with the deployment. NO CLI Option for this Now.",
|
304
|
-
"experimental": true,
|
305
|
-
"allow_union": true,
|
306
|
-
"items": {
|
307
|
-
"type": "object",
|
308
|
-
"properties": {
|
309
|
-
"asset_id": {
|
310
|
-
"type": "string"
|
311
|
-
},
|
312
|
-
"asset_instance_id": {
|
313
|
-
"type": "string"
|
314
|
-
}
|
315
|
-
}
|
316
|
-
}
|
317
|
-
},
|
318
|
-
"data": {
|
319
|
-
"type": "array",
|
320
|
-
"description": "data asset ids to include with the deployment.",
|
321
|
-
"experimental": true,
|
322
|
-
"allow_union": true,
|
323
|
-
"items": {
|
324
|
-
"type": "object",
|
325
|
-
"properties": {
|
326
|
-
"asset_id": {
|
327
|
-
"type": "string"
|
328
|
-
},
|
329
|
-
"asset_instance_id": {
|
330
|
-
"type": "string"
|
331
|
-
}
|
332
|
-
}
|
333
|
-
}
|
334
|
-
}
|
335
|
-
}
|
336
|
-
}
|
outerbounds/apps/dependencies.py
DELETED
@@ -1,115 +0,0 @@
|
|
1
|
-
import copy
|
2
|
-
import json
|
3
|
-
import os
|
4
|
-
import shutil
|
5
|
-
import sys
|
6
|
-
import tempfile
|
7
|
-
from hashlib import sha256
|
8
|
-
from typing import List, Optional, Callable, Any
|
9
|
-
from .app_config import AppConfig
|
10
|
-
from .utils import TODOException
|
11
|
-
from metaflow.metaflow_config import (
|
12
|
-
get_pinned_conda_libs,
|
13
|
-
DEFAULT_DATASTORE,
|
14
|
-
KUBERNETES_CONTAINER_IMAGE,
|
15
|
-
)
|
16
|
-
from collections import namedtuple
|
17
|
-
|
18
|
-
BakingStatus = namedtuple(
|
19
|
-
"BakingStatus", ["image_should_be_baked", "python_path", "resolved_image"]
|
20
|
-
)
|
21
|
-
|
22
|
-
|
23
|
-
class ImageBakingException(Exception):
|
24
|
-
pass
|
25
|
-
|
26
|
-
|
27
|
-
def _safe_open_file(path: str):
|
28
|
-
if not os.path.exists(path):
|
29
|
-
raise ImageBakingException(f"File does not exist: {path}")
|
30
|
-
try:
|
31
|
-
with open(path, "r") as f:
|
32
|
-
return f.read()
|
33
|
-
except Exception as e:
|
34
|
-
raise ImageBakingException(f"Failed to open file: {e}")
|
35
|
-
|
36
|
-
|
37
|
-
def bake_deployment_image(
|
38
|
-
app_config: AppConfig,
|
39
|
-
cache_file_path: str,
|
40
|
-
logger: Optional[Callable[[str], Any]] = None,
|
41
|
-
) -> BakingStatus:
|
42
|
-
# When do we bake an image?
|
43
|
-
# 1. When the user has specified something like `pypi`/`conda`
|
44
|
-
# 2, When the user has specified something like `from_requirements`/ `from_pyproject`
|
45
|
-
# TODO: add parsers for the pyproject/requirements stuff.
|
46
|
-
from metaflow.ob_internal import bake_image # type: ignore
|
47
|
-
from metaflow.plugins.pypi.parsers import (
|
48
|
-
requirements_txt_parser,
|
49
|
-
pyproject_toml_parser,
|
50
|
-
)
|
51
|
-
|
52
|
-
image = app_config.get("image", KUBERNETES_CONTAINER_IMAGE)
|
53
|
-
python_version = "%d.%d.%d" % sys.version_info[:3]
|
54
|
-
|
55
|
-
dependencies = app_config.get_state("dependencies", {})
|
56
|
-
pypi_packages = {}
|
57
|
-
conda_packages = {}
|
58
|
-
|
59
|
-
parsed_packages = {}
|
60
|
-
|
61
|
-
if dependencies.get("from_requirements_file"):
|
62
|
-
parsed_packages = requirements_txt_parser(
|
63
|
-
_safe_open_file(dependencies.get("from_requirements_file"))
|
64
|
-
)
|
65
|
-
pypi_packages = parsed_packages.get("packages", {})
|
66
|
-
python_version = parsed_packages.get("python_version", python_version)
|
67
|
-
|
68
|
-
elif dependencies.get("from_pyproject_toml"):
|
69
|
-
parsed_packages = pyproject_toml_parser(
|
70
|
-
_safe_open_file(dependencies.get("from_pyproject_toml"))
|
71
|
-
)
|
72
|
-
pypi_packages = parsed_packages.get("packages", {})
|
73
|
-
python_version = parsed_packages.get("python_version", python_version)
|
74
|
-
|
75
|
-
elif "pypi" in dependencies:
|
76
|
-
pypi_packages = dependencies.get("pypi", {})
|
77
|
-
|
78
|
-
if "conda" in dependencies:
|
79
|
-
conda_packages = dependencies.get("conda", {})
|
80
|
-
if "python" in dependencies:
|
81
|
-
python_version = dependencies.get("python", python_version)
|
82
|
-
|
83
|
-
python_packages_exist = len(pypi_packages) > 0 or len(conda_packages) > 0
|
84
|
-
if (not python_packages_exist) or app_config.get_state("skip_dependencies", False):
|
85
|
-
# Inform the user that no dependencies are being used.
|
86
|
-
if app_config.get_state("skip_dependencies", False) and logger:
|
87
|
-
logger(
|
88
|
-
"⏭️ Skipping baking dependencies into the image based on the --no-deps flag."
|
89
|
-
)
|
90
|
-
# TODO: Handle this a little more nicely.
|
91
|
-
return BakingStatus(
|
92
|
-
image_should_be_baked=False, resolved_image=image, python_path="python"
|
93
|
-
)
|
94
|
-
|
95
|
-
pinned_conda_libs = get_pinned_conda_libs(python_version, DEFAULT_DATASTORE)
|
96
|
-
pypi_packages.update(pinned_conda_libs)
|
97
|
-
_reference = app_config.get("name", "default")
|
98
|
-
# `image` cannot be None. If by change it is none, FB will fart.
|
99
|
-
fb_response = bake_image(
|
100
|
-
cache_file_path=cache_file_path,
|
101
|
-
pypi_packages=pypi_packages,
|
102
|
-
conda_packages=conda_packages,
|
103
|
-
ref=_reference,
|
104
|
-
python=python_version,
|
105
|
-
base_image=image,
|
106
|
-
logger=logger,
|
107
|
-
)
|
108
|
-
if fb_response.failure:
|
109
|
-
raise ImageBakingException(f"Failed to bake image: {fb_response.response}")
|
110
|
-
|
111
|
-
return BakingStatus(
|
112
|
-
image_should_be_baked=True,
|
113
|
-
resolved_image=fb_response.container_image,
|
114
|
-
python_path=fb_response.python_path,
|
115
|
-
)
|
outerbounds/apps/deployer.py
DELETED
File without changes
|
@@ -1,110 +0,0 @@
|
|
1
|
-
from functools import wraps
|
2
|
-
from ..click_importer import click
|
3
|
-
import os
|
4
|
-
from typing import TYPE_CHECKING
|
5
|
-
|
6
|
-
if TYPE_CHECKING:
|
7
|
-
from ..app_config import AppConfig
|
8
|
-
|
9
|
-
DEFAULT_BRANCH = "test"
|
10
|
-
|
11
|
-
|
12
|
-
def wrapping_cli_options(func):
|
13
|
-
@click.option(
|
14
|
-
"--project",
|
15
|
-
type=str,
|
16
|
-
help="The flow project the app/endpoint belongs to",
|
17
|
-
default=None,
|
18
|
-
)
|
19
|
-
@click.option(
|
20
|
-
"--branch",
|
21
|
-
type=str,
|
22
|
-
help="The branch the app/endpoint belongs to",
|
23
|
-
default=None,
|
24
|
-
)
|
25
|
-
@wraps(func)
|
26
|
-
def wrapper(*args, **kwargs):
|
27
|
-
return func(*args, **kwargs)
|
28
|
-
|
29
|
-
return wrapper
|
30
|
-
|
31
|
-
|
32
|
-
def build_config_from_options(options):
|
33
|
-
"""Build an app configuration from CLI options."""
|
34
|
-
keys = [
|
35
|
-
"project",
|
36
|
-
"branch",
|
37
|
-
]
|
38
|
-
config = {}
|
39
|
-
for key in keys:
|
40
|
-
if options.get(key):
|
41
|
-
config[key] = options.get(key)
|
42
|
-
|
43
|
-
return config
|
44
|
-
|
45
|
-
|
46
|
-
# Account for project / branch and the capsule input.
|
47
|
-
def capsule_input_overrides(app_config: "AppConfig", capsule_input: dict):
|
48
|
-
project = app_config.get_state("project", None)
|
49
|
-
# Update the project/branch related configurations.
|
50
|
-
if project is not None:
|
51
|
-
branch = app_config.get_state("branch", DEFAULT_BRANCH)
|
52
|
-
capsule_input["tags"].extend(
|
53
|
-
[dict(key="project", value=project), dict(key="branch", value=branch)]
|
54
|
-
)
|
55
|
-
|
56
|
-
model_asset_conf = app_config.get_state("models", None)
|
57
|
-
data_asset_conf = app_config.get_state("data", None)
|
58
|
-
code_info = _code_info(app_config)
|
59
|
-
# todo:fix me
|
60
|
-
_objects_key = "associatedObjects"
|
61
|
-
if model_asset_conf or data_asset_conf or code_info:
|
62
|
-
capsule_input[_objects_key] = {}
|
63
|
-
|
64
|
-
if model_asset_conf:
|
65
|
-
capsule_input[_objects_key]["models"] = [
|
66
|
-
{"assetId": x["asset_id"], "assetInstanceId": x["asset_instance_id"]}
|
67
|
-
for x in model_asset_conf
|
68
|
-
]
|
69
|
-
if data_asset_conf:
|
70
|
-
capsule_input[_objects_key]["data"] = [
|
71
|
-
{"assetId": x["asset_id"], "assetInstanceId": x["asset_instance_id"]}
|
72
|
-
for x in data_asset_conf
|
73
|
-
]
|
74
|
-
if code_info:
|
75
|
-
capsule_input[_objects_key]["code"] = code_info
|
76
|
-
|
77
|
-
return capsule_input
|
78
|
-
|
79
|
-
|
80
|
-
def _code_info(app_config: "AppConfig"):
|
81
|
-
from metaflow.metaflow_git import get_repository_info
|
82
|
-
|
83
|
-
try:
|
84
|
-
from metaflow.metaflow_git import _call_git # type: ignore
|
85
|
-
except ImportError:
|
86
|
-
# Fallback if _call_git is not available
|
87
|
-
def _call_git(args, path=None):
|
88
|
-
return "", 1, True
|
89
|
-
|
90
|
-
repo_info = get_repository_info(app_config.get_state("packaging_directory", None))
|
91
|
-
if len(repo_info) == 0:
|
92
|
-
return None
|
93
|
-
|
94
|
-
git_log_info, returncode, failed = _call_git(
|
95
|
-
["log", "-1", "--pretty=%B"],
|
96
|
-
path=app_config.get_state("packaging_directory", None),
|
97
|
-
)
|
98
|
-
repo_url = repo_info["repo_url"]
|
99
|
-
if isinstance(repo_url, str):
|
100
|
-
_url = repo_url if not repo_url.endswith(".git") else repo_url.rstrip(".git")
|
101
|
-
else:
|
102
|
-
_url = str(repo_url)
|
103
|
-
_code_info = {
|
104
|
-
"commitId": repo_info["commit_sha"],
|
105
|
-
"commitLink": os.path.join(_url, "commit", str(repo_info["commit_sha"])),
|
106
|
-
}
|
107
|
-
if not failed and returncode == 0 and isinstance(git_log_info, str):
|
108
|
-
_code_info["commitMessage"] = git_log_info.strip()
|
109
|
-
|
110
|
-
return _code_info
|
outerbounds/apps/perimeters.py
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
import json
|
3
|
-
from typing import Tuple, Union
|
4
|
-
|
5
|
-
|
6
|
-
class PerimeterExtractor:
|
7
|
-
@classmethod
|
8
|
-
def for_ob_cli(
|
9
|
-
cls, config_dir: str, profile: str
|
10
|
-
) -> Union[Tuple[str, str], Tuple[None, None]]:
|
11
|
-
"""
|
12
|
-
This function will be called when we are trying to extract the perimeter
|
13
|
-
via the ob cli's execution. We will rely on the following logic:
|
14
|
-
1. check environment variables like OB_CURRENT_PERIMETER / OBP_PERIMETER
|
15
|
-
2. run init config to extract the perimeter related configurations.
|
16
|
-
|
17
|
-
Returns
|
18
|
-
-------
|
19
|
-
Tuple[str, str] : Tuple containing perimeter name , API server url.
|
20
|
-
"""
|
21
|
-
from outerbounds.utils import metaflowconfig
|
22
|
-
|
23
|
-
perimeter = None
|
24
|
-
api_server = None
|
25
|
-
if os.environ.get("OB_CURRENT_PERIMETER") or os.environ.get("OBP_PERIMETER"):
|
26
|
-
perimeter = os.environ.get("OB_CURRENT_PERIMETER") or os.environ.get(
|
27
|
-
"OBP_PERIMETER"
|
28
|
-
)
|
29
|
-
|
30
|
-
if os.environ.get("OBP_API_SERVER"):
|
31
|
-
api_server = os.environ.get("OBP_API_SERVER")
|
32
|
-
|
33
|
-
if perimeter is None or api_server is None:
|
34
|
-
metaflow_config = metaflowconfig.init_config(config_dir, profile)
|
35
|
-
perimeter = metaflow_config.get("OBP_PERIMETER")
|
36
|
-
api_server = metaflowconfig.get_sanitized_url_from_config(
|
37
|
-
config_dir, profile, "OBP_API_SERVER"
|
38
|
-
)
|
39
|
-
|
40
|
-
return perimeter, api_server # type: ignore
|
41
|
-
|
42
|
-
@classmethod
|
43
|
-
def during_metaflow_execution(cls) -> str:
|
44
|
-
# TODO: implement this
|
45
|
-
return ""
|