Esempio n. 1
0
class TestContainerImageOCI(object):
    @patch('kiwi.oci_tools.umoci.CommandCapabilities.has_option_in_help')
    @patch('kiwi.container.oci.RuntimeConfig')
    @patch('kiwi.container.oci.OCI')
    def setup(self, mock_OCI, mock_RuntimeConfig, mock_cmd_caps):
        oci = mock.Mock()
        mock_cmd_caps.return_value = True
        oci.container_dir = 'kiwi_oci_dir.XXXX/oci_layout'
        mock_OCI.return_value = oci
        self.oci = ContainerImageOCI(
            'root_dir', {
                'container_name': 'foo/bar',
                'additional_tags': ['current', 'foobar']
            }
        )

    @patch('kiwi.oci_tools.umoci.CommandCapabilities.has_option_in_help')
    def test_init_custom_args(self, mock_cmd_caps):
        mock_cmd_caps.return_value = True
        custom_args = {
            'container_name': 'foo',
            'container_tag': '1.0',
            'additional_tags': ['current', 'foobar'],
            'entry_command': ['/bin/bash', '-x'],
            'entry_subcommand': ['ls', '-l'],
            'maintainer': 'tux',
            'user': '******',
            'workingdir': '/root',
            'expose_ports': ['80', '42'],
            'volumes': ['/var/log', '/tmp'],
            'environment': {'PATH': '/bin', 'FOO': 'bar'},
            'labels': {'a': 'value', 'b': 'value'}
        }
        container = ContainerImageOCI(
            'root_dir', custom_args
        )
        assert container.oci_config == custom_args

    @patch('kiwi.oci_tools.umoci.CommandCapabilities.has_option_in_help')
    def test_init_without_custom_args(self, mock_cmd_caps):
        mock_cmd_caps.return_value = True
        container = ContainerImageOCI('root_dir')
        assert container.oci_config == {
            'container_name': 'kiwi-container',
            'container_tag': 'latest',
            'entry_subcommand': ['/bin/bash'],
            'history': {'created_by': 'KIWI {0}'.format(__version__)}
        }

    @patch('kiwi.oci_tools.umoci.CommandCapabilities.has_option_in_help')
    @patch('kiwi.defaults.Defaults.is_buildservice_worker')
    @patch_open
    def test_init_in_buildservice(
        self, mock_open, mock_buildservice, mock_cmd_caps
    ):
        mock_buildservice.return_value = True
        mock_cmd_caps.return_value = True
        handle = mock_open.return_value.__enter__.return_value
        handle.__iter__.return_value =\
            iter(['BUILD_DISTURL=obs://build.opensuse.org/some:project'])
        container = ContainerImageOCI('root_dir')
        mock_open.assert_called_once_with('/.buildenv')
        assert container.oci_config['labels'] == {
            'org.openbuildservice.disturl':
            'obs://build.opensuse.org/some:project'
        }

    @patch('kiwi.oci_tools.umoci.CommandCapabilities.has_option_in_help')
    @patch('kiwi.defaults.Defaults.is_buildservice_worker')
    @patch_open
    @patch('kiwi.logger.log.warning')
    def test_init_in_buildservice_without_disturl(
        self, mock_warn, mock_open, mock_buildservice, mock_cmd_caps
    ):
        mock_buildservice.return_value = True
        mock_cmd_caps.return_value = True
        handle = mock_open.return_value.__enter__.return_value
        handle.__iter__.return_value = iter(['line content'])
        container = ContainerImageOCI('root_dir')
        mock_open.assert_called_once_with('/.buildenv')
        assert 'labels' not in container.oci_config
        assert mock_warn.called

    @patch('kiwi.container.oci.ArchiveTar')
    @patch('kiwi.container.oci.Defaults.get_shared_cache_location')
    def test_create(self, mock_cache, mock_tar):
        oci_tarfile = mock.Mock()
        mock_tar.return_value = oci_tarfile

        mock_cache.return_value = 'var/cache/kiwi'

        self.oci.runtime_config.get_container_compression = mock.Mock(
            return_value='xz'
        )

        self.oci.create('result.tar', None)

        self.oci.oci.init_layout.assert_called_once_with(False)
        self.oci.oci.unpack.assert_called_once_with()
        self.oci.oci.sync_rootfs.assert_called_once_with(
            'root_dir/', [
                'image', '.profile', '.kconfig', '.buildenv',
                'var/cache/kiwi', 'boot', 'dev', 'sys', 'proc'
            ]
        )
        self.oci.oci.repack.assert_called_once_with()
        self.oci.oci.set_config.assert_called_once_with({
            'container_name': 'foo/bar',
            'additional_tags': ['current', 'foobar'],
            'container_tag': 'latest',
            'entry_subcommand': ['/bin/bash'],
            'history': {'created_by': 'KIWI {0}'.format(__version__)}
        }, False)
        assert self.oci.oci.add_tag.call_args_list == [
            call('current'), call('foobar')
        ]
        self.oci.oci.garbage_collect.assert_called_once_with()
        mock_tar.assert_called_once_with('result.tar')
        oci_tarfile.create_xz_compressed.assert_called_once_with(
            'kiwi_oci_dir.XXXX/oci_layout',
            xz_options=self.oci.runtime_config.get_xz_options.return_value
        )

        self.oci.runtime_config.get_container_compression = mock.Mock(
            return_value=None
        )

        self.oci.create('result.tar', None)

        oci_tarfile.create.assert_called_once_with(
            'kiwi_oci_dir.XXXX/oci_layout'
        )

    @patch('kiwi.container.oci.ArchiveTar')
    @patch('kiwi.container.oci.Path.create')
    @patch('kiwi.container.oci.Defaults.get_shared_cache_location')
    def test_create_derived(
        self, mock_cache, mock_create, mock_tar
    ):
        mock_cache.return_value = 'var/cache/kiwi'

        self.oci.create('result.tar', 'root_dir/image/image_file')
        mock_create.assert_called_once_with('kiwi_oci_dir.XXXX/oci_layout')

        self.oci.oci.init_layout.assert_called_once_with(True)
        self.oci.oci.unpack.assert_called_once_with()
        self.oci.oci.sync_rootfs.assert_called_once_with(
            'root_dir/', [
                'image', '.profile', '.kconfig', '.buildenv',
                'var/cache/kiwi', 'boot', 'dev', 'sys', 'proc'
            ]
        )
        self.oci.oci.repack.assert_called_once_with()
        self.oci.oci.set_config.assert_called_once_with({
            'container_name': 'foo/bar',
            'additional_tags': ['current', 'foobar'],
            'container_tag': 'latest',
            'entry_subcommand': ['/bin/bash'],
            'history': {'created_by': 'KIWI {0}'.format(__version__)}
        }, True)
        assert self.oci.oci.add_tag.call_args_list == [
            call('current'), call('foobar')
        ]
        self.oci.oci.garbage_collect.assert_called_once_with()

        assert mock_tar.call_args_list == [
            call('root_dir/image/image_file'), call('result.tar')
        ]
