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.new() mock_OCIBuildah.assert_called_once_with()
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.new() mock_OCIUmoci.assert_called_once_with()
def sync_data(self): """ Synchronize data from the given base image to the target root directory. """ if not self.unknown_uri: compressor = Compress(self.image_file) if compressor.get_format(): compressor.uncompress(True) self.uncompressed_image = compressor.uncompressed_filename else: self.uncompressed_image = self.image_file image_uri = '{0}:{1}'.format( self.archive_transport, self.uncompressed_image ) else: log.warning('Bypassing base image URI to OCI tools') image_uri = self.unknown_uri oci = OCI() oci.import_container_image(image_uri) oci.unpack() oci.import_rootfs(self.root_dir) # A copy of the uncompressed image and its checksum are # kept inside the root_dir in order to ensure the later steps # i.e. system create are atomic and don't need any third # party archive. image_copy = Defaults.get_imported_root_image(self.root_dir) Path.create(os.path.dirname(image_copy)) oci.export_container_image( image_copy, 'oci-archive', Defaults.get_container_base_image_tag() ) self._make_checksum(image_copy)
def __init__(self, root_dir, custom_args=None): self.root_dir = root_dir self.oci_root_dir = None if custom_args: self.oci_config = custom_args else: self.oci_config = {} self.runtime_config = RuntimeConfig() # for builds inside the buildservice we include a reference to the # specific build. Thus disturl label only exists inside the # buildservice. if Defaults.is_buildservice_worker(): bs_label = 'org.openbuildservice.disturl' # Do not label anything if any build service label is # already present if 'labels' not in self.oci_config or \ bs_label not in self.oci_config['labels']: self._append_buildservice_disturl_label() if 'container_name' not in self.oci_config: log.info('No container configuration provided, ' 'using default container name "kiwi-container:latest"') self.oci_config['container_name'] = \ Defaults.get_default_container_name() self.oci_config['container_tag'] = \ Defaults.get_default_container_tag() if 'container_tag' not in self.oci_config: self.oci_config['container_tag'] = \ Defaults.get_default_container_tag() if 'entry_command' not in self.oci_config and \ 'entry_subcommand' not in self.oci_config: self.oci_config['entry_subcommand'] = \ Defaults.get_default_container_subcommand() if 'history' not in self.oci_config: self.oci_config['history'] = {} if 'created_by' not in self.oci_config['history']: self.oci_config['history']['created_by'] = \ Defaults.get_default_container_created_by() self.oci = OCI(self.oci_config['container_tag'])
def create(self, filename, base_image, ensure_empty_tmpdirs=True): """ Create compressed oci system container tar archive :param string filename: archive file name :param string base_image: archive used as a base image """ exclude_list = Defaults.\ get_exclude_list_for_root_data_sync(ensure_empty_tmpdirs) + Defaults.\ get_exclude_list_from_custom_exclude_files(self.root_dir) exclude_list.append('dev/*') exclude_list.append('sys/*') exclude_list.append('proc/*') oci = OCI.new() if base_image: oci.import_container_image('oci-archive:{0}:{1}'.format( base_image, Defaults.get_container_base_image_tag())) else: # Apply default subcommand only for base images if 'entry_command' not in self.oci_config and \ 'entry_subcommand' not in self.oci_config: self.oci_config['entry_subcommand'] = \ Defaults.get_default_container_subcommand() oci.init_container() image_ref = '{0}:{1}'.format(self.oci_config['container_name'], self.oci_config['container_tag']) oci.unpack() oci.sync_rootfs(self.root_dir, exclude_list) oci.repack(self.oci_config) oci.set_config(self.oci_config) oci.post_process() image_ref = '{0}:{1}'.format(self.oci_config['container_name'], self.oci_config['container_tag']) additional_refs = [] if self.archive_transport == 'docker-archive': if 'additional_names' in self.oci_config: additional_refs = [] for name in self.oci_config['additional_names']: name_parts = name.partition(':') if not name_parts[0]: additional_refs.append('{0}:{1}'.format( self.oci_config['container_name'], name_parts[2])) elif not name_parts[2]: additional_refs.append('{0}:{1}'.format( name_parts[0], self.oci_config['container_tag'])) else: additional_refs.append('{0}:{1}'.format( name_parts[0], name_parts[2])) oci.export_container_image(filename, self.archive_transport, image_ref, additional_refs) return filename
def create(self, filename, base_image): """ Create compressed oci system container tar archive :param string filename: archive file name :param string base_image: archive used as a base image """ exclude_list = Defaults.get_exclude_list_for_root_data_sync() exclude_list.append('dev/*') exclude_list.append('sys/*') exclude_list.append('proc/*') oci = OCI.new() if base_image: oci.import_container_image( 'oci-archive:{0}:{1}'.format( base_image, Defaults.get_container_base_image_tag() ) ) else: oci.init_container() image_ref = '{0}:{1}'.format( self.oci_config['container_name'], self.oci_config['container_tag'] ) oci.unpack() oci.sync_rootfs(self.root_dir, exclude_list) oci.repack(self.oci_config) oci.set_config(self.oci_config) oci.post_process() if self.archive_transport == 'docker-archive': image_ref = '{0}:{1}'.format( self.oci_config['container_name'], self.oci_config['container_tag'] ) additional_refs = [] if 'additional_tags' in self.oci_config: additional_refs = [] for tag in self.oci_config['additional_tags']: additional_refs.append('{0}:{1}'.format( self.oci_config['container_name'], tag )) else: image_ref = self.oci_config['container_tag'] additional_refs = [] oci.export_container_image( filename, self.archive_transport, image_ref, additional_refs ) if self.runtime_config.get_container_compression(): compressor = Compress(filename) return compressor.xz(self.runtime_config.get_xz_options()) else: return filename
def sync_data(self): """ Synchronize data from the given base image to the target root directory. """ self.extract_oci_image() oci = OCI('base_layer', self.oci_layout_dir) oci.unpack() oci.import_rootfs(self.root_dir) # A copy of the uncompressed image and its checksum are # kept inside the root_dir in order to ensure the later steps # i.e. system create are atomic and don't need any third # party archive. image_copy = Defaults.get_imported_root_image(self.root_dir) Path.create(os.path.dirname(image_copy)) image_tar = ArchiveTar(image_copy) image_tar.create(self.oci_layout_dir) self._make_checksum(image_copy)
def test_oci_tool_not_supported(self, mock_RuntimeConfig): self.runtime_config.get_oci_archive_tool.return_value = 'foo' mock_RuntimeConfig.return_value = self.runtime_config with raises(KiwiOCIArchiveToolError): OCI()
class ContainerImageOCI(object): """ Create oci container from a root directory :param string root_dir: root directory path name :param dict custom_args: Custom processing arguments defined as hash keys: Example .. code:: python { 'container_name': 'name', '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'}, 'labels': {'name': 'value'}, 'history': { 'created_by': 'some explanation here', 'comment': 'some comment here', 'author': 'tux' } } """ def __init__(self, root_dir, custom_args=None): self.root_dir = root_dir self.oci_root_dir = None if custom_args: self.oci_config = custom_args else: self.oci_config = {} self.runtime_config = RuntimeConfig() # for builds inside the buildservice we include a reference to the # specific build. Thus disturl label only exists inside the # buildservice. if Defaults.is_buildservice_worker(): bs_label = 'org.openbuildservice.disturl' # Do not label anything if any build service label is # already present if 'labels' not in self.oci_config or \ bs_label not in self.oci_config['labels']: self._append_buildservice_disturl_label() if 'container_name' not in self.oci_config: log.info('No container configuration provided, ' 'using default container name "kiwi-container:latest"') self.oci_config['container_name'] = \ Defaults.get_default_container_name() self.oci_config['container_tag'] = \ Defaults.get_default_container_tag() if 'container_tag' not in self.oci_config: self.oci_config['container_tag'] = \ Defaults.get_default_container_tag() if 'entry_command' not in self.oci_config and \ 'entry_subcommand' not in self.oci_config: self.oci_config['entry_subcommand'] = \ Defaults.get_default_container_subcommand() if 'history' not in self.oci_config: self.oci_config['history'] = {} if 'created_by' not in self.oci_config['history']: self.oci_config['history']['created_by'] = \ Defaults.get_default_container_created_by() self.oci = OCI(self.oci_config['container_tag']) def create(self, filename, base_image): """ Create compressed oci system container tar archive :param string filename: archive file name :param string base_image: archive used as a base image """ exclude_list = Defaults.get_exclude_list_for_root_data_sync() exclude_list.append('boot') exclude_list.append('dev') exclude_list.append('sys') exclude_list.append('proc') if base_image: Path.create(self.oci.container_dir) image_tar = ArchiveTar(base_image) image_tar.extract(self.oci.container_dir) self.oci.init_layout(bool(base_image)) self.oci.unpack() self.oci.sync_rootfs(''.join([self.root_dir, os.sep]), exclude_list) self.oci.repack(self.oci_config) if 'additional_tags' in self.oci_config: for tag in self.oci_config['additional_tags']: self.oci.add_tag(tag) self.oci.set_config(self.oci_config, bool(base_image)) self.oci.garbage_collect() return self.pack_image_to_file(filename) def pack_image_to_file(self, filename): """ Packs the oci image into the given filename. :param string filename: file name of the resulting packed image """ oci_tarfile = ArchiveTar(filename) container_compressor = self.runtime_config.get_container_compression() if container_compressor: return oci_tarfile.create_xz_compressed( self.oci.container_dir, xz_options=self.runtime_config.get_xz_options()) else: return oci_tarfile.create(self.oci.container_dir) def _append_buildservice_disturl_label(self): with open(os.sep + Defaults.get_buildservice_env_name()) as env: for line in env: if line.startswith('BUILD_DISTURL') and '=' in line: disturl = line.split('=')[1].lstrip('\'\"').rstrip( '\n\'\"') if disturl: self.oci_config['labels'] = { 'org.openbuildservice.disturl': disturl } return log.warning('Could not find BUILD_DISTURL inside .buildenv')