Exemplo n.º 1
0
    def _build_with_docker(self, docker_client):
        docker_args = {}
        docker_args['path'] = os.path.join(self.target, 'image')
        docker_args['pull'] = self.params.pull
        docker_args['rm'] = True
        docker_args['decode'] = True

        build_log = []
        docker_layer_ids = []

        try:
            stream = docker_client.build(**docker_args)

            for part in stream:
                # In case an error is returned, log the message and fail the build
                if 'errorDetail' in part:
                    error_message = part.get('errorDetail',
                                             {}).get('message', '')
                    raise CekitError(
                        "Image build failed: '{}'".format(error_message))
                elif 'stream' in part:
                    messages = part['stream']
                else:
                    # We actually expect only 'stream' here.
                    # If there is something different, we ignore it.
                    # It's safe to do so because if it would be an error, we would catch it
                    # earlier. Ignored logs are related to fetching/pulling/extracting
                    # of container images.
                    continue

                # This prevents polluting CEKit log with downloading/extracting messages
                messages = ANSI_ESCAPE.sub('', messages).strip()

                # Python 2 compatibility
                if sys.version_info[0] == 2:
                    messages = messages.encode("utf-8", errors="ignore")

                for message in messages.split('\n'):
                    LOGGER.info('Docker: {}'.format(message))

                build_log.append(messages)

                layer_id_match = re.search(r'^---> ([\w]{12})$', messages)

                if layer_id_match:
                    docker_layer_ids.append(layer_id_match.group(1))

        except requests.ConnectionError as ex:
            exception_chain = traceback.format_exc()
            LOGGER.debug(
                "Caught ConnectionError attempting to communicate with Docker ",
                exc_info=1)

            if 'PermissionError' in exception_chain:
                message = "Unable to contact docker daemon. Is it correctly setup?\n" \
                    "See https://developer.fedoraproject.org/tools/docker/docker-installation.html and " \
                    "http://www.projectatomic.io/blog/2015/08/why-we-dont-let-non-root-users-run-docker-in-centos-fedora-or-rhel"
            elif 'FileNotFoundError' in exception_chain:
                message = "Unable to contact docker daemon. Is it started?"
            else:
                message = "Unknown ConnectionError from docker ; is the daemon started and correctly setup?"

            if sys.version_info.major == 3:
                # Work-around for python 2 / 3 code - replicate exception(...) from None
                cekit_exception = CekitError(message, ex)
                cekit_exception.__cause__ = None
                raise cekit_exception
            else:
                raise CekitError(message, ex)

        except Exception as ex:
            msg = "Image build failed, see logs above."
            if len(docker_layer_ids) >= 2:
                LOGGER.error("You can look inside the failed image by running "
                             "'docker run --rm -ti {} bash'".format(
                                 docker_layer_ids[-1]))
            if "To enable Red Hat Subscription Management repositories:" in ' '.join(build_log) and \
                    not os.path.exists(os.path.join(self.target, 'image', 'repos')):
                msg = "Image build failed with a yum error and you don't " \
                    "have any yum repository configured, please check " \
                    "your image/module descriptor for proper repository " \
                    "definitions."

            raise CekitError(msg, ex)

        return docker_layer_ids[-1]
Exemplo n.º 2
0
    def _build_with_docker(self, docker_client):
        docker_args = {}
        docker_args['path'] = os.path.join(self.target, 'image')
        docker_args['pull'] = self.params.pull
        docker_args['rm'] = True

        build_log = [""]
        docker_layer_ids = []

        try:
            out = docker_client.build(**docker_args)
            for line in out:
                if b'stream' in line:
                    line = yaml.safe_load(line)['stream']
                elif b'status' in line:
                    line = yaml.safe_load(line)['status']
                elif b'errorDetail' in line:
                    line = yaml.safe_load(line)['errorDetail']['message']
                    raise CekitError("Image build failed: '%s'" % line)

                if line != build_log[-1]:
                    # this prevents poluting cekit log with dowloading/extracting msgs
                    log_msg = ANSI_ESCAPE.sub('', line).strip()
                    for msg in log_msg.split('\n'):
                        LOGGER.info('Docker: %s' % msg)
                    build_log.append(line)

                    layer_id_match = re.search(r'^---> ([\w]{12})$',
                                               line.strip())

                    if layer_id_match:
                        docker_layer_ids.append(layer_id_match.group(1))

        except requests.ConnectionError as ex:
            exception_chain = traceback.format_exc()
            LOGGER.debug(
                "Caught ConnectionError attempting to communicate with Docker ",
                exc_info=1)

            if 'PermissionError' in exception_chain:
                message = "Unable to contact docker daemon. Is it correctly setup?\n" \
                          "See https://developer.fedoraproject.org/tools/docker/docker-installation.html and " \
                          "http://www.projectatomic.io/blog/2015/08/why-we-dont-let-non-root-users-run-docker-in-centos-fedora-or-rhel"
            elif 'FileNotFoundError' in exception_chain:
                message = "Unable to contact docker daemon. Is it started?"
            else:
                message = "Unknown ConnectionError from docker ; is the daemon started and correctly setup?"

            if sys.version_info.major == 3:
                # Work-around for python 2 / 3 code - replicate exception(...) from None
                cekit_exception = CekitError(message, ex)
                cekit_exception.__cause__ = None
                raise cekit_exception
            else:
                raise CekitError(message, ex)

        except Exception as ex:
            msg = "Image build failed, see logs above."
            if len(docker_layer_ids) >= 2:
                LOGGER.error("You can look inside the failed image by running "
                             "'docker run --rm -ti %s bash'" %
                             docker_layer_ids[-1])
            if "To enable Red Hat Subscription Management repositories:" in ' '.join(build_log) and \
                    not os.path.exists(os.path.join(self.target, 'image', 'repos')):
                msg = "Image build failed with a yum error and you don't " \
                      "have any yum repository configured, please check " \
                      "your image/module descriptor for proper repository " \
                      " definitions."
            raise CekitError(msg, ex)

        return docker_layer_ids[-1]