Esempio n. 2
0
class TestContainerImageOCI(object):
    def setup(self):
        self.oci = ContainerImageOCI('root_dir', {'container_name': 'foo/bar'})

    def test_init_custom_args(self):
        custom_args = {
            'container_name':
            'foo',
            'container_tag':
            '1.0',
            'entry_command':
            ['--config.entrypoint=/bin/bash', '--config.entrypoint=-x'],
            'entry_subcommand': ['--config.cmd=ls', '--config.cmd=-l'],
            'maintainer': ['--author=tux'],
            'user': ['--config.user=root'],
            'workingdir': ['--config.workingdir=/root'],
            'expose_ports':
            ['--config.exposedports=80', '--config.exposedports=42'],
            'volumes': ['--config.volume=/var/log', '--config.volume=/tmp'],
            'environment': ['--config.env=PATH=/bin', '--config.env=FOO=bar'],
            'labels': ['--config.label=a=value', '--config.label=b=value'],
            'xz_options': ['-a', '-b']
        }
        container = ContainerImageOCI('root_dir', custom_args)
        assert container.container_name == custom_args['container_name']
        assert container.container_tag == custom_args['container_tag']
        assert container.entry_command == custom_args['entry_command']
        assert container.entry_subcommand == custom_args['entry_subcommand']
        assert container.maintainer == custom_args['maintainer']
        assert container.user == custom_args['user']
        assert container.workingdir == custom_args['workingdir']
        assert container.expose_ports == custom_args['expose_ports']
        assert container.volumes == custom_args['volumes']
        assert container.environment == custom_args['environment']
        assert container.labels == custom_args['labels']
        assert container.xz_options == custom_args['xz_options']

    def test_init_without_custom_args(self):
        container = ContainerImageOCI('root_dir')
        assert container.container_name == 'kiwi-container'
        assert container.container_tag == 'latest'

    @patch('kiwi.defaults.Defaults.is_buildservice_worker')
    @patch_open
    def test_init_in_buildservice(self, mock_open, mock_buildservice):
        mock_buildservice.return_value = True
        handle = mock_open.return_value.__enter__.return_value
        handle.__iter__.return_value =\
            iter(['BUILD_DISTURL=obs://build.opensuse.org/some:project'])
        container = ContainerImageOCI('root_dir')
        mock_open.assert_called_once_with('/.buildenv')
        assert container.labels == [
            '--config.label=org.openbuildservice.disturl='
            'obs://build.opensuse.org/some:project'
        ]

    @patch('kiwi.defaults.Defaults.is_buildservice_worker')
    @patch_open
    @patch('kiwi.logger.log.warning')
    def test_init_in_buildservice_without_disturl(self, mock_warn, mock_open,
                                                  mock_buildservice):
        mock_buildservice.return_value = True
        handle = mock_open.return_value.__enter__.return_value
        handle.__iter__.return_value = iter(['line content'])
        container = ContainerImageOCI('root_dir')
        mock_open.assert_called_once_with('/.buildenv')
        assert container.labels == []
        assert mock_warn.called

    @patch('kiwi.container.oci.Path.wipe')
    def test_del(self, mock_wipe):
        self.oci.oci_dir = 'dir_a'
        self.oci.oci_root_dir = 'dir_b'
        self.oci.__del__()
        assert mock_wipe.call_args_list == [call('dir_a'), call('dir_b')]

    @patch('kiwi.container.oci.datetime')
    @patch('kiwi.container.oci.ArchiveTar')
    @patch('kiwi.container.oci.Command.run')
    @patch('kiwi.container.oci.DataSync')
    @patch('kiwi.container.oci.mkdtemp')
    @patch('kiwi.container.oci.Defaults.get_shared_cache_location')
    def test_create(self, mock_cache, mock_mkdtemp, mock_sync, mock_command,
                    mock_tar, mock_datetime):
        strftime = mock.Mock()
        strftime.strftime = mock.Mock(return_value='current_date')
        mock_datetime.utcnow = mock.Mock(return_value=strftime)

        mock_cache.return_value = 'var/cache/kiwi'
        oci_root = mock.Mock()
        mock_sync.return_value = oci_root
        tmpdirs = ['kiwi_oci_root_dir', 'kiwi_oci_dir']

        def call_mkdtemp(prefix):
            return tmpdirs.pop()

        mock_mkdtemp.side_effect = call_mkdtemp

        self.oci.create('result.tar.xz', None)

        assert mock_command.call_args_list == [
            call(['umoci', 'init', '--layout', 'kiwi_oci_dir/umoci_layout']),
            call([
                'umoci', 'new', '--image', 'kiwi_oci_dir/umoci_layout:latest'
            ]),
            call([
                'umoci', 'unpack', '--image',
                'kiwi_oci_dir/umoci_layout:latest', 'kiwi_oci_root_dir'
            ]),
            call([
                'umoci', 'repack', '--image',
                'kiwi_oci_dir/umoci_layout:latest', 'kiwi_oci_root_dir'
            ]),
            call([
                'umoci', 'config', '--config.cmd=/bin/bash', '--image',
                'kiwi_oci_dir/umoci_layout:latest', '--created', 'current_date'
            ]),
            call(['umoci', 'gc', '--layout', 'kiwi_oci_dir/umoci_layout'])
        ]
        mock_sync.assert_called_once_with('root_dir/',
                                          'kiwi_oci_root_dir/rootfs')
        oci_root.sync_data.assert_called_once_with(
            exclude=[
                'image',
                '.profile',
                '.kconfig',
                '.buildenv',
                'var/cache/kiwi',
                'boot',
                'dev',
                'sys',
                'proc',
            ],
            options=['-a', '-H', '-X', '-A', '--delete'])

        mock_tar.called_once_with('result.tar.xz')

    @patch('kiwi.container.oci.datetime')
    @patch('kiwi.container.oci.ArchiveTar')
    @patch('kiwi.container.oci.Command.run')
    @patch('kiwi.container.oci.DataSync')
    @patch('kiwi.container.oci.mkdtemp')
    @patch('kiwi.container.oci.Path.create')
    @patch('kiwi.container.oci.Defaults.get_shared_cache_location')
    def test_create_derived(self, mock_cache, mock_create, mock_mkdtemp,
                            mock_sync, mock_command, mock_tar, mock_datetime):
        strftime = mock.Mock()
        strftime.strftime = mock.Mock(return_value='current_date')
        mock_datetime.utcnow = mock.Mock(return_value=strftime)

        mock_cache.return_value = 'var/cache/kiwi'
        oci_root = mock.Mock()
        mock_sync.return_value = oci_root
        tmpdirs = ['kiwi_oci_root_dir', 'kiwi_oci_dir']

        def call_mkdtemp(prefix):
            return tmpdirs.pop()

        mock_mkdtemp.side_effect = call_mkdtemp

        self.oci.create('result.tar.xz', 'root_dir/image/image_file')

        mock_create.assert_called_once_with('kiwi_oci_dir/umoci_layout')

        assert mock_command.call_args_list == [
            call([
                'umoci', 'config', '--image',
                'kiwi_oci_dir/umoci_layout:base_layer', '--tag', 'latest'
            ]),
            call([
                'umoci', 'unpack', '--image',
                'kiwi_oci_dir/umoci_layout:latest', 'kiwi_oci_root_dir'
            ]),
            call([
                'umoci', 'repack', '--image',
                'kiwi_oci_dir/umoci_layout:latest', 'kiwi_oci_root_dir'
            ]),
            call([
                'umoci', 'config', '--config.cmd=/bin/bash', '--image',
                'kiwi_oci_dir/umoci_layout:latest', '--created', 'current_date'
            ]),
            call(['umoci', 'gc', '--layout', 'kiwi_oci_dir/umoci_layout'])
        ]
        mock_sync.assert_called_once_with('root_dir/',
                                          'kiwi_oci_root_dir/rootfs')
        oci_root.sync_data.assert_called_once_with(
            exclude=[
                'image', '.profile', '.kconfig', '.buildenv', 'var/cache/kiwi',
                'boot', 'dev', 'sys', 'proc'
            ],
            options=['-a', '-H', '-X', '-A', '--delete'])
        mock_tar.call_args_list == [
            call('root_dir/image/image_file'),
            call('result.tar.xz')
        ]
