Skip to content
Snippets Groups Projects
Commit 2e88c8a4 authored by Adrian Ciu's avatar Adrian Ciu Committed by adrianciu
Browse files

VT-107: make BuildCacheManager flexible to missing or incorrect OCI credentials

parent 57a8e872
No related branches found
No related tags found
1 merge request!11VT-107: make BuildCacheManager flexible to missing or incorrect OCI credentials
Pipeline #61025 passed with stages
in 39 minutes and 24 seconds
# Dedal # Dedal
![Coverage Badge](https://gitlab.ebrains.eu/ri/tech-hub/platform/esd/dedal/badges/master/coverage.svg)
This repository provides functionalities to easily ```managed spack environments``` and This repository provides functionalities to easily ```managed spack environments``` and
```helpers for the container image build flow```. ```helpers for the container image build flow```.
......
import builtins
import glob import glob
import os import os
from os.path import join from os.path import join
...@@ -14,24 +15,44 @@ class BuildCacheManager(BuildCacheManagerInterface): ...@@ -14,24 +15,44 @@ class BuildCacheManager(BuildCacheManagerInterface):
This class aims to manage the push/pull/delete of build cache files This class aims to manage the push/pull/delete of build cache files
""" """
def __init__(self, registry_host, registry_project, registry_username, registry_password, cache_version='cache', def __new__(cls, registry_host, registry_project, registry_username, registry_password, cache_version='cache',
auth_backend='basic', insecure=False, tls_verify=True): auth_backend='basic', insecure=False, tls_verify=True):
self._logger = get_logger(__name__, BuildCacheManager.__name__) instance = super().__new__(cls)
self._registry_project = registry_project instance._logger = get_logger(__name__, BuildCacheManager.__name__)
instance._registry_project = registry_project
self._registry_username = registry_username instance._registry_username = registry_username
self._registry_password = registry_password instance._registry_password = registry_password
self._registry_host = registry_host instance._registry_host = registry_host
# Override input to disable prompts during login.
# Define a function that raises an exception when input is called.
def disabled_input(prompt=""):
raise Exception("Interactive login disabled: credentials are provided via attributes.")
# Save the original input function.
original_input = builtins.input
# Override input so that any call to input() during login will raise our exception.
builtins.input = disabled_input
# Initialize an OrasClient instance. # Initialize an OrasClient instance.
# This method utilizes the OCI Registry for container image and artifact management. # This method utilizes the OCI Registry for container image and artifact management.
# Refer to the official OCI Registry documentation for detailed information on the available authentication methods. # Refer to the official OCI Registry documentation for detailed information on the available authentication methods.
# Supported authentication types may include basic authentication (username/password), token-based authentication, # Supported authentication types may include basic authentication (username/password), token-based authentication,
self._client = oras.client.OrasClient(hostname=self._registry_host, auth_backend=auth_backend, instance._client = oras.client.OrasClient(hostname=instance._registry_host, auth_backend=auth_backend,
insecure=insecure, tls_verify=tls_verify) insecure=insecure, tls_verify=tls_verify)
self._client.login(username=self._registry_username, password=self._registry_password)
self.cache_version = cache_version try:
self._oci_registry_path = f'{self._registry_host}/{self._registry_project}/{self.cache_version}' instance._client.login(username=instance._registry_username, password=instance._registry_password)
except Exception:
instance._logger.error('Login failed!')
return None
finally:
builtins.input = original_input
instance.cache_version = cache_version
instance._oci_registry_path = f'{instance._registry_host}/{instance._registry_project}/{instance.cache_version}'
return instance
def upload(self, upload_dir: Path, override_cache=True): def upload(self, upload_dir: Path, override_cache=True):
""" """
......
...@@ -50,10 +50,16 @@ class SpackOperationCreateCache(SpackOperation): ...@@ -50,10 +50,16 @@ class SpackOperationCreateCache(SpackOperation):
NoSpackEnvironmentException: If the spack environment is not set up. NoSpackEnvironmentException: If the spack environment is not set up.
""" """
super().concretize_spack_env(force=True, test=test) super().concretize_spack_env(force=True, test=test)
dependency_path = self.spack_config.env.path / self.spack_config.env.name / 'spack.lock' if self.cache_dependency:
copy_file(dependency_path, self.spack_config.concretization_dir, logger=self.logger) dependency_path = self.spack_config.env.path / self.spack_config.env.name / 'spack.lock'
self.cache_dependency.upload(self.spack_config.concretization_dir, override_cache=self.spack_config.override_cache) copy_file(dependency_path, self.spack_config.concretization_dir, logger=self.logger)
self.logger.info(f'Created new spack concretization for create cache: {self.spack_config.env.name}') self.cache_dependency.upload(self.spack_config.concretization_dir,
override_cache=self.spack_config.override_cache)
self.logger.info(
f'Finished uploading new spack concretization for create cache: {self.spack_config.env.name}')
else:
self.logger.info(
f'Created new spack concretization for create cache: {self.spack_config.env.name}. No OCI credentials for concretization step were provided!')
@check_spack_env @check_spack_env
def install_packages(self, jobs: int = 2, debug=False, test=None): def install_packages(self, jobs: int = 2, debug=False, test=None):
...@@ -65,4 +71,9 @@ class SpackOperationCreateCache(SpackOperation): ...@@ -65,4 +71,9 @@ class SpackOperationCreateCache(SpackOperation):
self.create_gpg_keys() self.create_gpg_keys()
self.logger.info('Created gpg keys') self.logger.info('Created gpg keys')
super().install_packages(jobs=jobs, signed=self.signed, debug=debug, fresh=True, test=test) super().install_packages(jobs=jobs, signed=self.signed, debug=debug, fresh=True, test=test)
self.build_cache.upload(self.spack_config.buildcache_dir, override_cache=self.spack_config.override_cache) if self.build_cache:
self.build_cache.upload(self.spack_config.buildcache_dir, override_cache=self.spack_config.override_cache)
self.logger.info(f'Finished uploading build cache: {self.spack_config.env.name}')
else:
self.logger.info(
f'Created build cache: {self.spack_config.env.name}. No OCI credentials for concretization step were provided!')
...@@ -9,18 +9,21 @@ from dedal.spack_factory.SpackOperationUseCache import SpackOperationUseCache ...@@ -9,18 +9,21 @@ from dedal.spack_factory.SpackOperationUseCache import SpackOperationUseCache
class SpackOperationCreator: class SpackOperationCreator:
@staticmethod @staticmethod
def get_spack_operator(spack_config: SpackConfig = None, use_cache: bool = False) -> SpackOperation: def get_spack_operator(spack_config: SpackConfig = None, use_cache: bool = False) -> SpackOperation:
env_vars = [os.environ.get('CONCRETIZE_OCI_HOST'), env_vars_concretization_cache = [
os.environ.get('CONCRETIZE_OCI_PROJECT'), os.environ.get('CONCRETIZE_OCI_HOST'),
os.environ.get('CONCRETIZE_OCI_USERNAME'), os.environ.get('CONCRETIZE_OCI_PROJECT'),
os.environ.get('CONCRETIZE_OCI_PASSWORD'), os.environ.get('CONCRETIZE_OCI_USERNAME'),
os.environ.get('BUILDCACHE_OCI_HOST'), os.environ.get('CONCRETIZE_OCI_PASSWORD'),
os.environ.get('BUILDCACHE_OCI_PROJECT'), ]
os.environ.get('BUILDCACHE_OCI_USERNAME'), env_vars_build_cache = [
os.environ.get('BUILDCACHE_OCI_PASSWORD') os.environ.get('BUILDCACHE_OCI_HOST'),
] os.environ.get('BUILDCACHE_OCI_PROJECT'),
os.environ.get('BUILDCACHE_OCI_USERNAME'),
os.environ.get('BUILDCACHE_OCI_PASSWORD')
]
if spack_config is None: if spack_config is None:
return SpackOperation() return SpackOperation()
elif None in env_vars: elif None in env_vars_concretization_cache and None in env_vars_build_cache:
return SpackOperation(spack_config) return SpackOperation(spack_config)
elif spack_config.concretization_dir is None and spack_config.buildcache_dir is None: elif spack_config.concretization_dir is None and spack_config.buildcache_dir is None:
return SpackOperation(spack_config) return SpackOperation(spack_config)
......
...@@ -39,21 +39,23 @@ class SpackOperationUseCache(SpackOperation): ...@@ -39,21 +39,23 @@ class SpackOperationUseCache(SpackOperation):
""" """
super().setup_spack_env() super().setup_spack_env()
# Download concretization cache from OCI Registry # Download concretization cache from OCI Registry
self.cache_dependency.download(self.spack_config.concretization_dir) if self.cache_dependency:
self.cache_dependency.download(self.spack_config.concretization_dir)
# Download build cache from OCI Registry and add public key to trusted keys # Download build cache from OCI Registry and add public key to trusted keys
self.build_cache.download(self.spack_config.buildcache_dir) if self.build_cache:
cached_public_key = self.build_cache.get_public_key_from_cache(str(self.spack_config.buildcache_dir)) self.build_cache.download(self.spack_config.buildcache_dir)
signed = cached_public_key is not None cached_public_key = self.build_cache.get_public_key_from_cache(str(self.spack_config.buildcache_dir))
if signed: signed = cached_public_key is not None
self.trust_gpg_key(cached_public_key) if signed:
# Add build cache mirror self.trust_gpg_key(cached_public_key)
self.add_mirror('local_cache', # Add build cache mirror
str(self.spack_config.buildcache_dir), self.add_mirror('local_cache',
signed=signed, str(self.spack_config.buildcache_dir),
autopush=False, signed=signed,
global_mirror=False) autopush=False,
self.update_buildcache_index(self.spack_config.buildcache_dir) global_mirror=False)
self.install_gpg_keys() self.update_buildcache_index(self.spack_config.buildcache_dir)
self.install_gpg_keys()
@check_spack_env @check_spack_env
def concretize_spack_env(self, test=None): def concretize_spack_env(self, test=None):
...@@ -63,7 +65,7 @@ class SpackOperationUseCache(SpackOperation): ...@@ -63,7 +65,7 @@ class SpackOperationUseCache(SpackOperation):
NoSpackEnvironmentException: If the spack environment is not set up. NoSpackEnvironmentException: If the spack environment is not set up.
""" """
concretization_redo = False concretization_redo = False
if file_exists_and_not_empty(self.spack_config.concretization_dir / 'spack.lock'): if self.cache_dependency and file_exists_and_not_empty(self.spack_config.concretization_dir / 'spack.lock'):
concretization_file_path = self.env_path / 'spack.lock' concretization_file_path = self.env_path / 'spack.lock'
copy_file(self.spack_config.concretization_dir / 'spack.lock', self.env_path) copy_file(self.spack_config.concretization_dir / 'spack.lock', self.env_path)
# redo the concretization step if spack.lock file was not downloaded from the cache # redo the concretization step if spack.lock file was not downloaded from the cache
...@@ -90,18 +92,21 @@ class SpackOperationUseCache(SpackOperation): ...@@ -90,18 +92,21 @@ class SpackOperationUseCache(SpackOperation):
signed = '' if signed else '--no-check-signature' signed = '' if signed else '--no-check-signature'
debug = '--debug' if debug else '' debug = '--debug' if debug else ''
test = f'--test {test}' if test else '' test = f'--test {test}' if test else ''
install_result = run_command("bash", "-c", if self.build_cache:
f'{self.spack_command_on_env} && spack {debug} install -v --cache-only {signed} -j {jobs} {test}', install_result = run_command("bash", "-c",
stdout=subprocess.PIPE, f'{self.spack_command_on_env} && spack {debug} install -v --cache-only {signed} -j {jobs} {test}',
stderr=subprocess.PIPE, stdout=subprocess.PIPE,
text=True, stderr=subprocess.PIPE,
logger=self.logger, text=True,
info_msg=f"Installing spack packages for {self.spack_config.env.name}", logger=self.logger,
exception_msg=f"Error installing spack packages for {self.spack_config.env.name}", info_msg=f"Installing spack packages for {self.spack_config.env.name}",
exception=SpackInstallPackagesException) exception_msg=f"Error installing spack packages for {self.spack_config.env.name}",
log_command(install_result, str(Path(os.getcwd()).resolve() / ".generate_cache.log")) exception=SpackInstallPackagesException)
if install_result.returncode == 0: log_command(install_result, str(Path(os.getcwd()).resolve() / ".generate_cache.log"))
self.logger.info(f'Finished installation of spack packages from cache.') if install_result.returncode == 0:
self.logger.info(f'Finished installation of spack packages from cache.')
else:
self.logger.error(f'Something went wrong during installation from cache. Please check the logs.')
else: else:
self.logger.error(f'Something went wrong during installation from cache. Please check the logs.') install_result = super().install_packages(jobs=jobs, signed=signed, debug=debug, test=test)
return install_result return install_result
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment