Ejemplo n.º 1
0
        def __enter__(self):
            from_layer = self.number_of_layers

            if self.number_of_layers and not self.numeric:
                from_layer = self.docker.history(
                    self.image.tag)[self.number_of_layers]['Id']

            squash = Squash(self.log,
                            self.image.tag,
                            self.docker,
                            tag=self.tag,
                            from_layer=from_layer,
                            output_path=self.output_path,
                            load_image=self.load_image,
                            tmp_dir=self.tmp_dir,
                            development=self.development)

            self.image_id = squash.run()

            if not self.output_path:
                self.history = self.docker.history(self.image_id)

                if self.tag:
                    self.tar = self._save_image()

                    with tarfile.open(fileobj=self.tar, mode='r') as tar:
                        self.tarnames = tar.getnames()

                    self.squashed_layer = self._squashed_layer()
                    self.layers = [
                        o['Id'] for o in self.docker.history(self.image_id)
                    ]
                    self.metadata = self.docker.inspect_image(self.image_id)

            return self
Ejemplo n.º 2
0
        def __enter__(self):
            from_layer = self.number_of_layers

            if self.number_of_layers and not self.numeric:
                from_layer = self.docker.history(
                    self.image.tag)[self.number_of_layers]['Id']

            squash = Squash(
                self.log, self.image.tag, self.docker, tag=self.tag, from_layer=from_layer,
                output_path=self.output_path, load_image=self.load_image, tmp_dir=self.tmp_dir, development=self.development)

            self.image_id = squash.run()

            if not self.output_path:
                self.history = self.docker.history(self.image_id)

                if self.tag:
                    self.tar = self._save_image()

                    with tarfile.open(fileobj=self.tar, mode='r') as tar:
                        self.tarnames = tar.getnames()

                    self.squashed_layer = self._squashed_layer()
                    self.layers = [o['Id'] for o in self.docker.history(self.image_id)]
                    self.metadata = self.docker.inspect_image(self.image_id)

            return self
Ejemplo n.º 3
0
    def run(self):
        metadata = {
            "path":
            os.path.join(self.workflow.source.workdir,
                         EXPORTED_SQUASHED_IMAGE_NAME)
        }

        if self.dont_load:
            # squash the image, don't load it back to docker
            Squash(log=self.log,
                   image=self.image,
                   from_layer=self.from_layer,
                   tag=self.tag,
                   output_path=metadata["path"],
                   load_image=False).run()
        else:
            # squash the image and output both tarfile and Docker engine image
            new_id = Squash(log=self.log,
                            image=self.image,
                            from_layer=self.from_layer,
                            tag=self.tag,
                            output_path=metadata["path"],
                            load_image=True).run()
            self.workflow.builder.image_id = new_id

        metadata.update(get_exported_image_metadata(metadata["path"]))
        self.workflow.exported_image_sequence.append(metadata)
        defer_removal(self.workflow, self.image)
Ejemplo n.º 4
0
    def test_should_cleanup_after_squashing(self, v2_image):
        squash = Squash(self.log, 'image', self.docker_client, tag="new_image", load_image=True, cleanup=True)
        self.docker_client.inspect_image.return_value = {'Id': "some_id"}
        squash.run()

        calls = [mock.call(image, force=False, noprune=False) for image in ["some_id", squash.tmp_tag]]

        self.docker_client.remove_image.assert_has_calls(calls)
        self.docker_client.tag.assert_called_once_with(squash.tmp_tag, "new_image", tag=None, force=True)
Ejemplo n.º 5
0
    def _squash(self, docker_client, image_id):
        LOGGER.info("Squashing image {}...".format(image_id))

        squash = Squash(docker=docker_client,
                        log=LOGGER,
                        from_layer=self.generator.image['from'],
                        image=image_id,
                        cleanup=True)
        return squash.run()
 def test_exit_if_no_output_path_provided_and_loading_is_disabled_too(self):
     squash = Squash(self.log,
                     'image',
                     self.docker_client,
                     load_image=False,
                     output_path=None)
     squash.run()
     self.log.warn.assert_called_with(
         "No output path specified and loading into Docker is not selected either; squashed image would not accessible, proceeding with squashing doesn't make sense"
     )
