wandb 0.17.0rc1__py3-none-macosx_11_0_arm64.whl → 0.17.1__py3-none-macosx_11_0_arm64.whl
Sign up to get free protection for your applications and to get access to all the features.
- wandb/__init__.py +1 -2
- wandb/apis/importers/internals/internal.py +0 -1
- wandb/apis/importers/wandb.py +12 -7
- wandb/apis/internal.py +0 -3
- wandb/apis/public/api.py +213 -79
- wandb/apis/public/artifacts.py +335 -100
- wandb/apis/public/files.py +9 -9
- wandb/apis/public/jobs.py +16 -4
- wandb/apis/public/projects.py +26 -28
- wandb/apis/public/query_generator.py +1 -1
- wandb/apis/public/runs.py +163 -65
- wandb/apis/public/sweeps.py +2 -2
- wandb/apis/reports/__init__.py +1 -7
- wandb/apis/reports/v1/__init__.py +5 -27
- wandb/apis/reports/v2/__init__.py +7 -19
- wandb/apis/workspaces/__init__.py +8 -0
- wandb/beta/workflows.py +8 -3
- wandb/bin/apple_gpu_stats +0 -0
- wandb/bin/wandb-core +0 -0
- wandb/cli/cli.py +131 -59
- wandb/data_types.py +6 -3
- wandb/docker/__init__.py +2 -2
- wandb/env.py +3 -3
- wandb/errors/term.py +10 -2
- wandb/filesync/step_checksum.py +1 -4
- wandb/filesync/step_prepare.py +4 -24
- wandb/filesync/step_upload.py +5 -107
- wandb/filesync/upload_job.py +0 -76
- wandb/integration/gym/__init__.py +35 -15
- wandb/integration/huggingface/resolver.py +2 -2
- wandb/integration/keras/callbacks/metrics_logger.py +1 -1
- wandb/integration/keras/keras.py +1 -1
- wandb/integration/openai/fine_tuning.py +21 -3
- wandb/integration/prodigy/prodigy.py +1 -1
- wandb/jupyter.py +16 -17
- wandb/old/summary.py +1 -1
- wandb/plot/confusion_matrix.py +1 -1
- wandb/plot/pr_curve.py +2 -1
- wandb/plot/roc_curve.py +2 -1
- wandb/{plots → plot}/utils.py +13 -25
- wandb/proto/v3/wandb_internal_pb2.py +54 -54
- wandb/proto/v3/wandb_settings_pb2.py +2 -2
- wandb/proto/v3/wandb_telemetry_pb2.py +10 -10
- wandb/proto/v4/wandb_internal_pb2.py +54 -54
- wandb/proto/v4/wandb_settings_pb2.py +2 -2
- wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
- wandb/proto/v5/wandb_base_pb2.py +30 -0
- wandb/proto/v5/wandb_internal_pb2.py +355 -0
- wandb/proto/v5/wandb_server_pb2.py +63 -0
- wandb/proto/v5/wandb_settings_pb2.py +45 -0
- wandb/proto/v5/wandb_telemetry_pb2.py +41 -0
- wandb/proto/wandb_base_pb2.py +2 -0
- wandb/proto/wandb_deprecated.py +9 -1
- wandb/proto/wandb_generate_deprecated.py +34 -0
- wandb/proto/{wandb_internal_codegen.py → wandb_generate_proto.py} +1 -35
- wandb/proto/wandb_internal_pb2.py +2 -0
- wandb/proto/wandb_server_pb2.py +2 -0
- wandb/proto/wandb_settings_pb2.py +2 -0
- wandb/proto/wandb_telemetry_pb2.py +2 -0
- wandb/sdk/artifacts/artifact.py +68 -22
- wandb/sdk/artifacts/artifact_manifest.py +1 -1
- wandb/sdk/artifacts/artifact_manifest_entry.py +6 -3
- wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +1 -1
- wandb/sdk/artifacts/artifact_saver.py +1 -10
- wandb/sdk/artifacts/storage_handlers/local_file_handler.py +6 -2
- wandb/sdk/artifacts/storage_handlers/multi_handler.py +1 -1
- wandb/sdk/artifacts/storage_handlers/tracking_handler.py +6 -4
- wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +2 -42
- wandb/sdk/artifacts/storage_policy.py +1 -12
- wandb/sdk/data_types/_dtypes.py +8 -8
- wandb/sdk/data_types/image.py +2 -2
- wandb/sdk/data_types/video.py +5 -3
- wandb/sdk/integration_utils/data_logging.py +5 -5
- wandb/sdk/interface/interface.py +14 -1
- wandb/sdk/interface/interface_shared.py +1 -1
- wandb/sdk/internal/file_pusher.py +2 -5
- wandb/sdk/internal/file_stream.py +6 -19
- wandb/sdk/internal/internal_api.py +148 -136
- wandb/sdk/internal/job_builder.py +208 -136
- wandb/sdk/internal/progress.py +0 -28
- wandb/sdk/internal/sender.py +102 -39
- wandb/sdk/internal/settings_static.py +8 -1
- wandb/sdk/internal/system/assets/trainium.py +3 -3
- wandb/sdk/internal/system/system_info.py +4 -2
- wandb/sdk/internal/update.py +1 -1
- wandb/sdk/launch/__init__.py +9 -1
- wandb/sdk/launch/_launch.py +4 -24
- wandb/sdk/launch/_launch_add.py +1 -3
- wandb/sdk/launch/_project_spec.py +187 -225
- wandb/sdk/launch/agent/agent.py +59 -19
- wandb/sdk/launch/agent/config.py +0 -3
- wandb/sdk/launch/builder/abstract.py +68 -1
- wandb/sdk/launch/builder/build.py +165 -576
- wandb/sdk/launch/builder/context_manager.py +235 -0
- wandb/sdk/launch/builder/docker_builder.py +7 -23
- wandb/sdk/launch/builder/kaniko_builder.py +12 -25
- wandb/sdk/launch/builder/templates/dockerfile.py +92 -0
- wandb/sdk/launch/create_job.py +51 -45
- wandb/sdk/launch/environment/aws_environment.py +26 -1
- wandb/sdk/launch/inputs/files.py +148 -0
- wandb/sdk/launch/inputs/internal.py +224 -0
- wandb/sdk/launch/inputs/manage.py +95 -0
- wandb/sdk/launch/registry/google_artifact_registry.py +1 -1
- wandb/sdk/launch/runner/abstract.py +2 -2
- wandb/sdk/launch/runner/kubernetes_monitor.py +45 -12
- wandb/sdk/launch/runner/kubernetes_runner.py +6 -8
- wandb/sdk/launch/runner/local_container.py +2 -3
- wandb/sdk/launch/runner/local_process.py +8 -29
- wandb/sdk/launch/runner/sagemaker_runner.py +20 -14
- wandb/sdk/launch/runner/vertex_runner.py +8 -7
- wandb/sdk/launch/sweeps/scheduler.py +5 -3
- wandb/sdk/launch/sweeps/scheduler_sweep.py +1 -1
- wandb/sdk/launch/sweeps/utils.py +4 -4
- wandb/sdk/launch/utils.py +16 -138
- wandb/sdk/lib/_settings_toposort_generated.py +2 -5
- wandb/sdk/lib/apikey.py +4 -2
- wandb/sdk/lib/config_util.py +3 -3
- wandb/sdk/lib/import_hooks.py +1 -1
- wandb/sdk/lib/proto_util.py +22 -1
- wandb/sdk/lib/redirect.py +20 -15
- wandb/sdk/lib/tracelog.py +1 -1
- wandb/sdk/service/service.py +2 -1
- wandb/sdk/service/streams.py +5 -5
- wandb/sdk/wandb_init.py +25 -59
- wandb/sdk/wandb_login.py +28 -25
- wandb/sdk/wandb_run.py +123 -53
- wandb/sdk/wandb_settings.py +33 -64
- wandb/sdk/wandb_setup.py +1 -1
- wandb/sdk/wandb_watch.py +1 -1
- wandb/sklearn/plot/classifier.py +10 -12
- wandb/sklearn/plot/clusterer.py +1 -1
- wandb/sync/sync.py +2 -2
- wandb/testing/relay.py +32 -17
- wandb/util.py +36 -37
- wandb/wandb_agent.py +3 -3
- wandb/wandb_controller.py +5 -4
- {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/METADATA +8 -10
- {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/RECORD +141 -163
- {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/WHEEL +1 -1
- wandb/apis/reports/v1/_blocks.py +0 -1406
- wandb/apis/reports/v1/_helpers.py +0 -70
- wandb/apis/reports/v1/_panels.py +0 -1282
- wandb/apis/reports/v1/_templates.py +0 -478
- wandb/apis/reports/v1/blocks.py +0 -27
- wandb/apis/reports/v1/helpers.py +0 -2
- wandb/apis/reports/v1/mutations.py +0 -66
- wandb/apis/reports/v1/panels.py +0 -17
- wandb/apis/reports/v1/report.py +0 -268
- wandb/apis/reports/v1/runset.py +0 -144
- wandb/apis/reports/v1/templates.py +0 -7
- wandb/apis/reports/v1/util.py +0 -406
- wandb/apis/reports/v1/validators.py +0 -131
- wandb/apis/reports/v2/blocks.py +0 -25
- wandb/apis/reports/v2/expr_parsing.py +0 -257
- wandb/apis/reports/v2/gql.py +0 -68
- wandb/apis/reports/v2/interface.py +0 -1911
- wandb/apis/reports/v2/internal.py +0 -867
- wandb/apis/reports/v2/metrics.py +0 -6
- wandb/apis/reports/v2/panels.py +0 -15
- wandb/catboost/__init__.py +0 -9
- wandb/fastai/__init__.py +0 -9
- wandb/keras/__init__.py +0 -19
- wandb/lightgbm/__init__.py +0 -9
- wandb/plots/__init__.py +0 -6
- wandb/plots/explain_text.py +0 -36
- wandb/plots/heatmap.py +0 -81
- wandb/plots/named_entity.py +0 -43
- wandb/plots/part_of_speech.py +0 -50
- wandb/plots/plot_definitions.py +0 -768
- wandb/plots/precision_recall.py +0 -121
- wandb/plots/roc.py +0 -103
- wandb/sacred/__init__.py +0 -3
- wandb/xgboost/__init__.py +0 -9
- {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/entry_points.txt +0 -0
- {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,235 @@
|
|
1
|
+
import logging
|
2
|
+
import os
|
3
|
+
import shutil
|
4
|
+
import tempfile
|
5
|
+
from typing import Tuple
|
6
|
+
|
7
|
+
from wandb.sdk.launch._project_spec import LaunchProject
|
8
|
+
from wandb.sdk.launch.builder.build import image_tag_from_dockerfile_and_source
|
9
|
+
from wandb.sdk.launch.errors import LaunchError
|
10
|
+
from wandb.sdk.launch.utils import get_current_python_version
|
11
|
+
|
12
|
+
from .build import (
|
13
|
+
_WANDB_DOCKERFILE_NAME,
|
14
|
+
get_base_setup,
|
15
|
+
get_docker_user,
|
16
|
+
get_entrypoint_setup,
|
17
|
+
get_requirements_section,
|
18
|
+
get_user_setup,
|
19
|
+
)
|
20
|
+
from .templates.dockerfile import DOCKERFILE_TEMPLATE
|
21
|
+
|
22
|
+
_logger = logging.getLogger(__name__)
|
23
|
+
|
24
|
+
|
25
|
+
class BuildContextManager:
|
26
|
+
"""Creates a build context for a container image from job source code.
|
27
|
+
|
28
|
+
The dockerfile and build context may be specified by the job itself. If not,
|
29
|
+
the behavior for creating the build context is as follows:
|
30
|
+
|
31
|
+
- If a Dockerfile.wandb is found adjacent to the entrypoint, the directory
|
32
|
+
containing the entrypoint is used as the build context and Dockerfile.wandb
|
33
|
+
is used as the Dockerfile.
|
34
|
+
|
35
|
+
- If `override_dockerfile` is set on the LaunchProject, the directory
|
36
|
+
containing the Dockerfile is used as the build context and the Dockerfile
|
37
|
+
is used as the Dockerfile. `override_dockerfile` can be set in a launch
|
38
|
+
spec via the `-D` flag to `wandb launch` or in the `overrides` section
|
39
|
+
of the launch drawer.
|
40
|
+
|
41
|
+
- If no dockerfile is set, a Dockerfile is generated from the job's
|
42
|
+
requirements and entrypoint.
|
43
|
+
"""
|
44
|
+
|
45
|
+
def __init__(self, launch_project: LaunchProject):
|
46
|
+
"""Initialize a BuildContextManager.
|
47
|
+
|
48
|
+
Arguments:
|
49
|
+
launch_project: The launch project.
|
50
|
+
"""
|
51
|
+
self._launch_project = launch_project
|
52
|
+
assert self._launch_project.project_dir is not None
|
53
|
+
self._directory = tempfile.mkdtemp()
|
54
|
+
|
55
|
+
def _generate_dockerfile(self, builder_type: str) -> str:
|
56
|
+
"""Generate a Dockerfile for the container image.
|
57
|
+
|
58
|
+
Arguments:
|
59
|
+
builder_type: The type of builder to use. One of "docker" or "kaniko".
|
60
|
+
|
61
|
+
Returns:
|
62
|
+
The contents of the Dockerfile.
|
63
|
+
"""
|
64
|
+
launch_project = self._launch_project
|
65
|
+
entry_point = (
|
66
|
+
launch_project.override_entrypoint or launch_project.get_job_entry_point()
|
67
|
+
)
|
68
|
+
|
69
|
+
# get python versions truncated to major.minor to ensure image availability
|
70
|
+
if launch_project.python_version:
|
71
|
+
spl = launch_project.python_version.split(".")[:2]
|
72
|
+
py_version, py_major = (".".join(spl), spl[0])
|
73
|
+
else:
|
74
|
+
py_version, py_major = get_current_python_version()
|
75
|
+
|
76
|
+
python_build_image = (
|
77
|
+
f"python:{py_version}" # use full python image for package installation
|
78
|
+
)
|
79
|
+
requirements_section = get_requirements_section(
|
80
|
+
launch_project, self._directory, builder_type
|
81
|
+
)
|
82
|
+
# ----- stage 2: base -----
|
83
|
+
python_base_setup = get_base_setup(launch_project, py_version, py_major)
|
84
|
+
|
85
|
+
# set up user info
|
86
|
+
username, userid = get_docker_user(launch_project, launch_project.resource)
|
87
|
+
user_setup = get_user_setup(username, userid, launch_project.resource)
|
88
|
+
workdir = f"/home/{username}"
|
89
|
+
|
90
|
+
assert entry_point is not None
|
91
|
+
entrypoint_section = get_entrypoint_setup(entry_point)
|
92
|
+
|
93
|
+
dockerfile_contents = DOCKERFILE_TEMPLATE.format(
|
94
|
+
py_build_image=python_build_image,
|
95
|
+
requirements_section=requirements_section,
|
96
|
+
base_setup=python_base_setup,
|
97
|
+
uid=userid,
|
98
|
+
user_setup=user_setup,
|
99
|
+
workdir=workdir,
|
100
|
+
entrypoint_section=entrypoint_section,
|
101
|
+
)
|
102
|
+
return dockerfile_contents
|
103
|
+
|
104
|
+
def create_build_context(self, builder_type: str) -> Tuple[str, str]:
|
105
|
+
"""Create the build context for the container image.
|
106
|
+
|
107
|
+
Returns:
|
108
|
+
A pair of str: the path to the build context locally and the image
|
109
|
+
tag computed from the Dockerfile.
|
110
|
+
"""
|
111
|
+
entrypoint = (
|
112
|
+
self._launch_project.get_job_entry_point()
|
113
|
+
or self._launch_project.override_entrypoint
|
114
|
+
)
|
115
|
+
assert entrypoint is not None
|
116
|
+
assert entrypoint.name is not None
|
117
|
+
assert self._launch_project.project_dir is not None
|
118
|
+
|
119
|
+
# we use that as the build context.
|
120
|
+
build_context_root_dir = self._launch_project.project_dir
|
121
|
+
job_build_context = self._launch_project.job_build_context
|
122
|
+
if job_build_context:
|
123
|
+
full_path = os.path.join(build_context_root_dir, job_build_context)
|
124
|
+
if not os.path.exists(full_path):
|
125
|
+
raise LaunchError(f"Build context does not exist at {full_path}")
|
126
|
+
build_context_root_dir = full_path
|
127
|
+
|
128
|
+
# This is the case where the user specifies a Dockerfile to use.
|
129
|
+
# We use the directory containing the Dockerfile as the build context.
|
130
|
+
override_dockerfile = self._launch_project.override_dockerfile
|
131
|
+
if override_dockerfile:
|
132
|
+
full_path = os.path.join(
|
133
|
+
build_context_root_dir,
|
134
|
+
override_dockerfile,
|
135
|
+
)
|
136
|
+
if not os.path.exists(full_path):
|
137
|
+
raise LaunchError(f"Dockerfile does not exist at {full_path}")
|
138
|
+
shutil.copytree(
|
139
|
+
build_context_root_dir,
|
140
|
+
self._directory,
|
141
|
+
symlinks=True,
|
142
|
+
dirs_exist_ok=True,
|
143
|
+
ignore=shutil.ignore_patterns("fsmonitor--daemon.ipc"),
|
144
|
+
)
|
145
|
+
shutil.copy(
|
146
|
+
full_path,
|
147
|
+
os.path.join(self._directory, _WANDB_DOCKERFILE_NAME),
|
148
|
+
)
|
149
|
+
return self._directory, image_tag_from_dockerfile_and_source(
|
150
|
+
self._launch_project, open(full_path).read()
|
151
|
+
)
|
152
|
+
|
153
|
+
# If the job specifies a Dockerfile, we use that as the Dockerfile.
|
154
|
+
job_dockerfile = self._launch_project.job_dockerfile
|
155
|
+
if job_dockerfile:
|
156
|
+
dockerfile_path = os.path.join(build_context_root_dir, job_dockerfile)
|
157
|
+
if not os.path.exists(dockerfile_path):
|
158
|
+
raise LaunchError(f"Dockerfile does not exist at {dockerfile_path}")
|
159
|
+
shutil.copytree(
|
160
|
+
build_context_root_dir,
|
161
|
+
self._directory,
|
162
|
+
symlinks=True,
|
163
|
+
dirs_exist_ok=True,
|
164
|
+
ignore=shutil.ignore_patterns("fsmonitor--daemon.ipc"),
|
165
|
+
)
|
166
|
+
shutil.copy(
|
167
|
+
dockerfile_path,
|
168
|
+
os.path.join(self._directory, _WANDB_DOCKERFILE_NAME),
|
169
|
+
)
|
170
|
+
return self._directory, image_tag_from_dockerfile_and_source(
|
171
|
+
self._launch_project, open(dockerfile_path).read()
|
172
|
+
)
|
173
|
+
|
174
|
+
# This is the case where we find Dockerfile.wandb adjacent to the
|
175
|
+
# entrypoint. We use the entrypoint directory as the build context.
|
176
|
+
entrypoint_dir = os.path.dirname(entrypoint.name)
|
177
|
+
if entrypoint_dir:
|
178
|
+
path = os.path.join(
|
179
|
+
build_context_root_dir,
|
180
|
+
entrypoint_dir,
|
181
|
+
_WANDB_DOCKERFILE_NAME,
|
182
|
+
)
|
183
|
+
else:
|
184
|
+
path = os.path.join(build_context_root_dir, _WANDB_DOCKERFILE_NAME)
|
185
|
+
if os.path.exists(
|
186
|
+
path
|
187
|
+
): # We found a Dockerfile.wandb adjacent to the entrypoint.
|
188
|
+
shutil.copytree(
|
189
|
+
os.path.dirname(path),
|
190
|
+
self._directory,
|
191
|
+
symlinks=True,
|
192
|
+
dirs_exist_ok=True,
|
193
|
+
ignore=shutil.ignore_patterns("fsmonitor--daemon.ipc"),
|
194
|
+
)
|
195
|
+
# TODO: remove this once we make things more explicit for users
|
196
|
+
if entrypoint_dir:
|
197
|
+
new_path = os.path.basename(entrypoint.name)
|
198
|
+
entrypoint = self._launch_project.get_job_entry_point()
|
199
|
+
if entrypoint is not None:
|
200
|
+
entrypoint.update_entrypoint_path(new_path)
|
201
|
+
with open(path) as f:
|
202
|
+
docker_file_contents = f.read()
|
203
|
+
return self._directory, image_tag_from_dockerfile_and_source(
|
204
|
+
self._launch_project, docker_file_contents
|
205
|
+
)
|
206
|
+
|
207
|
+
# This is the case where we use our own Dockerfile template. We move
|
208
|
+
# the user code into a src directory in the build context.
|
209
|
+
dst_path = os.path.join(self._directory, "src")
|
210
|
+
assert self._launch_project.project_dir is not None
|
211
|
+
shutil.copytree(
|
212
|
+
src=self._launch_project.project_dir,
|
213
|
+
dst=dst_path,
|
214
|
+
symlinks=True,
|
215
|
+
ignore=shutil.ignore_patterns("fsmonitor--daemon.ipc"),
|
216
|
+
)
|
217
|
+
shutil.copy(
|
218
|
+
os.path.join(os.path.dirname(__file__), "templates", "_wandb_bootstrap.py"),
|
219
|
+
os.path.join(self._directory),
|
220
|
+
)
|
221
|
+
if self._launch_project.python_version:
|
222
|
+
runtime_path = os.path.join(dst_path, "runtime.txt")
|
223
|
+
with open(runtime_path, "w") as fp:
|
224
|
+
fp.write(f"python-{self._launch_project.python_version}")
|
225
|
+
|
226
|
+
# TODO: we likely don't need to pass the whole git repo into the container
|
227
|
+
# with open(os.path.join(directory, ".dockerignore"), "w") as f:
|
228
|
+
# f.write("**/.git")
|
229
|
+
with open(os.path.join(self._directory, _WANDB_DOCKERFILE_NAME), "w") as handle:
|
230
|
+
docker_file_contents = self._generate_dockerfile(builder_type=builder_type)
|
231
|
+
handle.write(docker_file_contents)
|
232
|
+
image_tag = image_tag_from_dockerfile_and_source(
|
233
|
+
self._launch_project, docker_file_contents
|
234
|
+
)
|
235
|
+
return self._directory, image_tag
|
@@ -7,8 +7,7 @@ from typing import Any, Dict, Optional
|
|
7
7
|
import wandb
|
8
8
|
import wandb.docker as docker
|
9
9
|
from wandb.sdk.launch.agent.job_status_tracker import JobAndRunStatusTracker
|
10
|
-
from wandb.sdk.launch.builder.abstract import AbstractBuilder
|
11
|
-
from wandb.sdk.launch.builder.build import registry_from_uri
|
10
|
+
from wandb.sdk.launch.builder.abstract import AbstractBuilder, registry_from_uri
|
12
11
|
from wandb.sdk.launch.environment.abstract import AbstractEnvironment
|
13
12
|
from wandb.sdk.launch.registry.abstract import AbstractRegistry
|
14
13
|
|
@@ -21,13 +20,8 @@ from ..utils import (
|
|
21
20
|
event_loop_thread_exec,
|
22
21
|
warn_failed_packages_from_build_logs,
|
23
22
|
)
|
24
|
-
from .build import
|
25
|
-
|
26
|
-
_create_docker_build_ctx,
|
27
|
-
generate_dockerfile,
|
28
|
-
image_tag_from_dockerfile_and_source,
|
29
|
-
validate_docker_installation,
|
30
|
-
)
|
23
|
+
from .build import _WANDB_DOCKERFILE_NAME, validate_docker_installation
|
24
|
+
from .context_manager import BuildContextManager
|
31
25
|
|
32
26
|
_logger = logging.getLogger(__name__)
|
33
27
|
|
@@ -41,7 +35,6 @@ class DockerBuilder(AbstractBuilder):
|
|
41
35
|
"""
|
42
36
|
|
43
37
|
builder_type = "docker"
|
44
|
-
base_image = "python:3.8"
|
45
38
|
target_platform = "linux/amd64"
|
46
39
|
|
47
40
|
def __init__(
|
@@ -124,17 +117,11 @@ class DockerBuilder(AbstractBuilder):
|
|
124
117
|
await self.verify()
|
125
118
|
await self.login()
|
126
119
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
runner_type=launch_project.resource,
|
131
|
-
builder_type="docker",
|
132
|
-
dockerfile=launch_project.override_dockerfile,
|
133
|
-
)
|
134
|
-
|
135
|
-
image_tag = image_tag_from_dockerfile_and_source(launch_project, dockerfile_str)
|
136
|
-
|
120
|
+
build_context_manager = BuildContextManager(launch_project=launch_project)
|
121
|
+
build_ctx_path, image_tag = build_context_manager.create_build_context("docker")
|
122
|
+
dockerfile = os.path.join(build_ctx_path, _WANDB_DOCKERFILE_NAME)
|
137
123
|
repository = None if not self.registry else await self.registry.get_repo_uri()
|
124
|
+
|
138
125
|
# if repo is set, use the repo name as the image name
|
139
126
|
if repository:
|
140
127
|
image_uri = f"{repository}:{image_tag}"
|
@@ -152,9 +139,6 @@ class DockerBuilder(AbstractBuilder):
|
|
152
139
|
_logger.info(
|
153
140
|
f"image {image_uri} does not already exist in repository, building."
|
154
141
|
)
|
155
|
-
|
156
|
-
build_ctx_path = _create_docker_build_ctx(launch_project, dockerfile_str)
|
157
|
-
dockerfile = os.path.join(build_ctx_path, _WANDB_DOCKERFILE_NAME)
|
158
142
|
try:
|
159
143
|
output = await event_loop_thread_exec(docker.build)(
|
160
144
|
tags=[image_uri],
|
@@ -13,8 +13,7 @@ from typing import Any, Dict, Optional
|
|
13
13
|
|
14
14
|
import wandb
|
15
15
|
from wandb.sdk.launch.agent.job_status_tracker import JobAndRunStatusTracker
|
16
|
-
from wandb.sdk.launch.builder.abstract import AbstractBuilder
|
17
|
-
from wandb.sdk.launch.builder.build import registry_from_uri
|
16
|
+
from wandb.sdk.launch.builder.abstract import AbstractBuilder, registry_from_uri
|
18
17
|
from wandb.sdk.launch.environment.abstract import AbstractEnvironment
|
19
18
|
from wandb.sdk.launch.environment.azure_environment import AzureEnvironment
|
20
19
|
from wandb.sdk.launch.registry.abstract import AbstractRegistry
|
@@ -32,12 +31,8 @@ from ..utils import (
|
|
32
31
|
get_kube_context_and_api_client,
|
33
32
|
warn_failed_packages_from_build_logs,
|
34
33
|
)
|
35
|
-
from .build import
|
36
|
-
|
37
|
-
_create_docker_build_ctx,
|
38
|
-
generate_dockerfile,
|
39
|
-
image_tag_from_dockerfile_and_source,
|
40
|
-
)
|
34
|
+
from .build import _WANDB_DOCKERFILE_NAME
|
35
|
+
from .context_manager import BuildContextManager
|
41
36
|
|
42
37
|
get_module(
|
43
38
|
"kubernetes_asyncio",
|
@@ -261,17 +256,13 @@ class KanikoBuilder(AbstractBuilder):
|
|
261
256
|
job_tracker: Optional[JobAndRunStatusTracker] = None,
|
262
257
|
) -> str:
|
263
258
|
await self.verify()
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
runner_type=launch_project.resource,
|
269
|
-
builder_type="kaniko",
|
270
|
-
dockerfile=launch_project.override_dockerfile,
|
271
|
-
)
|
272
|
-
image_tag = image_tag_from_dockerfile_and_source(launch_project, dockerfile_str)
|
259
|
+
|
260
|
+
build_contex_manager = BuildContextManager(launch_project=launch_project)
|
261
|
+
context_path, image_tag = build_contex_manager.create_build_context("kaniko")
|
262
|
+
run_id = launch_project.run_id
|
273
263
|
repo_uri = await self.registry.get_repo_uri()
|
274
264
|
image_uri = repo_uri + ":" + image_tag
|
265
|
+
|
275
266
|
if (
|
276
267
|
not launch_project.build_required()
|
277
268
|
and await self.registry.check_image_exists(image_uri)
|
@@ -279,14 +270,10 @@ class KanikoBuilder(AbstractBuilder):
|
|
279
270
|
return image_uri
|
280
271
|
|
281
272
|
_logger.info(f"Building image {image_uri}...")
|
282
|
-
|
283
|
-
context_path = _create_docker_build_ctx(launch_project, dockerfile_str)
|
284
|
-
run_id = launch_project.run_id
|
285
|
-
|
286
273
|
_, api_client = await get_kube_context_and_api_client(
|
287
274
|
kubernetes, launch_project.resource_args
|
288
275
|
)
|
289
|
-
# TODO: use same client as
|
276
|
+
# TODO: use same client as kubernetes_runner.py
|
290
277
|
batch_v1 = client.BatchV1Api(api_client)
|
291
278
|
core_v1 = client.CoreV1Api(api_client)
|
292
279
|
|
@@ -492,8 +479,8 @@ class KanikoBuilder(AbstractBuilder):
|
|
492
479
|
}
|
493
480
|
)
|
494
481
|
else:
|
495
|
-
|
496
|
-
f"
|
482
|
+
wandb.termwarn(
|
483
|
+
f"{LOG_PREFIX}Automatic credential handling is not supported for registry type {type(self.registry)}. Build job: {self.build_job_name}"
|
497
484
|
)
|
498
485
|
volumes.append(
|
499
486
|
{
|
@@ -522,7 +509,7 @@ class KanikoBuilder(AbstractBuilder):
|
|
522
509
|
volume_mounts.append(
|
523
510
|
{"name": "docker-config", "mountPath": "/kaniko/.docker/"}
|
524
511
|
)
|
525
|
-
# Kaniko doesn't want https:// at the
|
512
|
+
# Kaniko doesn't want https:// at the beginning of the image tag.
|
526
513
|
destination = image_tag
|
527
514
|
if destination.startswith("https://"):
|
528
515
|
destination = destination.replace("https://", "")
|
@@ -0,0 +1,92 @@
|
|
1
|
+
DOCKERFILE_TEMPLATE = """
|
2
|
+
# ----- stage 1: build -----
|
3
|
+
FROM {py_build_image} as build
|
4
|
+
|
5
|
+
# requirements section depends on pip vs conda, and presence of buildx
|
6
|
+
ENV PIP_PROGRESS_BAR off
|
7
|
+
{requirements_section}
|
8
|
+
|
9
|
+
# ----- stage 2: base -----
|
10
|
+
{base_setup}
|
11
|
+
|
12
|
+
COPY --from=build /env /env
|
13
|
+
ENV PATH="/env/bin:$PATH"
|
14
|
+
|
15
|
+
ENV SHELL /bin/bash
|
16
|
+
|
17
|
+
# some resources (eg sagemaker) must run on root
|
18
|
+
{user_setup}
|
19
|
+
|
20
|
+
WORKDIR {workdir}
|
21
|
+
RUN chown -R {uid} {workdir}
|
22
|
+
|
23
|
+
# make artifacts cache dir unrelated to build
|
24
|
+
RUN mkdir -p {workdir}/.cache && chown -R {uid} {workdir}/.cache
|
25
|
+
|
26
|
+
# copy code/etc
|
27
|
+
COPY --chown={uid} src/ {workdir}
|
28
|
+
|
29
|
+
ENV PYTHONUNBUFFERED=1
|
30
|
+
|
31
|
+
{entrypoint_section}
|
32
|
+
"""
|
33
|
+
|
34
|
+
# this goes into base_setup in TEMPLATE
|
35
|
+
PYTHON_SETUP_TEMPLATE = """
|
36
|
+
FROM {py_base_image} as base
|
37
|
+
"""
|
38
|
+
|
39
|
+
# this goes into base_setup in TEMPLATE
|
40
|
+
ACCELERATOR_SETUP_TEMPLATE = """
|
41
|
+
FROM {accelerator_base_image} as base
|
42
|
+
|
43
|
+
# make non-interactive so build doesn't block on questions
|
44
|
+
ENV DEBIAN_FRONTEND=noninteractive
|
45
|
+
|
46
|
+
# install python
|
47
|
+
RUN apt-get update -qq && apt-get install --no-install-recommends -y \
|
48
|
+
{python_packages} \
|
49
|
+
&& apt-get -qq purge && apt-get -qq clean \
|
50
|
+
&& rm -rf /var/lib/apt/lists/*
|
51
|
+
|
52
|
+
# make sure `python` points at the right version
|
53
|
+
RUN update-alternatives --install /usr/bin/python python /usr/bin/python{py_version} 1 \
|
54
|
+
&& update-alternatives --install /usr/local/bin/python python /usr/bin/python{py_version} 1
|
55
|
+
"""
|
56
|
+
|
57
|
+
# this goes into requirements_section in TEMPLATE
|
58
|
+
PIP_TEMPLATE = """
|
59
|
+
RUN python -m venv /env
|
60
|
+
# make sure we install into the env
|
61
|
+
ENV PATH="/env/bin:$PATH"
|
62
|
+
|
63
|
+
COPY {requirements_files} ./
|
64
|
+
{buildx_optional_prefix} {pip_install}
|
65
|
+
"""
|
66
|
+
|
67
|
+
# this goes into requirements_section in TEMPLATE
|
68
|
+
CONDA_TEMPLATE = """
|
69
|
+
COPY src/environment.yml .
|
70
|
+
{buildx_optional_prefix} conda env create -f environment.yml -n env
|
71
|
+
|
72
|
+
# pack the environment so that we can transfer to the base image
|
73
|
+
RUN conda install -c conda-forge conda-pack
|
74
|
+
RUN conda pack -n env -o /tmp/env.tar && \
|
75
|
+
mkdir /env && cd /env && tar xf /tmp/env.tar && \
|
76
|
+
rm /tmp/env.tar
|
77
|
+
RUN /env/bin/conda-unpack
|
78
|
+
"""
|
79
|
+
|
80
|
+
USER_CREATE_TEMPLATE = """
|
81
|
+
RUN useradd \
|
82
|
+
--create-home \
|
83
|
+
--no-log-init \
|
84
|
+
--shell /bin/bash \
|
85
|
+
--gid 0 \
|
86
|
+
--uid {uid} \
|
87
|
+
{user} || echo ""
|
88
|
+
"""
|
89
|
+
|
90
|
+
ENTRYPOINT_TEMPLATE = """
|
91
|
+
ENTRYPOINT {entrypoint}
|
92
|
+
"""
|