class TestContainerImageOCI(object):
    @patch('kiwi.container.oci.RuntimeConfig')
    def setup(self, mock_RuntimeConfig):
        self.oci = ContainerImageOCI(
            'root_dir', {
                'container_name': 'foo/bar',
                'additional_tags': ['current', 'foobar']
            }
        )

    def test_init_custom_args(self):
        custom_args = {
            'container_name': 'foo',
            'container_tag': '1.0',
            'additional_tags': ['current', 'foobar'],
            'entry_command': [
                '--config.entrypoint=/bin/bash',
                '--config.entrypoint=-x'
            ],
            'entry_subcommand': [
                '--config.cmd=ls',
                '--config.cmd=-l'
            ],
            'maintainer': ['--author=tux'],
            'user': ['--config.user=root'],
            'workingdir': ['--config.workingdir=/root'],
            'expose_ports': [
                '--config.exposedports=80',
                '--config.exposedports=42'
            ],
            'volumes': [
                '--config.volume=/var/log',
                '--config.volume=/tmp'
            ],
            'environment': [
                '--config.env=PATH=/bin',
                '--config.env=FOO=bar'
            ],
            'labels': [
                '--config.label=a=value',
                '--config.label=b=value'
            ]
        }
        container = ContainerImageOCI(
            'root_dir', custom_args
        )
        assert container.container_name == custom_args['container_name']
        assert container.container_tag == custom_args['container_tag']
        assert container.entry_command == custom_args['entry_command']
        assert container.entry_subcommand == custom_args['entry_subcommand']
        assert container.maintainer == custom_args['maintainer']
        assert container.user == custom_args['user']
        assert container.workingdir == custom_args['workingdir']
        assert container.expose_ports == custom_args['expose_ports']
        assert container.volumes == custom_args['volumes']
        assert container.environment == custom_args['environment']
        assert container.labels == custom_args['labels']
        assert container.additional_tags == custom_args['additional_tags']

    def test_init_without_custom_args(self):
        container = ContainerImageOCI('root_dir')
        assert container.container_name == 'kiwi-container'
        assert container.container_tag == 'latest'
        assert container.additional_tags == []

    @patch('kiwi.defaults.Defaults.is_buildservice_worker')
    @patch_open
    def test_init_in_buildservice(self, mock_open, mock_buildservice):
        mock_buildservice.return_value = True
        handle = mock_open.return_value.__enter__.return_value
        handle.__iter__.return_value =\
            iter(['BUILD_DISTURL=obs://build.opensuse.org/some:project'])
        container = ContainerImageOCI('root_dir')
        mock_open.assert_called_once_with('/.buildenv')
        assert container.labels == [
            '--config.label=org.openbuildservice.disturl='
            'obs://build.opensuse.org/some:project'
        ]

    @patch('kiwi.defaults.Defaults.is_buildservice_worker')
    @patch_open
    @patch('kiwi.logger.log.warning')
    def test_init_in_buildservice_without_disturl(
        self, mock_warn, mock_open, mock_buildservice
    ):
        mock_buildservice.return_value = True
        handle = mock_open.return_value.__enter__.return_value
        handle.__iter__.return_value = iter(['line content'])
        container = ContainerImageOCI('root_dir')
        mock_open.assert_called_once_with('/.buildenv')
        assert container.labels == []
        assert mock_warn.called

    @patch('kiwi.container.oci.Path.wipe')
    def test_del(self, mock_wipe):
        self.oci.oci_dir = 'dir_a'
        self.oci.oci_root_dir = 'dir_b'
        self.oci.__del__()
        assert mock_wipe.call_args_list == [
            call('dir_a'), call('dir_b')
        ]

    @patch('kiwi.container.oci.datetime')
    @patch('kiwi.container.oci.ArchiveTar')
    @patch('kiwi.container.oci.Command.run')
    @patch('kiwi.container.oci.DataSync')
    @patch('kiwi.container.oci.mkdtemp')
    @patch('kiwi.container.oci.Defaults.get_shared_cache_location')
    def test_create(
        self, mock_cache, mock_mkdtemp,
        mock_sync, mock_command, mock_tar, mock_datetime
    ):
        oci_tarfile = mock.Mock()
        mock_tar.return_value = oci_tarfile
        strftime = mock.Mock()
        strftime.strftime = mock.Mock(return_value='current_date')
        mock_datetime.utcnow = mock.Mock(
            return_value=strftime
        )

        mock_cache.return_value = 'var/cache/kiwi'
        oci_root = mock.Mock()
        mock_sync.return_value = oci_root
        tmpdirs = ['kiwi_oci_root_dir', 'kiwi_oci_dir']

        def call_mkdtemp(prefix):
            return tmpdirs.pop()

        mock_mkdtemp.side_effect = call_mkdtemp

        self.oci.runtime_config.get_container_compression = mock.Mock(
            return_value='xz'
        )

        self.oci.create('result.tar', None)

        assert mock_command.call_args_list == [
            call([
                'umoci', 'init', '--layout',
                'kiwi_oci_dir/umoci_layout'
            ]),
            call([
                'umoci', 'new', '--image',
                'kiwi_oci_dir/umoci_layout:latest'
            ]),
            call([
                'umoci', 'unpack', '--image',
                'kiwi_oci_dir/umoci_layout:latest', 'kiwi_oci_root_dir'
            ]),
            call([
                'umoci', 'repack', '--image',
                'kiwi_oci_dir/umoci_layout:latest', 'kiwi_oci_root_dir'
            ]),
            call([
                'umoci', 'config', '--image',
                'kiwi_oci_dir/umoci_layout:latest', '--tag', 'current'
            ]),
            call([
                'umoci', 'config', '--image',
                'kiwi_oci_dir/umoci_layout:latest', '--tag', 'foobar'
            ]),
            call([
                'umoci', 'config', '--config.cmd=/bin/bash', '--image',
                'kiwi_oci_dir/umoci_layout:latest', '--created', 'current_date'
            ]),
            call([
                'umoci', 'gc', '--layout', 'kiwi_oci_dir/umoci_layout'
            ])
        ]
        mock_sync.assert_called_once_with(
            'root_dir/', 'kiwi_oci_root_dir/rootfs'
        )
        oci_root.sync_data.assert_called_once_with(
            exclude=[
                'image', '.profile', '.kconfig', '.buildenv',
                'var/cache/kiwi', 'boot', 'dev', 'sys', 'proc',
            ],
            options=['-a', '-H', '-X', '-A', '--delete']
        )
        mock_tar.assert_called_once_with('result.tar')
        oci_tarfile.create_xz_compressed.assert_called_once_with(
            'kiwi_oci_dir/umoci_layout',
            xz_options=self.oci.runtime_config.get_xz_options.return_value
        )

        tmpdirs = ['kiwi_oci_root_dir', 'kiwi_oci_dir']
        self.oci.runtime_config.get_container_compression = mock.Mock(
            return_value=None
        )

        self.oci.create('result.tar', None)

        oci_tarfile.create.assert_called_once_with(
            'kiwi_oci_dir/umoci_layout'
        )

    @patch('kiwi.container.oci.datetime')
    @patch('kiwi.container.oci.ArchiveTar')
    @patch('kiwi.container.oci.Command.run')
    @patch('kiwi.container.oci.DataSync')
    @patch('kiwi.container.oci.mkdtemp')
    @patch('kiwi.container.oci.Path.create')
    @patch('kiwi.container.oci.Defaults.get_shared_cache_location')
    def test_create_derived(
        self, mock_cache, mock_create, mock_mkdtemp,
        mock_sync, mock_command, mock_tar, mock_datetime
    ):
        strftime = mock.Mock()
        strftime.strftime = mock.Mock(return_value='current_date')
        mock_datetime.utcnow = mock.Mock(
            return_value=strftime
        )

        mock_cache.return_value = 'var/cache/kiwi'
        oci_root = mock.Mock()
        mock_sync.return_value = oci_root
        tmpdirs = ['kiwi_oci_root_dir', 'kiwi_oci_dir']

        def call_mkdtemp(prefix):
            return tmpdirs.pop()

        mock_mkdtemp.side_effect = call_mkdtemp

        self.oci.create('result.tar', 'root_dir/image/image_file')

        mock_create.assert_called_once_with('kiwi_oci_dir/umoci_layout')

        assert mock_command.call_args_list == [
            call([
                'umoci', 'config', '--image',
                'kiwi_oci_dir/umoci_layout:base_layer', '--tag', 'latest'
            ]),
            call([
                'umoci', 'unpack', '--image',
                'kiwi_oci_dir/umoci_layout:latest', 'kiwi_oci_root_dir'
            ]),
            call([
                'umoci', 'repack', '--image',
                'kiwi_oci_dir/umoci_layout:latest', 'kiwi_oci_root_dir'
            ]),
            call([
                'umoci', 'config', '--image',
                'kiwi_oci_dir/umoci_layout:latest', '--tag', 'current'
            ]),
            call([
                'umoci', 'config', '--image',
                'kiwi_oci_dir/umoci_layout:latest', '--tag', 'foobar'
            ]),
            call([
                'umoci', 'config', '--config.cmd=/bin/bash', '--image',
                'kiwi_oci_dir/umoci_layout:latest', '--created', 'current_date'
            ]),
            call([
                'umoci', 'gc', '--layout', 'kiwi_oci_dir/umoci_layout'
            ])
        ]
        mock_sync.assert_called_once_with(
            'root_dir/', 'kiwi_oci_root_dir/rootfs'
        )
        oci_root.sync_data.assert_called_once_with(
            exclude=[
                'image', '.profile', '.kconfig', '.buildenv',
                'var/cache/kiwi', 'boot', 'dev', 'sys', 'proc'
            ],
            options=['-a', '-H', '-X', '-A', '--delete']
        )
        assert mock_tar.call_args_list == [
            call('root_dir/image/image_file'), call('result.tar')
        ]