Ejemplo n.º 7
0
    def test_should_cleanup_after_squashing(self, v2_image):
        self.docker_client.inspect_image.return_value = {'Id': "abcdefgh"}
        squash = Squash(self.log,
                        'image',
                        self.docker_client,
                        load_image=True,
                        cleanup=True)
        squash.run()

        self.docker_client.remove_image.assert_called_with('abcdefgh',
                                                           force=False,
                                                           noprune=False)
    def test_should_handle_cleanup_error_when_removing_image(self, v2_image):
        self.docker_client.inspect_image.return_value = {'Id': "abcdefgh"}
        self.docker_client.remove_image.side_effect = docker.errors.APIError(
            "Message")

        squash = Squash(self.log,
                        'image',
                        self.docker_client,
                        load_image=True,
                        cleanup=True)
        squash.run()

        self.log.info.assert_any_call("Removing old image image...")
        self.log.warn.assert_any_call(
            "Could not remove image image: Message, skipping cleanup after squashing"
        )
    def test_should_handle_cleanup_error_while_getting_image_id(
            self, v2_image):
        self.docker_client.inspect_image.side_effect = docker.errors.APIError(
            "Message")

        squash = Squash(self.log,
                        'image',
                        self.docker_client,
                        load_image=True,
                        cleanup=True)
        squash.run()

        self.docker_client.remove_image.assert_not_called()
        self.log.warn.assert_any_call(
            "Could not get the image ID for image image: Message, skipping cleanup after squashing"
        )
Ejemplo n.º 10
0
    def run(self):
        if self.workflow.build_result.skip_layer_squash:
            return  # enable build plugins to prevent unnecessary squashes
        if self.save_archive:
            output_path = os.path.join(self.workflow.source.workdir,
                                       EXPORTED_SQUASHED_IMAGE_NAME)
            metadata = {"path": output_path}
        else:
            output_path = None

        # Squash the image and output tarfile
        # If the parameter dont_load is set to True squashed image won't be
        # loaded in to Docker daemon. If it's set to False it will be loaded.
        new_id = Squash(log=self.log,
                        image=self.image,
                        from_layer=self.from_layer,
                        tag=self.tag,
                        output_path=output_path,
                        load_image=not self.dont_load).run()

        if ':' not in new_id:
            # Older versions of the daemon do not include the prefix
            new_id = 'sha256:{}'.format(new_id)

        if not self.dont_load:
            self.workflow.builder.image_id = new_id

        if self.save_archive:
            metadata.update(
                get_exported_image_metadata(output_path,
                                            IMAGE_TYPE_DOCKER_ARCHIVE))
            self.workflow.exported_image_sequence.append(metadata)
        defer_removal(self.workflow, self.image)
Ejemplo n.º 11
0
    def run(self):
        if is_flatpak_build(self.workflow):
            # We'll extract the filesystem anyways for a Flatpak instead of exporting
            # the docker image directly, so squash just slows things down.
            self.log.info('flatpak build, skipping plugin')
            return

        # This plugin is obsoleted. This line change is just for the test pass.
        if getattr(self.workflow, "skip_layer_squash", False):
            return  # enable build plugins to prevent unnecessary squashes
        if self.save_archive:
            output_path = os.path.join(self.workflow.source.workdir,
                                       EXPORTED_SQUASHED_IMAGE_NAME)
            metadata = {"path": output_path}
        else:
            output_path = None

        # Squash the image and output tarfile
        # If the parameter dont_load is set to True squashed image won't be
        # loaded in to Docker daemon. If it's set to False it will be loaded.
        new_id = Squash(log=self.log,
                        image=self.image,
                        from_layer=self.from_layer,
                        tag=self.tag,
                        output_path=output_path,
                        load_image=not self.dont_load).run()

        if ':' not in new_id:
            # Older versions of the daemon do not include the prefix
            new_id = 'sha256:{}'.format(new_id)

        if not self.dont_load:
            self.workflow.data.image_id = new_id

        if self.save_archive:
            metadata.update(
                get_exported_image_metadata(output_path,
                                            IMAGE_TYPE_DOCKER_ARCHIVE))
            # OSBS2 TBD exported_image_sequence will not work for multiple platform
            self.workflow.data.exported_image_sequence.append(metadata)
    def test_should_not_cleanup_after_squashing(self, v2_image):
        squash = Squash(self.log, 'image', self.docker_client, load_image=True)
        squash.run()

        v2_image.cleanup.assert_not_called()
 def test_handle_case_when_no_image_is_provided(self):
     squash = Squash(self.log, None, self.docker_client)
     with self.assertRaises(SquashError) as cm:
         squash.run()
     self.assertEquals(str(cm.exception), "Image is not provided")
