Skip to content

Commit 9e380a8

Browse files
authored
Conda Pack build related enhancements (#908)
2 parents 55740a6 + 5c244be commit 9e380a8

File tree

5 files changed

+108
-41
lines changed

5 files changed

+108
-41
lines changed

ads/common/auth.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def __post_init__(self):
7373
self.oci_key_profile = self.oci_key_profile or os.environ.get(
7474
"OCI_CONFIG_PROFILE", DEFAULT_PROFILE
7575
)
76-
self.oci_config = self.oci_config or {}
76+
self.oci_config = self.oci_config or {"region": os.environ["OCI_RESOURCE_REGION"]} if os.environ.get("OCI_RESOURCE_REGION") else {}
7777
self.oci_signer_kwargs = self.oci_signer_kwargs or {}
7878
self.oci_client_kwargs = self.oci_client_kwargs or {}
7979

@@ -82,7 +82,7 @@ def set_auth(
8282
auth: Optional[str] = AuthType.API_KEY,
8383
oci_config_location: Optional[str] = DEFAULT_LOCATION,
8484
profile: Optional[str] = DEFAULT_PROFILE,
85-
config: Optional[Dict] = {},
85+
config: Optional[Dict] = {"region": os.environ["OCI_RESOURCE_REGION"]} if os.environ.get("OCI_RESOURCE_REGION") else {},
8686
signer: Optional[Any] = None,
8787
signer_callable: Optional[Callable] = None,
8888
signer_kwargs: Optional[Dict] = {},
@@ -678,7 +678,7 @@ def create_signer(self) -> Dict:
678678
>>> signer_generator = AuthFactory().signerGenerator(AuthType.RESOURCE_PRINCIPAL)
679679
>>> signer_generator(signer_args).create_signer()
680680
"""
681-
configuration = ads.telemetry.update_oci_client_config()
681+
configuration = ads.telemetry.update_oci_client_config(AuthState().oci_config)
682682
signer_dict = {
683683
"config": configuration,
684684
"signer": oci.auth.signers.get_resource_principals_signer(),
@@ -739,7 +739,7 @@ def create_signer(self) -> Dict:
739739
>>> signer_generator = AuthFactory().signerGenerator(AuthType.INSTANCE_PRINCIPAL)
740740
>>> signer_generator(signer_args).create_signer()
741741
"""
742-
configuration = ads.telemetry.update_oci_client_config()
742+
configuration = ads.telemetry.update_oci_client_config(AuthState().oci_config)
743743
signer_dict = {
744744
"config": configuration,
745745
"signer": oci.auth.signers.InstancePrincipalsSecurityTokenSigner(

ads/opctl/conda/cmds.py

Lines changed: 85 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def _check_job_image_exists(gpu: bool) -> None:
8080
def _get_name(name: str, env_file: str) -> str:
8181
if not name and env_file:
8282
with open(env_file) as f:
83-
name = yaml.safe_load(f.read()).get("name", None)
83+
name = yaml.safe_load(f.read()).get("manifest").get("name", None)
8484
if not name:
8585
raise ValueError(
8686
"Either specify environment name in environment yaml or with `--name`."
@@ -146,7 +146,14 @@ def _create(
146146
if not os.path.exists(env_file):
147147
raise FileNotFoundError(f"Environment file {env_file} is not found.")
148148

149-
slug = f"{name}_v{version}".replace(" ", "").replace(".", "_").lower()
149+
conda_dep = None
150+
with open(env_file) as mfile:
151+
conda_dep = yaml.safe_load(mfile.read())
152+
# If manifest exists in the environment.yaml file, use that
153+
manifest = conda_dep.get("manifest", {})
154+
slug = manifest.get(
155+
"slug", f"{name}_v{version}".replace(" ", "").replace(".", "_").lower()
156+
)
150157
pack_folder_path = os.path.join(
151158
os.path.abspath(os.path.expanduser(conda_pack_folder)), slug
152159
)
@@ -171,23 +178,38 @@ def _create(
171178

172179
os.makedirs(pack_folder_path, exist_ok=True)
173180

181+
logger.info(
182+
f"Preparing manifest. Manifest in the environment: {conda_dep.get('manifest')}"
183+
)
174184
manifest = _fetch_manifest_template()
175-
manifest["manifest"]["name"] = name
185+
if "name" not in manifest:
186+
manifest["manifest"]["name"] = name
176187
manifest["manifest"]["slug"] = slug
177-
manifest["manifest"]["type"] = "published"
178-
manifest["manifest"]["version"] = version
188+
if "type" not in manifest:
189+
logger.info("Setting manifest to published")
190+
manifest["manifest"]["type"] = "published"
191+
if "version" not in manifest:
192+
manifest["manifest"]["version"] = version
179193
manifest["manifest"]["arch_type"] = "GPU" if gpu else "CPU"
180194

181195
manifest["manifest"]["create_date"] = datetime.utcnow().strftime(
182196
"%a, %b %d, %Y, %H:%M:%S %Z UTC"
183197
)
184-
manifest["manifest"]["manifest_version"] = "1.0"
198+
199+
if not "manifest_version" in manifest:
200+
manifest["manifest"]["manifest_version"] = "1.0"
185201

186202
logger.info(f"Creating conda environment {slug}")
187-
conda_dep = None
188-
with open(env_file) as mfile:
189-
conda_dep = yaml.safe_load(mfile.read())
190-
conda_dep["manifest"] = manifest["manifest"]
203+
manifest_dict = {
204+
k: manifest["manifest"][k]
205+
for k in manifest["manifest"]
206+
if manifest["manifest"][k]
207+
}
208+
if "manifest" in conda_dep:
209+
conda_dep["manifest"].update(manifest_dict)
210+
else:
211+
conda_dep["manifest"] = manifest_dict
212+
logger.info(f"Updated conda environment manifest: {conda_dep.get('manifest')}")
191213

192214
if is_in_notebook_session() or NO_CONTAINER:
193215
command = f"conda env create --prefix {pack_folder_path} --file {os.path.abspath(os.path.expanduser(env_file))}"
@@ -200,13 +222,12 @@ def _create(
200222
)
201223

202224
create_command = f"conda env create --prefix {docker_pack_folder_path} --file {docker_env_file_path}"
203-
225+
204226
volumes = {
205227
pack_folder_path: {"bind": docker_pack_folder_path},
206228
os.path.abspath(os.path.expanduser(env_file)): {
207229
"bind": docker_env_file_path
208230
},
209-
210231
}
211232

212233
if gpu:
@@ -217,26 +238,42 @@ def _create(
217238
if prepare_publish:
218239
tmp_file = tempfile.NamedTemporaryFile(suffix=".yaml")
219240
# Save the manifest in the temp file that can be mounted inside the container so that archiving will work
220-
with open(tmp_file.name, 'w') as f:
221-
yaml.safe_dump(conda_dep, f)
241+
with open(tmp_file.name, "w") as f:
242+
yaml.safe_dump(conda_dep, f)
222243

223-
pack_script = os.path.join(os.path.dirname(os.path.abspath(__file__)), "pack.py")
244+
pack_script = os.path.join(
245+
os.path.dirname(os.path.abspath(__file__)), "pack.py"
246+
)
224247
pack_command = f"python {os.path.join(DEFAULT_IMAGE_HOME_DIR, 'pack.py')} --conda-path {docker_pack_folder_path} --manifest-location {os.path.join(DEFAULT_IMAGE_HOME_DIR, 'manifest.yaml')}"
225248

226249
# add pack script and manifest file to the mount so that archive can be created in the same container run
227250
condapack_script = {
228-
pack_script: {"bind": os.path.join(DEFAULT_IMAGE_HOME_DIR, "pack.py")},
229-
tmp_file.name: {"bind": os.path.join(DEFAULT_IMAGE_HOME_DIR, "manifest.yaml")}
251+
pack_script: {
252+
"bind": os.path.join(DEFAULT_IMAGE_HOME_DIR, "pack.py")
253+
},
254+
tmp_file.name: {
255+
"bind": os.path.join(DEFAULT_IMAGE_HOME_DIR, "manifest.yaml")
256+
},
230257
}
231-
volumes = {**volumes, **condapack_script} # | not supported in python 3.8
258+
volumes = {
259+
**volumes,
260+
**condapack_script,
261+
} # | not supported in python 3.8
232262

233263
run_container(
234-
image=image, bind_volumes=volumes, entrypoint="/bin/bash -c ", env_vars={}, command=f" '{create_command} && {pack_command}'"
264+
image=image,
265+
bind_volumes=volumes,
266+
entrypoint="/bin/bash -c ",
267+
env_vars={},
268+
command=f" '{create_command} && {pack_command}'",
235269
)
236270
else:
237271
run_container(
238-
image=image, bind_volumes=volumes, env_vars={}, command=create_command
239-
)
272+
image=image,
273+
bind_volumes=volumes,
274+
env_vars={},
275+
command=create_command,
276+
)
240277
except Exception:
241278
if os.path.exists(pack_folder_path):
242279
shutil.rmtree(pack_folder_path)
@@ -507,9 +544,11 @@ def publish(**kwargs) -> None:
507544
conda_pack_folder=exec_config["conda_pack_folder"],
508545
gpu=exec_config.get("gpu", False),
509546
overwrite=exec_config["overwrite"],
510-
prepare_publish=True
547+
prepare_publish=True,
548+
)
549+
skip_archive = (
550+
True # The conda pack archive is already created during create process.
511551
)
512-
skip_archive = True # The conda pack archive is already created during create process.
513552
else:
514553
slug = exec_config.get("slug")
515554
if not slug:
@@ -526,10 +565,10 @@ def publish(**kwargs) -> None:
526565
oci_profile=exec_config.get("oci_profile"),
527566
overwrite=exec_config["overwrite"],
528567
auth_type=exec_config["auth"],
529-
skip_archive=skip_archive
568+
skip_archive=skip_archive,
530569
)
531570

532-
571+
533572
def _publish(
534573
conda_slug: str,
535574
conda_uri_prefix: str,
@@ -538,7 +577,7 @@ def _publish(
538577
oci_profile: str,
539578
overwrite: bool,
540579
auth_type: str,
541-
skip_archive: bool = False
580+
skip_archive: bool = False,
542581
) -> None:
543582
"""Publish a local conda pack to object storage location
544583
@@ -616,7 +655,11 @@ def _publish(
616655
pack_script = os.path.join(os.path.dirname(os.path.abspath(__file__)), "pack.py")
617656
if not skip_archive:
618657
if is_in_notebook_session() or NO_CONTAINER:
658+
# Set the CONDA_PUBLISH_TYPE environment variable so that the `type` attribute inside the manifest is not changed
659+
publish_type = os.environ.get("CONDA_PUBLISH_TYPE")
619660
command = f"python {pack_script} --conda-path {pack_folder_path}"
661+
if publish_type:
662+
command = f"CONDA_PUBLISH_TYPE={publish_type} {command}"
620663
run_command(command, shell=True)
621664
else:
622665
volumes = {
@@ -641,7 +684,9 @@ def _publish(
641684
NOT_ALLOWED_CHARS = "@#$%^&*/"
642685

643686
if any(chr in conda_slug for chr in NOT_ALLOWED_CHARS):
644-
raise ValueError(f"Invalid conda_slug. Found {NOT_ALLOWED_CHARS} in slug name. Please use a different slug name.")
687+
raise ValueError(
688+
f"Invalid conda_slug. Found {NOT_ALLOWED_CHARS} in slug name. Please use a different slug name."
689+
)
645690
pack_file = os.path.join(pack_folder_path, f"{conda_slug}.tar.gz")
646691
if not os.path.exists(pack_file):
647692
raise RuntimeError(f"Pack {pack_file} was not created.")
@@ -664,14 +709,19 @@ def _publish(
664709
str(manifest["version"]),
665710
publish_slug,
666711
)
667-
manifest["pack_path"] = os.path.join(
668-
prefix,
669-
manifest.get("arch_type", "CPU").lower(),
670-
manifest["name"],
671-
str(manifest["version"]),
672-
publish_slug,
673-
)
674-
manifest["pack_uri"] = pack_uri
712+
if os.environ.get("CONDA_PUBLISH_TYPE") != "service":
713+
# Set these values only for published conda pack
714+
manifest["pack_path"] = os.path.join(
715+
prefix,
716+
manifest.get("arch_type", "CPU").lower(),
717+
manifest["name"],
718+
str(manifest["version"]),
719+
publish_slug,
720+
)
721+
manifest["pack_uri"] = pack_uri
722+
else:
723+
manifest["type"] = "published"
724+
675725
with open(manifest_location, "w") as f:
676726
yaml.safe_dump(env, f)
677727
if pack_size > 100:

ads/opctl/conda/pack.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121

2222
def main(pack_folder_path, manifest_file=None):
23-
slug = os.path.basename(pack_folder_path)
2423
manifest_path = (
2524
manifest_file or glob.glob(os.path.join(pack_folder_path, "*_manifest.yaml"))[0]
2625
)
@@ -47,7 +46,9 @@ def main(pack_folder_path, manifest_file=None):
4746
raise e
4847

4948
manifest = env["manifest"]
50-
manifest["type"] = "published"
49+
slug = manifest.get("slug", os.path.basename(pack_folder_path))
50+
if os.environ.get("CONDA_PUBLISH_TYPE") != "service":
51+
manifest["type"] = "published"
5152
new_env_info["manifest"] = manifest
5253
with open(manifest_path, "w") as f:
5354
yaml.safe_dump(new_env_info, f)

tests/unitary/with_extras/ads_string/test_ads_string.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ def setup_class(self):
4848
"averaged_perceptron_tagger",
4949
download_dir=os.environ["CONDA_PREFIX"] + "/nltk",
5050
)
51+
nltk.download(
52+
"averaged_perceptron_tagger_eng",
53+
download_dir=os.environ["CONDA_PREFIX"] + "/nltk",
54+
)
55+
nltk.download(
56+
"punkt_tab",
57+
download_dir=os.environ["CONDA_PREFIX"] + "/nltk",
58+
)
5159

5260
def test_basic_string_methods(self):
5361
s = ADSString("HELLO WORLD")

tests/unitary/with_extras/feature_types/test_feature_types.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ def setup_class(self):
4545
"averaged_perceptron_tagger",
4646
download_dir=os.environ["CONDA_PREFIX"] + "/nltk",
4747
)
48+
nltk.download(
49+
"averaged_perceptron_tagger_eng",
50+
download_dir=os.environ["CONDA_PREFIX"] + "/nltk",
51+
)
52+
nltk.download(
53+
"punkt_tab",
54+
download_dir=os.environ["CONDA_PREFIX"] + "/nltk",
55+
)
4856

4957
def test_datatime_type(self):
5058
assert (

0 commit comments

Comments
 (0)