Esempio n. 4
0
class TestContainerImageOCI:
    @fixture(autouse=True)
    def inject_fixtures(self, caplog):
        self._caplog = caplog

    @patch('kiwi.oci_tools.umoci.CommandCapabilities.has_option_in_help')
    def setup(self, mock_cmd_caps):
        mock_cmd_caps.return_value = True
        self.runtime_config = mock.Mock()
        self.runtime_config.get_container_compression = mock.Mock(
            return_value=None)
        kiwi.container.oci.RuntimeConfig = mock.Mock(
            return_value=self.runtime_config)
        self.oci = ContainerImageOCI('root_dir', 'docker-archive', {
            'container_name': 'foo/bar',
            'additional_tags': ['current', 'foobar']
        })

    @patch('kiwi.oci_tools.umoci.CommandCapabilities.has_option_in_help')
    def test_init_custom_args(self, mock_cmd_caps):
        mock_cmd_caps.return_value = True
        custom_args = {
            'container_name': 'foo',
            'container_tag': '1.0',
            'additional_tags': ['current', 'foobar'],
            'entry_command': ['/bin/bash', '-x'],
            'entry_subcommand': ['ls', '-l'],
            'maintainer': 'tux',
            'user': '******',
            'workingdir': '/root',
            'expose_ports': ['80', '42'],
            'volumes': ['/var/log', '/tmp'],
            'environment': {
                'PATH': '/bin',
                'FOO': 'bar'
            },
            'labels': {
                'a': 'value',
                'b': 'value'
            }
        }
        container = ContainerImageOCI('root_dir', 'oci-archive', custom_args)
        assert container.oci_config == custom_args

    @patch('kiwi.oci_tools.umoci.CommandCapabilities.has_option_in_help')
    def test_init_without_custom_args(self, mock_cmd_caps):
        mock_cmd_caps.return_value = True
        container = ContainerImageOCI('root_dir', 'oci-archive')
        assert container.oci_config == {
            'container_name': 'kiwi-container',
            'container_tag': 'latest',
            'history': {
                'created_by': 'KIWI {0}'.format(__version__)
            }
        }

    @patch('kiwi.container.oci.RuntimeConfig')
    @patch('kiwi.oci_tools.umoci.CommandCapabilities.has_option_in_help')
    @patch('kiwi.defaults.Defaults.is_buildservice_worker')
    def test_init_in_buildservice(self, mock_buildservice, mock_cmd_caps,
                                  mock_RuntimeConfig):
        mock_buildservice.return_value = True
        mock_cmd_caps.return_value = True

        m_open = mock_open()
        with patch('builtins.open', m_open, create=True):
            m_open.return_value.__iter__ = lambda _:\
                iter(['BUILD_DISTURL=obs://build.opensuse.org/some:project'])
            container = ContainerImageOCI('root_dir', 'oci-archive')

        m_open.assert_called_once_with('/.buildenv')
        assert container.oci_config['labels'] == {
            'org.openbuildservice.disturl':
            'obs://build.opensuse.org/some:project'
        }

        m_open = mock_open()
        with patch('builtins.open', m_open, create=True):
            m_open.return_value.__iter__ = lambda _:\
                iter(['BUILD_DISTURL=obs://build.opensuse.org/some:project'])
            container = ContainerImageOCI('root_dir', 'oci-archive',
                                          {'labels': {
                                              'label': 'value'
                                          }})

        m_open.assert_called_once_with('/.buildenv')
        assert container.oci_config['labels'] == {
            'label': 'value',
            'org.openbuildservice.disturl':
            'obs://build.opensuse.org/some:project'
        }

    @patch('kiwi.container.oci.RuntimeConfig')
    @patch('kiwi.oci_tools.umoci.CommandCapabilities.has_option_in_help')
    @patch('kiwi.defaults.Defaults.is_buildservice_worker')
    def test_init_in_buildservice_without_disturl(self, mock_buildservice,
                                                  mock_cmd_caps,
                                                  mock_RuntimeConfig):
        mock_buildservice.return_value = True
        mock_cmd_caps.return_value = True

        m_open = mock_open()
        with patch('builtins.open', m_open, create=True):
            m_open.return_value.__iter__ = lambda _: iter(['line content'])
            with self._caplog.at_level(logging.WARNING):
                container = ContainerImageOCI('root_dir', 'oci-archive')

        m_open.assert_called_once_with('/.buildenv')
        assert 'labels' not in container.oci_config

    @patch('kiwi.container.oci.OCI')
    @patch('kiwi.container.oci.Defaults.get_shared_cache_location')
    def test_create_oci_archive(self, mock_cache, mock_OCI):
        mock_cache.return_value = 'var/cache/kiwi'
        mock_oci = mock.Mock()
        mock_OCI.new.return_value = mock_oci

        self.oci.archive_transport = 'oci-archive'
        self.oci.create('result.tar', None)

        mock_oci.init_container.assert_called_once_with()
        mock_oci.unpack.assert_called_once_with()
        mock_oci.sync_rootfs.assert_called_once_with('root_dir', [
            'image', '.profile', '.kconfig', 'run/*', 'tmp/*', '.buildenv',
            'var/cache/kiwi', 'dev/*', 'sys/*', 'proc/*'
        ])
        mock_oci.repack.assert_called_once_with({
            'container_name':
            'foo/bar',
            'additional_tags': ['current', 'foobar'],
            'container_tag':
            'latest',
            'entry_subcommand': ['/bin/bash'],
            'history': {
                'created_by': 'KIWI {0}'.format(__version__)
            }
        })
        mock_oci.set_config.assert_called_once_with({
            'container_name':
            'foo/bar',
            'additional_tags': ['current', 'foobar'],
            'container_tag':
            'latest',
            'entry_subcommand': ['/bin/bash'],
            'history': {
                'created_by': 'KIWI {0}'.format(__version__)
            }
        })
        mock_oci.post_process.assert_called_once_with()
        mock_oci.export_container_image.assert_called_once_with(
            'result.tar', 'oci-archive', 'latest', [])

    @patch('kiwi.container.oci.OCI')
    @patch('kiwi.container.oci.Defaults.get_shared_cache_location')
    def test_create_derived_docker_archive(self, mock_cache, mock_OCI):
        mock_cache.return_value = 'var/cache/kiwi'
        mock_oci = mock.Mock()
        mock_OCI.new.return_value = mock_oci

        self.runtime_config.get_container_compression.return_value = 'xz'

        self.oci.create('result.tar', 'root_dir/image/image_file')

        mock_oci.import_container_image.assert_called_once_with(
            'oci-archive:root_dir/image/image_file:base_layer')
        mock_oci.unpack.assert_called_once_with()
        mock_oci.sync_rootfs.assert_called_once_with('root_dir', [
            'image', '.profile', '.kconfig', 'run/*', 'tmp/*', '.buildenv',
            'var/cache/kiwi', 'dev/*', 'sys/*', 'proc/*'
        ])
        mock_oci.repack.assert_called_once_with({
            'container_name':
            'foo/bar',
            'additional_tags': ['current', 'foobar'],
            'container_tag':
            'latest',
            'history': {
                'created_by': 'KIWI {0}'.format(__version__)
            }
        })
        mock_oci.set_config.assert_called_once_with({
            'container_name':
            'foo/bar',
            'additional_tags': ['current', 'foobar'],
            'container_tag':
            'latest',
            'history': {
                'created_by': 'KIWI {0}'.format(__version__)
            }
        })
        mock_oci.post_process.assert_called_once_with()
        mock_oci.export_container_image.assert_called_once_with(
            'result.tar', 'docker-archive', 'foo/bar:latest',
            ['foo/bar:current', 'foo/bar:foobar'])