Ejemplo n.º 14
0
    class SquashedImage(object):

        def __init__(self, image, number_of_layers=None, output_path=None, load_image=True, numeric=False, tmp_dir=None, log=None, development=False, tag=True):
            self.image = image
            self.number_of_layers = number_of_layers
            self.docker = TestIntegSquash.docker
            self.log = log or TestIntegSquash.log
            if tag:
                self.tag = "%s:squashed" % self.image.name
            else:
                self.tag = None
            self.output_path = output_path
            self.load_image = load_image
            self.numeric = numeric
            self.tmp_dir = tmp_dir
            self.development = development

        def __enter__(self):
            from_layer = self.number_of_layers

            if self.number_of_layers and not self.numeric:
                from_layer = self.docker.history(
                    self.image.tag)[self.number_of_layers]['Id']

            self.squash = Squash(
                self.log, self.image.tag, self.docker, tag=self.tag, from_layer=from_layer,
                output_path=self.output_path, load_image=self.load_image, tmp_dir=self.tmp_dir, development=self.development)
            self.tmp_tag = self.squash.tmp_tag

            self.image_id = self.squash.run()

            if not self.output_path:
                self.history = self.docker.history(self.image_id)

                if self.tag:
                    self.tar = self._save_image()

                    with tarfile.open(fileobj=self.tar, mode='r') as tar:
                        self.tarnames = tar.getnames()

                    self.squashed_layer = self._squashed_layer()
                    self.layers = [o['Id'] for o in self.docker.history(self.image_id)]
                    self.metadata = self.docker.inspect_image(self.image_id)

            return self

        def __exit__(self, exc_type, exc_val, exc_tb):
            if not (os.getenv('CI') or self.output_path):
                self.docker.remove_image(image=self.image_id, force=True)

        def _save_image(self):
            image = self.docker.get_image(self.tmp_tag)

            buf = BytesIO()
            for chunk in image:
                buf.write(chunk)
            buf.seek(0)  # Rewind

            return buf

        def _extract_file(self, name, tar_object):
            tar_object.seek(0)
            with tarfile.open(fileobj=tar_object, mode='r') as tar:
                member = tar.getmember(name)
                return tar.extractfile(member)

        def _squashed_layer(self):
            self.tar.seek(0)
            with tarfile.open(fileobj=self.tar, mode='r') as tar:
                self.squashed_layer_path = ImageHelper.top_layer_path(tar)
            return self._extract_file("%s/layer.tar" % self.squashed_layer_path, self.tar)

        def assertFileExists(self, name):
            self.squashed_layer.seek(0)  # Rewind
            with tarfile.open(fileobj=self.squashed_layer, mode='r') as tar:
                assert name in tar.getnames(
                ), "File '%s' was not found in the squashed files: %s" % (name, tar.getnames())

        def assertFileDoesNotExist(self, name):
            self.squashed_layer.seek(0)  # Rewind
            with tarfile.open(fileobj=self.squashed_layer, mode='r') as tar:
                assert name not in tar.getnames(
                ), "File '%s' was found in the squashed layer files: %s" % (name, tar.getnames())

        def assertFileIsNotHardLink(self, name):
            self.squashed_layer.seek(0)  # Rewind
            with tarfile.open(fileobj=self.squashed_layer, mode='r') as tar:
                member = tar.getmember(name)
                assert member.islnk(
                ) == False, "File '%s' should not be a hard link, but it is" % name

        def assert_target_tag_exists(self):
            if self.tag:
                self.squash._switch_tmp_image_to_target_tag()
                self.docker.inspect_image(self.tag)#raise exception if not exists
Ejemplo n.º 15
0
    def test_should_cleanup_after_squashing(self, v2_image):
        self.docker_client.inspect_image.return_value = {'Id': "abcdefgh"}
        squash = Squash(self.log, 'image', self.docker_client, load_image=True, cleanup=True)
        squash.run()

        self.docker_client.remove_image.assert_called_with('abcdefgh', force=False, noprune=False)
Ejemplo n.º 16
0
    def test_should_not_cleanup_after_squashing(self, v2_image):
        squash = Squash(self.log, 'image', self.docker_client, load_image=True)
        squash.run()

        v2_image.cleanup.assert_not_called()
Ejemplo n.º 17
0
 def test_exit_if_no_output_path_provided_and_loading_is_disabled_too(self):
     squash = Squash(self.log, 'image', self.docker_client, load_image=False, output_path=None)
     squash.run()
     self.log.warn.assert_called_with("No output path specified and loading into Docker is not selected either; squashed image would not accessible, proceeding with squashing doesn't make sense")
Ejemplo n.º 18
0
 def test_handle_case_when_no_image_is_provided(self):
     squash = Squash(self.log, None, self.docker_client)
     with self.assertRaises(SquashError) as cm:
         squash.run()
     self.assertEquals(
         str(cm.exception), "Image is not provided")