Refactor container factory classes
This commit refactors the container related classes to turn them into proper factory classes and also includes type hints to facilitate it's use from an API POV. Related to #1498
This commit is contained in:
parent
998d473bc0
commit
99be52baec
@ -113,7 +113,7 @@ class ContainerBuilder:
|
||||
log.info(
|
||||
'Setting up %s container', self.requested_container_type
|
||||
)
|
||||
container_setup = ContainerSetup(
|
||||
container_setup = ContainerSetup.new(
|
||||
self.requested_container_type, self.root_dir,
|
||||
self.container_config
|
||||
)
|
||||
@ -130,7 +130,7 @@ class ContainerBuilder:
|
||||
log.info(
|
||||
'--> Creating container image'
|
||||
)
|
||||
container_image = ContainerImage(
|
||||
container_image = ContainerImage.new(
|
||||
self.requested_container_type, self.root_dir, self.container_config
|
||||
)
|
||||
self.filename = container_image.create(
|
||||
|
||||
@ -15,16 +15,18 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with kiwi. If not, see <http://www.gnu.org/licenses/>
|
||||
#
|
||||
# project
|
||||
from kiwi.container.oci import ContainerImageOCI
|
||||
from kiwi.container.appx import ContainerImageAppx
|
||||
import importlib
|
||||
from abc import (
|
||||
ABCMeta,
|
||||
abstractmethod
|
||||
)
|
||||
|
||||
from kiwi.exceptions import (
|
||||
KiwiContainerImageSetupError
|
||||
)
|
||||
|
||||
|
||||
class ContainerImage:
|
||||
class ContainerImage(metaclass=ABCMeta):
|
||||
"""
|
||||
**Container Image factory**
|
||||
|
||||
@ -32,20 +34,29 @@ class ContainerImage:
|
||||
:param string root_dir: root directory path name
|
||||
:param dict custom_args: custom arguments
|
||||
"""
|
||||
def __new__(self, name, root_dir, custom_args=None):
|
||||
if name == 'docker':
|
||||
return ContainerImageOCI(
|
||||
root_dir, 'docker-archive', custom_args=custom_args
|
||||
@abstractmethod
|
||||
def __init__(self) -> None:
|
||||
return None # pragma: no cover
|
||||
|
||||
@staticmethod
|
||||
def new(name: str, root_dir: str, custom_args: dict = None):
|
||||
name_map = {
|
||||
'docker': 'OCI',
|
||||
'oci': 'OCI',
|
||||
'appx': 'Appx'
|
||||
}
|
||||
args_map = {
|
||||
'docker': [root_dir, 'docker-archive', custom_args],
|
||||
'oci': [root_dir, 'oci-archive', custom_args],
|
||||
'appx': [root_dir, custom_args]
|
||||
}
|
||||
try:
|
||||
container_image = importlib.import_module(
|
||||
'kiwi.container.{}'.format('oci' if name == 'docker' else name)
|
||||
)
|
||||
elif name == 'oci':
|
||||
return ContainerImageOCI(
|
||||
root_dir, 'oci-archive', custom_args=custom_args
|
||||
)
|
||||
elif name == 'appx':
|
||||
return ContainerImageAppx(
|
||||
root_dir, custom_args=custom_args
|
||||
)
|
||||
else:
|
||||
module_name = 'ContainerImage{}'.format(name_map[name])
|
||||
return container_image.__dict__[module_name](*args_map[name])
|
||||
except Exception:
|
||||
raise KiwiContainerImageSetupError(
|
||||
'Support for {0} container not implemented'.format(name)
|
||||
)
|
||||
|
||||
@ -118,7 +118,7 @@ class ContainerImageOCI:
|
||||
exclude_list.append('sys/*')
|
||||
exclude_list.append('proc/*')
|
||||
|
||||
oci = OCI()
|
||||
oci = OCI.new()
|
||||
if base_image:
|
||||
oci.import_container_image(
|
||||
'oci-archive:{0}:{1}'.format(
|
||||
|
||||
@ -15,28 +15,40 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with kiwi. If not, see <http://www.gnu.org/licenses/>
|
||||
#
|
||||
# project
|
||||
from kiwi.container.setup.docker import ContainerSetupDocker
|
||||
from kiwi.container.setup.oci import ContainerSetupOCI
|
||||
from kiwi.container.setup.appx import ContainerSetupAppx
|
||||
import importlib
|
||||
from abc import (
|
||||
ABCMeta,
|
||||
abstractmethod
|
||||
)
|
||||
|
||||
# project
|
||||
from kiwi.exceptions import (
|
||||
KiwiContainerSetupError
|
||||
)
|
||||
|
||||
|
||||
class ContainerSetup:
|
||||
class ContainerSetup(metaclass=ABCMeta):
|
||||
"""
|
||||
container setup factory
|
||||
"""
|
||||
def __new__(self, name, root_dir, custom_args=None):
|
||||
if name == 'docker':
|
||||
return ContainerSetupDocker(root_dir, custom_args)
|
||||
elif name == 'oci':
|
||||
return ContainerSetupOCI(root_dir, custom_args)
|
||||
elif name == 'appx':
|
||||
return ContainerSetupAppx(root_dir, custom_args)
|
||||
else:
|
||||
@abstractmethod
|
||||
def __init__(self) -> None:
|
||||
return None # pragma: no cover
|
||||
|
||||
@staticmethod
|
||||
def new(name: str, root_dir: str, custom_args: dict = None):
|
||||
name_map = {
|
||||
'docker': 'Docker',
|
||||
'oci': 'OCI',
|
||||
'appx': 'Appx'
|
||||
}
|
||||
try:
|
||||
container_setup = importlib.import_module(
|
||||
'kiwi.container.setup.{}'.format(name)
|
||||
)
|
||||
module_name = 'ContainerSetup{}'.format(name_map[name])
|
||||
return container_setup.__dict__[module_name](root_dir, custom_args)
|
||||
except Exception:
|
||||
raise KiwiContainerSetupError(
|
||||
'Support for {0} container not implemented'.format(name)
|
||||
)
|
||||
|
||||
@ -15,28 +15,42 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with kiwi. If not, see <http://www.gnu.org/licenses/>
|
||||
#
|
||||
# project
|
||||
from kiwi.oci_tools.umoci import OCIUmoci
|
||||
from kiwi.oci_tools.buildah import OCIBuildah
|
||||
from kiwi.runtime_config import RuntimeConfig
|
||||
import importlib
|
||||
from abc import (
|
||||
ABCMeta,
|
||||
abstractmethod
|
||||
)
|
||||
|
||||
# project
|
||||
from kiwi.runtime_config import RuntimeConfig
|
||||
from kiwi.exceptions import (
|
||||
KiwiOCIArchiveToolError
|
||||
)
|
||||
|
||||
|
||||
class OCI:
|
||||
class OCI(metaclass=ABCMeta):
|
||||
"""
|
||||
**OCI Factory**
|
||||
"""
|
||||
def __new__(self):
|
||||
@abstractmethod
|
||||
def __init__(self) -> None:
|
||||
return None # pragma: no cover
|
||||
|
||||
@staticmethod
|
||||
def new():
|
||||
name_map = {
|
||||
'umoci': 'Umoci',
|
||||
'buildah': 'Buildah'
|
||||
}
|
||||
runtime_config = RuntimeConfig()
|
||||
tool_name = runtime_config.get_oci_archive_tool()
|
||||
if tool_name == 'umoci':
|
||||
return OCIUmoci()
|
||||
elif tool_name == 'buildah':
|
||||
return OCIBuildah()
|
||||
else:
|
||||
try:
|
||||
oci_tool = importlib.import_module(
|
||||
'kiwi.oci_tools.{}'.format(tool_name)
|
||||
)
|
||||
module_name = 'OCI{}'.format(name_map[tool_name])
|
||||
return oci_tool.__dict__[module_name]()
|
||||
except Exception:
|
||||
raise KiwiOCIArchiveToolError(
|
||||
'No support for {0} tool available'.format(tool_name)
|
||||
)
|
||||
|
||||
@ -55,7 +55,7 @@ class RootImportOCI(RootImportBase):
|
||||
log.warning('Bypassing base image URI to OCI tools')
|
||||
image_uri = self.unknown_uri
|
||||
|
||||
oci = OCI()
|
||||
oci = OCI.new()
|
||||
oci.import_container_image(image_uri)
|
||||
oci.unpack()
|
||||
oci.import_rootfs(self.root_dir)
|
||||
|
||||
@ -112,22 +112,22 @@ class TestContainerBuilder:
|
||||
@patch('kiwi.builder.container.ContainerImage')
|
||||
def test_create(self, mock_image, mock_setup):
|
||||
container_setup = mock.Mock()
|
||||
mock_setup.return_value = container_setup
|
||||
mock_setup.new.return_value = container_setup
|
||||
container_image = mock.Mock()
|
||||
container_image.create = mock.Mock(
|
||||
return_value='target_dir/image_name.x86_64-1.2.3.docker.tar.xz'
|
||||
)
|
||||
mock_image.return_value = container_image
|
||||
mock_image.new.return_value = container_image
|
||||
self.setup.export_package_verification.return_value = '.verified'
|
||||
self.setup.export_package_changes.return_value = '.changes'
|
||||
self.setup.export_package_list.return_value = '.packages'
|
||||
self.container.base_image = None
|
||||
self.container.create()
|
||||
mock_setup.assert_called_once_with(
|
||||
mock_setup.new.assert_called_once_with(
|
||||
'docker', 'root_dir', self.container_config
|
||||
)
|
||||
container_setup.setup.assert_called_once_with()
|
||||
mock_image.assert_called_once_with(
|
||||
mock_image.new.assert_called_once_with(
|
||||
'docker', 'root_dir', self.container_config
|
||||
)
|
||||
container_image.create.assert_called_once_with(
|
||||
@ -188,7 +188,7 @@ class TestContainerBuilder:
|
||||
container_image.create = mock.Mock(
|
||||
return_value='target_dir/image_name.x86_64-1.2.3.docker.tar.xz'
|
||||
)
|
||||
mock_image.return_value = container_image
|
||||
mock_image.new.return_value = container_image
|
||||
|
||||
container = ContainerBuilder(
|
||||
self.xml_state, 'target_dir', 'root_dir'
|
||||
@ -212,7 +212,7 @@ class TestContainerBuilder:
|
||||
'checksumvalue', 'root_dir/image/imported_root.md5'
|
||||
)
|
||||
|
||||
mock_image.assert_called_once_with(
|
||||
mock_image.new.assert_called_once_with(
|
||||
'docker', 'root_dir', self.container_config
|
||||
)
|
||||
container_image.create.assert_called_once_with(
|
||||
|
||||
@ -9,25 +9,25 @@ from kiwi.exceptions import KiwiContainerImageSetupError
|
||||
class TestContainerImage:
|
||||
def test_container_image_not_implemented(self):
|
||||
with raises(KiwiContainerImageSetupError):
|
||||
ContainerImage('foo', 'root_dir')
|
||||
ContainerImage.new('foo', 'root_dir')
|
||||
|
||||
@patch('kiwi.container.ContainerImageOCI')
|
||||
@patch('kiwi.container.oci.ContainerImageOCI')
|
||||
def test_container_image_docker(self, mock_docker):
|
||||
ContainerImage('docker', 'root_dir')
|
||||
ContainerImage.new('docker', 'root_dir')
|
||||
mock_docker.assert_called_once_with(
|
||||
'root_dir', 'docker-archive', custom_args=None
|
||||
'root_dir', 'docker-archive', None
|
||||
)
|
||||
|
||||
@patch('kiwi.container.ContainerImageOCI')
|
||||
@patch('kiwi.container.oci.ContainerImageOCI')
|
||||
def test_container_image_oci(self, mock_oci):
|
||||
ContainerImage('oci', 'root_dir')
|
||||
ContainerImage.new('oci', 'root_dir')
|
||||
mock_oci.assert_called_once_with(
|
||||
'root_dir', 'oci-archive', custom_args=None
|
||||
'root_dir', 'oci-archive', None
|
||||
)
|
||||
|
||||
@patch('kiwi.container.ContainerImageAppx')
|
||||
@patch('kiwi.container.appx.ContainerImageAppx')
|
||||
def test_container_image_appx(self, mock_appx):
|
||||
ContainerImage('appx', 'root_dir')
|
||||
ContainerImage.new('appx', 'root_dir')
|
||||
mock_appx.assert_called_once_with(
|
||||
'root_dir', custom_args=None
|
||||
'root_dir', None
|
||||
)
|
||||
|
||||
@ -120,7 +120,7 @@ class TestContainerImageOCI:
|
||||
def test_create_oci_archive(self, mock_cache, mock_OCI):
|
||||
mock_cache.return_value = 'var/cache/kiwi'
|
||||
mock_oci = mock.Mock()
|
||||
mock_OCI.return_value = mock_oci
|
||||
mock_OCI.new.return_value = mock_oci
|
||||
|
||||
self.oci.runtime_config.get_container_compression = mock.Mock(
|
||||
return_value=None
|
||||
@ -164,7 +164,7 @@ class TestContainerImageOCI:
|
||||
):
|
||||
mock_cache.return_value = 'var/cache/kiwi'
|
||||
mock_oci = mock.Mock()
|
||||
mock_OCI.return_value = mock_oci
|
||||
mock_OCI.new.return_value = mock_oci
|
||||
|
||||
self.oci.create('result.tar', 'root_dir/image/image_file')
|
||||
|
||||
|
||||
@ -9,19 +9,19 @@ from kiwi.exceptions import KiwiContainerSetupError
|
||||
class TestContainerSetup:
|
||||
def test_container_not_implemented(self):
|
||||
with raises(KiwiContainerSetupError):
|
||||
ContainerSetup('foo', 'root_dir')
|
||||
ContainerSetup.new('foo', 'root_dir')
|
||||
|
||||
@patch('kiwi.container.setup.ContainerSetupDocker')
|
||||
@patch('kiwi.container.setup.docker.ContainerSetupDocker')
|
||||
def test_container_docker(self, mock_docker):
|
||||
ContainerSetup('docker', 'root_dir')
|
||||
ContainerSetup.new('docker', 'root_dir')
|
||||
mock_docker.assert_called_once_with('root_dir', None)
|
||||
|
||||
@patch('kiwi.container.setup.ContainerSetupOCI')
|
||||
@patch('kiwi.container.setup.oci.ContainerSetupOCI')
|
||||
def test_container_oci(self, mock_oci):
|
||||
ContainerSetup('oci', 'root_dir')
|
||||
ContainerSetup.new('oci', 'root_dir')
|
||||
mock_oci.assert_called_once_with('root_dir', None)
|
||||
|
||||
@patch('kiwi.container.setup.ContainerSetupAppx')
|
||||
@patch('kiwi.container.setup.appx.ContainerSetupAppx')
|
||||
def test_container_appx(self, mock_appx):
|
||||
ContainerSetup('appx', 'root_dir')
|
||||
ContainerSetup.new('appx', 'root_dir')
|
||||
mock_appx.assert_called_once_with('root_dir', None)
|
||||
|
||||
@ -15,24 +15,24 @@ class TestOCI:
|
||||
self.runtime_config = Mock()
|
||||
self.runtime_config.get_oci_archive_tool = Mock()
|
||||
|
||||
@patch('kiwi.oci_tools.OCIUmoci')
|
||||
@patch('kiwi.oci_tools.umoci.OCIUmoci')
|
||||
@patch('kiwi.oci_tools.RuntimeConfig')
|
||||
def test_oci_tool_umoci(
|
||||
self, mock_RuntimeConfig, mock_OCIUmoci
|
||||
):
|
||||
self.runtime_config.get_oci_archive_tool.return_value = 'umoci'
|
||||
mock_RuntimeConfig.return_value = self.runtime_config
|
||||
OCI()
|
||||
OCI.new()
|
||||
mock_OCIUmoci.assert_called_once_with()
|
||||
|
||||
@patch('kiwi.oci_tools.OCIBuildah')
|
||||
@patch('kiwi.oci_tools.buildah.OCIBuildah')
|
||||
@patch('kiwi.oci_tools.RuntimeConfig')
|
||||
def test_oci_tool_buildah(
|
||||
self, mock_RuntimeConfig, mock_OCIBuildah
|
||||
):
|
||||
self.runtime_config.get_oci_archive_tool.return_value = 'buildah'
|
||||
mock_RuntimeConfig.return_value = self.runtime_config
|
||||
OCI()
|
||||
OCI.new()
|
||||
mock_OCIBuildah.assert_called_once_with()
|
||||
|
||||
@patch('kiwi.oci_tools.RuntimeConfig')
|
||||
@ -40,4 +40,4 @@ class TestOCI:
|
||||
self.runtime_config.get_oci_archive_tool.return_value = 'foo'
|
||||
mock_RuntimeConfig.return_value = self.runtime_config
|
||||
with raises(KiwiOCIArchiveToolError):
|
||||
OCI()
|
||||
OCI.new()
|
||||
|
||||
@ -42,7 +42,7 @@ class TestRootImportOCI:
|
||||
@patch('kiwi.system.root_import.oci.OCI')
|
||||
def test_sync_data(self, mock_OCI, mock_path, mock_md5, mock_compress):
|
||||
oci = Mock()
|
||||
mock_OCI.return_value = oci
|
||||
mock_OCI.new.return_value = oci
|
||||
md5 = Mock()
|
||||
mock_md5.return_value = Mock()
|
||||
|
||||
@ -52,7 +52,7 @@ class TestRootImportOCI:
|
||||
|
||||
self.oci_import.sync_data()
|
||||
|
||||
mock_OCI.assert_called_once_with()
|
||||
mock_OCI.new.assert_called_once_with()
|
||||
|
||||
oci.unpack.assert_called_once_with()
|
||||
oci.import_rootfs.assert_called_once_with(
|
||||
@ -70,7 +70,7 @@ class TestRootImportOCI:
|
||||
self, mock_OCI, mock_path, mock_md5, mock_compress
|
||||
):
|
||||
oci = Mock()
|
||||
mock_OCI.return_value = oci
|
||||
mock_OCI.new.return_value = oci
|
||||
md5 = Mock()
|
||||
mock_md5.return_value = Mock()
|
||||
|
||||
@ -80,7 +80,7 @@ class TestRootImportOCI:
|
||||
|
||||
self.oci_import.sync_data()
|
||||
|
||||
mock_OCI.assert_called_once_with()
|
||||
mock_OCI.new.assert_called_once_with()
|
||||
|
||||
oci.unpack.assert_called_once_with()
|
||||
oci.import_rootfs.assert_called_once_with(
|
||||
@ -100,7 +100,7 @@ class TestRootImportOCI:
|
||||
):
|
||||
mock_exists.return_value = True
|
||||
oci = Mock()
|
||||
mock_OCI.return_value = oci
|
||||
mock_OCI.new.return_value = oci
|
||||
md5 = Mock()
|
||||
mock_md5.return_value = Mock()
|
||||
with patch.dict('os.environ', {'HOME': '../data'}):
|
||||
@ -111,7 +111,7 @@ class TestRootImportOCI:
|
||||
|
||||
with self._caplog.at_level(logging.WARNING):
|
||||
oci_import.sync_data()
|
||||
mock_OCI.assert_called_once_with()
|
||||
mock_OCI.new.assert_called_once_with()
|
||||
oci.import_container_image.assert_called_once_with(
|
||||
'docker:image:tag'
|
||||
)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user