Example #1
0
    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
Example #2
0
    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
Example #3
0
    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()
Example #4
0
    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")
Example #5
0
    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())
Example #6
0
    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.")
Example #7
0
    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)
Example #8
0
    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