def assert_profile(self, profile: dict): keys = {'limits', 'requests'} assert isinstance(profile, dict) and keys.issubset(set(profile)), \ ConfigurationError("Resource profile must be a mapping containing the keys {}".format(keys)) for key in keys: for res, unit in zip(['cpu', 'memory'], ['vCores', 'MB']): num = profile.get(key, {}).get(res) if res == 'memory': assert num is None or isinstance(num, int), NhaDockerError( "Resource {} '{}' must be an integer ({})".format( key.rstrip('s'), res, unit)) else: assert num is None or isinstance( num, (int, float, str) ), NhaDockerError( "Resource {} '{}' must be integer or float or string ({})" .format(key.rstrip('s'), res, unit)) if isinstance(num, str): assert num[-1] == "m", NhaDockerError( "When string, CPU must be in milli notation. Example: 500m" ) num = float(num[:-1]) / 1000 assert num >= 0.001, NhaDockerError( "CPU precision must be at least 0.001, but was: {}" .format(num)) profile.get(key, {})[res] = num return profile
def assert_resources(self, profile: dict): for key in self.KEYS_RESOURCES: for res, unit in zip(['cpu', 'memory'], ['vCores', 'MB']): num = profile.get(key, {}).get(res) if res == 'memory': assert num is None or isinstance(num, int), NhaDockerError( "Resource {} '{}' must be an integer ({})".format(key.rstrip('s'), res, unit)) else: assert num is None or isinstance(num, (int, float, str)), NhaDockerError( "Resource {} '{}' must be integer or float or string ({})".format(key.rstrip('s'), res, unit)) if isinstance(num, str): num = num.strip() assert num[-1] == "m", NhaDockerError( 'When string, CPU must be in milli notation. Example: "500m"') num = float(num[:-1]) / 1000 assert num >= 0.001, NhaDockerError("CPU precision must be at least 0.001, but was: {}" .format(num)) profile[key][res] = num elif isinstance(num, (int, float)): assert num >= 0.001, NhaDockerError("CPU precision must be at least 0.001, but was: {}" .format(num)) return profile
def build(self, nocache: bool = False): work_path = None try: LOG.info("Building {} from {}".format(self.img_spec.target, self.repo.address)) work_path = self.make_work_path() build_path = self.deploy_source(work_path) logs = self.docker.build(path=build_path, tag=self.img_spec.target, nocache=nocache, rm=True) self.print_logs(logs) self.image = self.docker.images(self.img_spec.target)[0] except Exception as e: raise NhaDockerError("Failed to build from {}".format( self.repo)) from e else: self.tag_image() self.push_image() return self.image_id finally: if work_path is not None: work_path.dispose()
def wait_for_net(self): for _ in range(self.timeout): if self.find_net() is None: time.sleep(1) else: break else: raise NhaDockerError("Timed out waiting for Docker network")
def print_logs(self, logs): for line in logs: dyct = assert_dict(line) if 'stream' in dyct: message = dyct['stream'].strip() if message: LOG.debug(message) if 'error' in dyct: raise NhaDockerError(dyct['error'].strip())
def push_image(self): if self.img_spec.pushable: LOG.info("Pushing {}".format(self.img_spec.target)) log = self.docker.push(self.img_spec.repo, tag=self.img_spec.tag) outcome = json.loads(Regex.LINE_BREAK.split(log.strip())[-1]) if 'error' in outcome: raise NhaDockerError( "Failed to push image '{}'. Error: {}".format( self.img_spec.target, outcome.get('errorDetail'))) else: LOG.warn("Docker registry is not configured. Skipping image push.")
def wait_for_pod(self, pod: Pod): try: if pod.get_phase() == PodPhase.RUNNING and pod.is_ready(): return else: raise NhaDockerError("Timed out waiting for pod '{}'".format( pod.name)) except (ConuException, K8sApiException, NhaDockerError) as e: msg = "Waiting up to {} seconds for pod '{}' to start".format( self.timeout, pod.name) raise PatientError(wait_callback=lambda: self.LOG.info(msg), original_exception=e)
def get_api(self): import docker # lazy import api = docker.APIClient(self.daemon_address) try: # dry run api.ping() except Exception as e: raise NhaDockerError( """Unable to connect to Docker daemon. """ """Assert that the daemon is running and that your user has the required permissions.""" ) from e return api