ob-metaflow-extensions 1.1.151__py2.py3-none-any.whl → 1.6.2__py2.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.
- metaflow_extensions/outerbounds/__init__.py +1 -1
- metaflow_extensions/outerbounds/plugins/__init__.py +24 -3
- metaflow_extensions/outerbounds/plugins/apps/app_cli.py +0 -0
- metaflow_extensions/outerbounds/plugins/apps/core/__init__.py +16 -0
- metaflow_extensions/outerbounds/plugins/apps/core/_state_machine.py +506 -0
- metaflow_extensions/outerbounds/plugins/apps/core/_vendor/__init__.py +0 -0
- metaflow_extensions/outerbounds/plugins/apps/core/_vendor/spinner/__init__.py +4 -0
- metaflow_extensions/outerbounds/plugins/apps/core/_vendor/spinner/spinners.py +478 -0
- metaflow_extensions/outerbounds/plugins/apps/core/app_config.py +128 -0
- metaflow_extensions/outerbounds/plugins/apps/core/app_deploy_decorator.py +333 -0
- metaflow_extensions/outerbounds/plugins/apps/core/artifacts.py +0 -0
- metaflow_extensions/outerbounds/plugins/apps/core/capsule.py +1029 -0
- metaflow_extensions/outerbounds/plugins/apps/core/click_importer.py +24 -0
- metaflow_extensions/outerbounds/plugins/apps/core/code_package/__init__.py +3 -0
- metaflow_extensions/outerbounds/plugins/apps/core/code_package/code_packager.py +618 -0
- metaflow_extensions/outerbounds/plugins/apps/core/code_package/examples.py +125 -0
- metaflow_extensions/outerbounds/plugins/apps/core/config/__init__.py +15 -0
- metaflow_extensions/outerbounds/plugins/apps/core/config/cli_generator.py +165 -0
- metaflow_extensions/outerbounds/plugins/apps/core/config/config_utils.py +966 -0
- metaflow_extensions/outerbounds/plugins/apps/core/config/schema_export.py +299 -0
- metaflow_extensions/outerbounds/plugins/apps/core/config/typed_configs.py +233 -0
- metaflow_extensions/outerbounds/plugins/apps/core/config/typed_init_generator.py +537 -0
- metaflow_extensions/outerbounds/plugins/apps/core/config/unified_config.py +1125 -0
- metaflow_extensions/outerbounds/plugins/apps/core/config_schema.yaml +337 -0
- metaflow_extensions/outerbounds/plugins/apps/core/dependencies.py +115 -0
- metaflow_extensions/outerbounds/plugins/apps/core/deployer.py +1300 -0
- metaflow_extensions/outerbounds/plugins/apps/core/exceptions.py +341 -0
- metaflow_extensions/outerbounds/plugins/apps/core/experimental/__init__.py +89 -0
- metaflow_extensions/outerbounds/plugins/apps/core/perimeters.py +123 -0
- metaflow_extensions/outerbounds/plugins/apps/core/secrets.py +164 -0
- metaflow_extensions/outerbounds/plugins/apps/core/utils.py +233 -0
- metaflow_extensions/outerbounds/plugins/apps/core/validations.py +17 -0
- metaflow_extensions/outerbounds/plugins/aws/__init__.py +4 -0
- metaflow_extensions/outerbounds/plugins/aws/assume_role.py +3 -0
- metaflow_extensions/outerbounds/plugins/aws/assume_role_decorator.py +118 -0
- metaflow_extensions/outerbounds/plugins/checkpoint_datastores/coreweave.py +9 -77
- metaflow_extensions/outerbounds/plugins/checkpoint_datastores/external_chckpt.py +85 -0
- metaflow_extensions/outerbounds/plugins/checkpoint_datastores/nebius.py +7 -78
- metaflow_extensions/outerbounds/plugins/fast_bakery/baker.py +119 -0
- metaflow_extensions/outerbounds/plugins/fast_bakery/docker_environment.py +17 -3
- metaflow_extensions/outerbounds/plugins/fast_bakery/fast_bakery.py +1 -0
- metaflow_extensions/outerbounds/plugins/kubernetes/kubernetes_client.py +18 -44
- metaflow_extensions/outerbounds/plugins/kubernetes/pod_killer.py +374 -0
- metaflow_extensions/outerbounds/plugins/nim/card.py +1 -6
- metaflow_extensions/outerbounds/plugins/nim/{__init__.py → nim_decorator.py} +13 -49
- metaflow_extensions/outerbounds/plugins/nim/nim_manager.py +294 -233
- metaflow_extensions/outerbounds/plugins/nim/utils.py +36 -0
- metaflow_extensions/outerbounds/plugins/nvcf/constants.py +2 -2
- metaflow_extensions/outerbounds/plugins/nvct/nvct_decorator.py +32 -8
- metaflow_extensions/outerbounds/plugins/nvct/nvct_runner.py +1 -1
- metaflow_extensions/outerbounds/plugins/ollama/__init__.py +171 -16
- metaflow_extensions/outerbounds/plugins/ollama/constants.py +1 -0
- metaflow_extensions/outerbounds/plugins/ollama/exceptions.py +22 -0
- metaflow_extensions/outerbounds/plugins/ollama/ollama.py +1710 -114
- metaflow_extensions/outerbounds/plugins/ollama/status_card.py +292 -0
- metaflow_extensions/outerbounds/plugins/optuna/__init__.py +49 -0
- metaflow_extensions/outerbounds/plugins/profilers/simple_card_decorator.py +96 -0
- metaflow_extensions/outerbounds/plugins/s3_proxy/__init__.py +7 -0
- metaflow_extensions/outerbounds/plugins/s3_proxy/binary_caller.py +132 -0
- metaflow_extensions/outerbounds/plugins/s3_proxy/constants.py +11 -0
- metaflow_extensions/outerbounds/plugins/s3_proxy/exceptions.py +13 -0
- metaflow_extensions/outerbounds/plugins/s3_proxy/proxy_bootstrap.py +59 -0
- metaflow_extensions/outerbounds/plugins/s3_proxy/s3_proxy_api.py +93 -0
- metaflow_extensions/outerbounds/plugins/s3_proxy/s3_proxy_decorator.py +250 -0
- metaflow_extensions/outerbounds/plugins/s3_proxy/s3_proxy_manager.py +225 -0
- metaflow_extensions/outerbounds/plugins/snowflake/snowflake.py +37 -7
- metaflow_extensions/outerbounds/plugins/snowpark/snowpark.py +18 -8
- metaflow_extensions/outerbounds/plugins/snowpark/snowpark_cli.py +6 -0
- metaflow_extensions/outerbounds/plugins/snowpark/snowpark_client.py +45 -18
- metaflow_extensions/outerbounds/plugins/snowpark/snowpark_decorator.py +18 -9
- metaflow_extensions/outerbounds/plugins/snowpark/snowpark_job.py +10 -4
- metaflow_extensions/outerbounds/plugins/torchtune/__init__.py +163 -0
- metaflow_extensions/outerbounds/plugins/vllm/__init__.py +255 -0
- metaflow_extensions/outerbounds/plugins/vllm/constants.py +1 -0
- metaflow_extensions/outerbounds/plugins/vllm/exceptions.py +1 -0
- metaflow_extensions/outerbounds/plugins/vllm/status_card.py +352 -0
- metaflow_extensions/outerbounds/plugins/vllm/vllm_manager.py +621 -0
- metaflow_extensions/outerbounds/remote_config.py +46 -9
- metaflow_extensions/outerbounds/toplevel/apps/__init__.py +9 -0
- metaflow_extensions/outerbounds/toplevel/apps/exceptions.py +11 -0
- metaflow_extensions/outerbounds/toplevel/global_aliases_for_metaflow_package.py +86 -2
- metaflow_extensions/outerbounds/toplevel/ob_internal.py +4 -0
- metaflow_extensions/outerbounds/toplevel/plugins/optuna/__init__.py +1 -0
- metaflow_extensions/outerbounds/toplevel/plugins/torchtune/__init__.py +1 -0
- metaflow_extensions/outerbounds/toplevel/plugins/vllm/__init__.py +1 -0
- metaflow_extensions/outerbounds/toplevel/s3_proxy.py +88 -0
- {ob_metaflow_extensions-1.1.151.dist-info → ob_metaflow_extensions-1.6.2.dist-info}/METADATA +2 -2
- ob_metaflow_extensions-1.6.2.dist-info/RECORD +136 -0
- metaflow_extensions/outerbounds/plugins/nim/utilities.py +0 -5
- ob_metaflow_extensions-1.1.151.dist-info/RECORD +0 -74
- {ob_metaflow_extensions-1.1.151.dist-info → ob_metaflow_extensions-1.6.2.dist-info}/WHEEL +0 -0
- {ob_metaflow_extensions-1.1.151.dist-info → ob_metaflow_extensions-1.6.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
$schema: https://json-schema.org/draft/2020-12/schema
|
|
2
|
+
title: CoreConfig
|
|
3
|
+
description: |
|
|
4
|
+
Schema for defining Outerbounds Apps configuration. This schema is what we will end up using on the CLI/programmatic interface.
|
|
5
|
+
How to read this schema:
|
|
6
|
+
1. If the a property has `mutation_behavior` set to `union` then it will allow overrides of values at runtime from the CLI.
|
|
7
|
+
2. If the property has `mutation_behavior`set to `not_allowed` then either the CLI or the config file value will be used (which ever is not None). If the user supplies something in both then an error will be raised.
|
|
8
|
+
3. If a property has `experimental` set to true then a lot its validations may-be skipped and parsing handled somewhere else.
|
|
9
|
+
type: object
|
|
10
|
+
required:
|
|
11
|
+
- name
|
|
12
|
+
- port
|
|
13
|
+
- commands
|
|
14
|
+
properties:
|
|
15
|
+
name:
|
|
16
|
+
description: The name of the app to deploy. (validation applied)
|
|
17
|
+
type: string
|
|
18
|
+
example: myapp
|
|
19
|
+
mutation_behavior: union
|
|
20
|
+
cli_option: --name
|
|
21
|
+
port:
|
|
22
|
+
description: |-
|
|
23
|
+
Port where the app is hosted. When deployed this will be port on which we will deploy the app. (validation applied)
|
|
24
|
+
type: integer
|
|
25
|
+
example: 8000
|
|
26
|
+
mutation_behavior: union
|
|
27
|
+
cli_option: --port
|
|
28
|
+
description:
|
|
29
|
+
description: The description of the app to deploy.
|
|
30
|
+
type: string
|
|
31
|
+
example: This is a description of my app.
|
|
32
|
+
mutation_behavior: union
|
|
33
|
+
cli_option: --description
|
|
34
|
+
app_type:
|
|
35
|
+
description: The User defined type of app to deploy. Its only used for bookkeeping purposes.
|
|
36
|
+
type: string
|
|
37
|
+
example: MyCustomAgent
|
|
38
|
+
mutation_behavior: union
|
|
39
|
+
cli_option: --app-type
|
|
40
|
+
image:
|
|
41
|
+
description: The Docker image to deploy with the App.
|
|
42
|
+
type: string
|
|
43
|
+
example: python:3.10-slim
|
|
44
|
+
mutation_behavior: union
|
|
45
|
+
cli_option: --image
|
|
46
|
+
tags:
|
|
47
|
+
description: The tags of the app to deploy. (validation applied)
|
|
48
|
+
type: array
|
|
49
|
+
items:
|
|
50
|
+
type: string
|
|
51
|
+
example:
|
|
52
|
+
- foo: bar
|
|
53
|
+
- x: y
|
|
54
|
+
mutation_behavior: union
|
|
55
|
+
cli_option: --tag
|
|
56
|
+
secrets:
|
|
57
|
+
description: |-
|
|
58
|
+
Outerbounds integrations to attach to the app. You can use the value you set in the `@secrets` decorator in your code. (validation applied)
|
|
59
|
+
type: array
|
|
60
|
+
items:
|
|
61
|
+
type: string
|
|
62
|
+
example:
|
|
63
|
+
- hf-token
|
|
64
|
+
mutation_behavior: union
|
|
65
|
+
cli_option: --secret
|
|
66
|
+
compute_pools:
|
|
67
|
+
description: A list of compute pools to deploy the app to.
|
|
68
|
+
type: array
|
|
69
|
+
items:
|
|
70
|
+
type: string
|
|
71
|
+
example:
|
|
72
|
+
- default
|
|
73
|
+
- large
|
|
74
|
+
mutation_behavior: union
|
|
75
|
+
cli_option: --compute-pools
|
|
76
|
+
environment:
|
|
77
|
+
description: Environment variables to deploy with the App.
|
|
78
|
+
type: object
|
|
79
|
+
additionalProperties: true
|
|
80
|
+
example:
|
|
81
|
+
DEBUG: true
|
|
82
|
+
DATABASE_CONFIG:
|
|
83
|
+
host: localhost
|
|
84
|
+
port: 5432
|
|
85
|
+
ALLOWED_ORIGINS:
|
|
86
|
+
- http://localhost:3000
|
|
87
|
+
- https://myapp.com
|
|
88
|
+
mutation_behavior: union
|
|
89
|
+
cli_option: --env
|
|
90
|
+
commands:
|
|
91
|
+
description: A list of commands to run the app with.
|
|
92
|
+
type: array
|
|
93
|
+
items:
|
|
94
|
+
type: string
|
|
95
|
+
example:
|
|
96
|
+
- python app.py
|
|
97
|
+
- python app.py --foo bar
|
|
98
|
+
mutation_behavior: not_allowed
|
|
99
|
+
resources:
|
|
100
|
+
title: ResourceConfig
|
|
101
|
+
description: Resource configuration for the app.
|
|
102
|
+
type: object
|
|
103
|
+
required: []
|
|
104
|
+
properties:
|
|
105
|
+
cpu:
|
|
106
|
+
description: CPU requests (validation applied)
|
|
107
|
+
type: string
|
|
108
|
+
default: '1'
|
|
109
|
+
example: 500m
|
|
110
|
+
mutation_behavior: union
|
|
111
|
+
cli_option: --cpu
|
|
112
|
+
memory:
|
|
113
|
+
description: Memory requests (validation applied)
|
|
114
|
+
type: string
|
|
115
|
+
default: 4Gi
|
|
116
|
+
example: 512Mi
|
|
117
|
+
mutation_behavior: union
|
|
118
|
+
cli_option: --memory
|
|
119
|
+
gpu:
|
|
120
|
+
description: GPU requests (validation applied)
|
|
121
|
+
type: string
|
|
122
|
+
example: '1'
|
|
123
|
+
mutation_behavior: union
|
|
124
|
+
cli_option: --gpu
|
|
125
|
+
disk:
|
|
126
|
+
description: Storage disk size. (validation applied)
|
|
127
|
+
type: string
|
|
128
|
+
default: 20Gi
|
|
129
|
+
example: 1Gi
|
|
130
|
+
mutation_behavior: union
|
|
131
|
+
cli_option: --disk
|
|
132
|
+
shared_memory:
|
|
133
|
+
description: Shared memory (validation applied)
|
|
134
|
+
type: string
|
|
135
|
+
example: 1Gi
|
|
136
|
+
mutation_behavior: union
|
|
137
|
+
cli_option: --shared-memory
|
|
138
|
+
mutation_behavior: union
|
|
139
|
+
auth:
|
|
140
|
+
title: AuthConfig
|
|
141
|
+
description: Authentication configuration.
|
|
142
|
+
type: object
|
|
143
|
+
required: []
|
|
144
|
+
properties:
|
|
145
|
+
type:
|
|
146
|
+
description: The type of authentication to use for the app.
|
|
147
|
+
type: string
|
|
148
|
+
default: Browser
|
|
149
|
+
enum:
|
|
150
|
+
- Browser
|
|
151
|
+
- API
|
|
152
|
+
- BrowserAndApi
|
|
153
|
+
example: Browser
|
|
154
|
+
mutation_behavior: union
|
|
155
|
+
cli_option: --auth-type
|
|
156
|
+
public:
|
|
157
|
+
description: Whether the app is public or not.
|
|
158
|
+
type: boolean
|
|
159
|
+
default: true
|
|
160
|
+
example: true
|
|
161
|
+
mutation_behavior: union
|
|
162
|
+
cli_option: --public-access/--private-access
|
|
163
|
+
mutation_behavior: union
|
|
164
|
+
replicas:
|
|
165
|
+
title: ReplicaConfig
|
|
166
|
+
description: Replica configuration.
|
|
167
|
+
type: object
|
|
168
|
+
required: []
|
|
169
|
+
properties:
|
|
170
|
+
fixed:
|
|
171
|
+
description: |-
|
|
172
|
+
The fixed number of replicas to deploy the app with. If min and max are set, this will raise an error.
|
|
173
|
+
type: integer
|
|
174
|
+
example: 1
|
|
175
|
+
mutation_behavior: union
|
|
176
|
+
cli_option: --fixed-replicas
|
|
177
|
+
min:
|
|
178
|
+
description: The minimum number of replicas to deploy the app with.
|
|
179
|
+
type: integer
|
|
180
|
+
example: 1
|
|
181
|
+
mutation_behavior: union
|
|
182
|
+
cli_option: --min-replicas
|
|
183
|
+
max:
|
|
184
|
+
description: The maximum number of replicas to deploy the app with.
|
|
185
|
+
type: integer
|
|
186
|
+
example: 10
|
|
187
|
+
mutation_behavior: union
|
|
188
|
+
cli_option: --max-replicas
|
|
189
|
+
scaling_policy:
|
|
190
|
+
title: ScalingPolicyConfig
|
|
191
|
+
description: |-
|
|
192
|
+
Policies for autoscaling replicas. Available policies:
|
|
193
|
+
- Request based Autoscaling (rpm)
|
|
194
|
+
type: object
|
|
195
|
+
required: []
|
|
196
|
+
properties:
|
|
197
|
+
rpm:
|
|
198
|
+
description: |-
|
|
199
|
+
Scale up replicas when the requests per minute crosses this threshold. If nothing is provided and the replicas.max and replicas.min is set then the default rpm would be 60.
|
|
200
|
+
type: integer
|
|
201
|
+
default: 60
|
|
202
|
+
mutation_behavior: union
|
|
203
|
+
cli_option: --scaling-rpm
|
|
204
|
+
mutation_behavior: union
|
|
205
|
+
mutation_behavior: union
|
|
206
|
+
dependencies:
|
|
207
|
+
title: DependencyConfig
|
|
208
|
+
description: Dependency configuration.
|
|
209
|
+
type: object
|
|
210
|
+
required: []
|
|
211
|
+
properties:
|
|
212
|
+
from_requirements_file:
|
|
213
|
+
description: The path to the requirements.txt file to attach to the app.
|
|
214
|
+
type: string
|
|
215
|
+
example: requirements.txt
|
|
216
|
+
mutation_behavior: not_allowed
|
|
217
|
+
cli_option: --dep-from-requirements
|
|
218
|
+
from_pyproject_toml:
|
|
219
|
+
description: The path to the pyproject.toml file to attach to the app.
|
|
220
|
+
type: string
|
|
221
|
+
example: pyproject.toml
|
|
222
|
+
mutation_behavior: not_allowed
|
|
223
|
+
cli_option: --dep-from-pyproject
|
|
224
|
+
python:
|
|
225
|
+
description: The Python version to use for the app.
|
|
226
|
+
type: string
|
|
227
|
+
example: '3.10'
|
|
228
|
+
mutation_behavior: union
|
|
229
|
+
cli_option: --python
|
|
230
|
+
pypi:
|
|
231
|
+
description: |-
|
|
232
|
+
A dictionary of pypi dependencies to attach to the app. The key is the package name and the value is the version.
|
|
233
|
+
type: object
|
|
234
|
+
additionalProperties: true
|
|
235
|
+
example:
|
|
236
|
+
numpy: 1.23.0
|
|
237
|
+
pandas: ''
|
|
238
|
+
mutation_behavior: not_allowed
|
|
239
|
+
cli_option: --pypi
|
|
240
|
+
conda:
|
|
241
|
+
description: |-
|
|
242
|
+
A dictionary of conda dependencies to attach to the app. The key is the package name and the value is the version.
|
|
243
|
+
type: object
|
|
244
|
+
additionalProperties: true
|
|
245
|
+
example:
|
|
246
|
+
numpy: 1.23.0
|
|
247
|
+
pandas: ''
|
|
248
|
+
mutation_behavior: not_allowed
|
|
249
|
+
cli_option: --conda
|
|
250
|
+
mutation_behavior: union
|
|
251
|
+
package:
|
|
252
|
+
title: PackageConfig
|
|
253
|
+
description: Package configuration.
|
|
254
|
+
type: object
|
|
255
|
+
required: []
|
|
256
|
+
properties:
|
|
257
|
+
src_paths:
|
|
258
|
+
description: The path to the source code to deploy with the App.
|
|
259
|
+
type: array
|
|
260
|
+
items:
|
|
261
|
+
type: string
|
|
262
|
+
example:
|
|
263
|
+
- ./
|
|
264
|
+
mutation_behavior: union
|
|
265
|
+
cli_option: --package-src-path
|
|
266
|
+
suffixes:
|
|
267
|
+
description: A list of suffixes to add to the source code to deploy with the App.
|
|
268
|
+
type: array
|
|
269
|
+
items:
|
|
270
|
+
type: string
|
|
271
|
+
example:
|
|
272
|
+
- .py
|
|
273
|
+
- .ipynb
|
|
274
|
+
mutation_behavior: union
|
|
275
|
+
cli_option: --package-suffixes
|
|
276
|
+
mutation_behavior: union
|
|
277
|
+
no_deps:
|
|
278
|
+
description: Do not bake any dependencies. Directly used the image provided
|
|
279
|
+
type: boolean
|
|
280
|
+
default: false
|
|
281
|
+
mutation_behavior: union
|
|
282
|
+
cli_option: --no-deps
|
|
283
|
+
force_upgrade:
|
|
284
|
+
description: Force upgrade the app even if it is currently being upgraded.
|
|
285
|
+
type: boolean
|
|
286
|
+
default: false
|
|
287
|
+
mutation_behavior: union
|
|
288
|
+
cli_option: --force-upgrade
|
|
289
|
+
persistence:
|
|
290
|
+
description: The persistence mode to deploy the app with. (validation applied)
|
|
291
|
+
type: string
|
|
292
|
+
default: none
|
|
293
|
+
enum:
|
|
294
|
+
- none
|
|
295
|
+
- postgres
|
|
296
|
+
example: postgres
|
|
297
|
+
experimental: true
|
|
298
|
+
mutation_behavior: union
|
|
299
|
+
cli_option: --persistence
|
|
300
|
+
project:
|
|
301
|
+
description: The project name to deploy the app to.
|
|
302
|
+
type: string
|
|
303
|
+
example: my-project
|
|
304
|
+
experimental: true
|
|
305
|
+
mutation_behavior: union
|
|
306
|
+
cli_option: --project
|
|
307
|
+
branch:
|
|
308
|
+
description: The branch name to deploy the app to.
|
|
309
|
+
type: string
|
|
310
|
+
example: main
|
|
311
|
+
experimental: true
|
|
312
|
+
mutation_behavior: union
|
|
313
|
+
cli_option: --branch
|
|
314
|
+
models:
|
|
315
|
+
type: array
|
|
316
|
+
items:
|
|
317
|
+
type: string
|
|
318
|
+
example:
|
|
319
|
+
- asset_id: model-123
|
|
320
|
+
asset_instance_id: instance-456
|
|
321
|
+
experimental: true
|
|
322
|
+
mutation_behavior: union
|
|
323
|
+
data:
|
|
324
|
+
type: array
|
|
325
|
+
items:
|
|
326
|
+
type: string
|
|
327
|
+
example:
|
|
328
|
+
- asset_id: data-789
|
|
329
|
+
asset_instance_id: instance-101
|
|
330
|
+
experimental: true
|
|
331
|
+
mutation_behavior: union
|
|
332
|
+
generate_static_url:
|
|
333
|
+
description: Generate a static URL for the app based on its name.
|
|
334
|
+
type: boolean
|
|
335
|
+
default: false
|
|
336
|
+
mutation_behavior: union
|
|
337
|
+
cli_option: --generate-static-url
|
|
@@ -0,0 +1,115 @@
|
|
|
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 internal_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", {}) or {}
|
|
77
|
+
|
|
78
|
+
if "conda" in dependencies:
|
|
79
|
+
conda_packages = dependencies.get("conda", {}) or {}
|
|
80
|
+
if "python" in dependencies:
|
|
81
|
+
python_version = dependencies.get("python", python_version) or 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 chance it is none, FB will fart.
|
|
99
|
+
fb_response = internal_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
|
+
)
|