class TestContainerImageOCI(object):
    def setup(self):
        self.oci = ContainerImageOCI(
            'root_dir', {
                'container_name': 'foo/bar'
            }
        )

    def test_init_custom_args(self):
        ContainerImageOCI(
            'root_dir', {
                'container_name': 'foo',
                'container_tag': '1.0',
                'entry_command': [
                    "--config.entrypoint=/bin/bash",
                    "--config.entrypoint=-x"
                ],
                'entry_subcommand': [
                    "--config.cmd=ls",
                    "--config.cmd=-l"
                ],
                'maintainer': ['--author=tux'],
                'user': ['--config.user=root'],
                'workingdir': ['--config.workingdir=/root'],
                'expose_ports': [
                    "--config.exposedports=80",
                    "--config.exposedports=42"
                ],
                'volumes': [
                    "--config.volume=/var/log",
                    "--config.volume=/tmp"
                ],
                'environment': [
                    "--config.env=PATH=/bin'",
                    "--config.env=FOO=bar"
                ],
                'labels': [
                    "--config.label=a=value",
                    "--config.label=b=value"
                ]
            }
        )

    @patch('kiwi.container.oci.Path.wipe')
    def test_del(self, mock_wipe):
        self.oci.oci_dir = 'dir_a'
        self.oci.oci_root_dir = 'dir_b'
        self.oci.__del__()
        assert mock_wipe.call_args_list == [
            call('dir_a'), call('dir_b')
        ]

    @patch('kiwi.container.oci.datetime')
    @patch('kiwi.container.oci.ArchiveTar')
    @patch('kiwi.container.oci.Command.run')
    @patch('kiwi.container.oci.DataSync')
    @patch('kiwi.container.oci.mkdtemp')
    @patch('kiwi.container.oci.Defaults.get_shared_cache_location')
    def test_create(
        self, mock_cache, mock_mkdtemp,
        mock_sync, mock_command, mock_tar, mock_datetime
    ):
        strftime = mock.Mock()
        strftime.strftime = mock.Mock(return_value='current_date')
        mock_datetime.utcnow = mock.Mock(
            return_value=strftime
        )

        mock_cache.return_value = 'var/cache/kiwi'
        oci_root = mock.Mock()
        mock_sync.return_value = oci_root
        tmpdirs = ['kiwi_oci_root_dir', 'kiwi_oci_dir']

        def call_mkdtemp(prefix):
            return tmpdirs.pop()

        mock_mkdtemp.side_effect = call_mkdtemp

        self.oci.create('result.tar.xz', None)

        assert mock_command.call_args_list == [
            call([
                'umoci', 'init', '--layout',
                'kiwi_oci_dir/umoci_layout'
            ]),
            call([
                'umoci', 'new', '--image',
                'kiwi_oci_dir/umoci_layout:latest'
            ]),
            call([
                'umoci', 'unpack', '--image',
                'kiwi_oci_dir/umoci_layout:latest', 'kiwi_oci_root_dir'
            ]),
            call([
                'umoci', 'repack', '--image',
                'kiwi_oci_dir/umoci_layout:latest', 'kiwi_oci_root_dir'
            ]),
            call([
                'umoci', 'config', '--config.cmd=/bin/bash', '--image',
                'kiwi_oci_dir/umoci_layout:latest', '--created', 'current_date'
            ]),
            call([
                'umoci', 'gc', '--layout', 'kiwi_oci_dir/umoci_layout'
            ])
        ]
        mock_sync.assert_called_once_with(
            'root_dir/', 'kiwi_oci_root_dir/rootfs'
        )
        oci_root.sync_data.assert_called_once_with(
            exclude=[
                'image', '.profile', '.kconfig', 'boot', 'dev', 'sys', 'proc',
                'var/cache/kiwi'
            ],
            options=['-a', '-H', '-X', '-A', '--delete']
        )

        mock_tar.called_once_with('result.tar.xz')

    @patch('kiwi.container.oci.datetime')
    @patch('kiwi.container.oci.ArchiveTar')
    @patch('kiwi.container.oci.Command.run')
    @patch('kiwi.container.oci.DataSync')
    @patch('kiwi.container.oci.mkdtemp')
    @patch('kiwi.container.oci.Path.create')
    @patch('kiwi.container.oci.Defaults.get_shared_cache_location')
    def test_create_derived(
        self, mock_cache, mock_create, mock_mkdtemp,
        mock_sync, mock_command, mock_tar, mock_datetime
    ):
        strftime = mock.Mock()
        strftime.strftime = mock.Mock(return_value='current_date')
        mock_datetime.utcnow = mock.Mock(
            return_value=strftime
        )

        mock_cache.return_value = 'var/cache/kiwi'
        oci_root = mock.Mock()
        mock_sync.return_value = oci_root
        tmpdirs = ['kiwi_oci_root_dir', 'kiwi_oci_dir']

        def call_mkdtemp(prefix):
            return tmpdirs.pop()

        mock_mkdtemp.side_effect = call_mkdtemp

        self.oci.create('result.tar.xz', 'root_dir/image/image_file')

        mock_create.assert_called_once_with('kiwi_oci_dir/umoci_layout')

        assert mock_command.call_args_list == [
            call([
                'umoci', 'config', '--image',
                'kiwi_oci_dir/umoci_layout', '--tag', 'latest'
            ]),
            call([
                'umoci', 'unpack', '--image',
                'kiwi_oci_dir/umoci_layout:latest', 'kiwi_oci_root_dir'
            ]),
            call([
                'umoci', 'repack', '--image',
                'kiwi_oci_dir/umoci_layout:latest', 'kiwi_oci_root_dir'
            ]),
            call([
                'umoci', 'config', '--config.cmd=/bin/bash', '--image',
                'kiwi_oci_dir/umoci_layout:latest', '--created', 'current_date'
            ]),
            call([
                'umoci', 'gc', '--layout', 'kiwi_oci_dir/umoci_layout'
            ])
        ]
        mock_sync.assert_called_once_with(
            'root_dir/', 'kiwi_oci_root_dir/rootfs'
        )
        oci_root.sync_data.assert_called_once_with(
            exclude=[
                'image', '.profile', '.kconfig', 'boot', 'dev', 'sys', 'proc',
                'var/cache/kiwi'
            ],
            options=['-a', '-H', '-X', '-A', '--delete']
        )
        mock_tar.call_args_list == [
            call('root_dir/image/image_file'), call('result.tar.xz')
        ]