def test_encode_to_ostree_ref(self): """ Verify that 1: image after encoded to ostree ref will be no longer hex 2: image contains no tag will have tag latest appended 3: qualified image(image with registry included) and non-qualified image will behave in the same way when calling _encode_to_ostree_ref """ def ensure_ref_is_not_hex(ref): ref_is_hex = SystemContainers._is_hex(ref) self.assertFalse(ref_is_hex) qual_img_without_tag = "registry.fedoraproject.org/f27/kubernetes-apiserver" qual_img_with_tag = qual_img_without_tag + ":tag" non_qual_img_without_tag = "cafe" non_qual_img_with_tag = non_qual_img_without_tag + ":tag" qual_img_without_tag_ref = SystemContainers._encode_to_ostree_ref( qual_img_without_tag) self.assertTrue(qual_img_without_tag_ref.endswith("latest")) ensure_ref_is_not_hex(qual_img_without_tag_ref) # The encoded ref will have ":" translated to _3A (unicode) qual_img_with_tag_ref = SystemContainers._encode_to_ostree_ref( qual_img_with_tag) self.assertTrue(qual_img_with_tag_ref.endswith("_3Atag")) ensure_ref_is_not_hex(qual_img_with_tag_ref) non_qual_img_without_tag_ref = SystemContainers._encode_to_ostree_ref( non_qual_img_without_tag) ensure_ref_is_not_hex(non_qual_img_without_tag_ref) non_qual_img_with_tag_ref = SystemContainers._encode_to_ostree_ref( non_qual_img_with_tag) self.assertTrue(non_qual_img_with_tag_ref.endswith("_3Atag")) ensure_ref_is_not_hex(non_qual_img_with_tag_ref)
def test_get_remote_location(self): """ This function checks for 4 different cases of _get_remote_location function 1: when the remote is given as /xx and /xx/rootfs exist 2: when the remote is given as /xx/rootfs and /xx/rootfs/usr exist 3: when the remote input does not contain a rootfs 4: when the remote input path does not exist """ try: tmpdir = tempfile.mkdtemp() rootfs_location = os.path.sep.join([tmpdir, "rootfs"]) not_valid_location = os.path.sep.join([tmpdir, "not-valid-test"]) non_existant_location = os.path.sep.join([tmpdir, "non-existant-path"]) os.makedirs(os.path.sep.join([rootfs_location, "usr"])) os.mkdir(not_valid_location) # Here: we check for 4 different cases _get_remote_location verifies self.assertRaises(ValueError, SystemContainers._get_remote_location, non_existant_location) remote_path_one = SystemContainers._get_remote_location(tmpdir) # we default to real path here because on AH, / sometimes actually refer to /sysroot self.assertEqual(remote_path_one, os.path.realpath(tmpdir)) remote_path_two = SystemContainers._get_remote_location(rootfs_location) self.assertEqual(remote_path_two, os.path.realpath(tmpdir)) self.assertRaises(ValueError, SystemContainers._get_remote_location, not_valid_location) finally: # We then remove the directories to keep the user's fs clean shutil.rmtree(tmpdir)
def test_update_rename_file_value(self): """ This function checks 2 different cases for function '_update_rename_file_value' 1: checks if the values will be successfully swapped given correct value combinations 2: checks when one of the values in "rename_files" is not replaced, error will come out """ # Prepare for the values sc = SystemContainers() manifest = { "renameFiles": { "testKey": "$testVal", "testKeySec": "$testTwo" } } values = {"testVal": "testSubOne", "testTwo": "testSubTwo"} secondValues = {"testVal": "secondTestSubOne"} # Test for the cases mentioned above sc._update_rename_file_value(manifest, values) self.assertEqual(manifest["renameFiles"]["testKey"], "testSubOne") self.assertEqual(manifest["renameFiles"]["testKeySec"], "testSubTwo") # Reset the value for next test case manifest["renameFiles"]["testKey"] = "$testMisMatch" self.assertRaises(ValueError, sc._update_rename_file_value, manifest, secondValues)
def test_container_exec_in_usermode(self): """ A ValueError should be raised as usermode is not supported. """ args = self.Args(backend='ostree') sc = SystemContainers() sc.set_args(args) self.assertRaises(ValueError, sc.container_exec, 'test', False, {})
def __init__(self): self.input = None self.syscontainers = SystemContainers() class Args: def __init__(self): self.system = os.getuid() == 0 self.user = not self.system self.setvalues = {} self.remote = False self.syscontainers.set_args(Args())
def test_container_exec_not_running_no_checkout(self, _gb, _um, _sa): """ A ValueError should be raised when the container is not running and there is no checkout. """ _sa.return_value = False # The service is not active _um.return_value = False # user mode is False _gb.return_value = None # The checkout is None args = self.Args(backend='ostree') sc = SystemContainers() sc.set_args(args) self.assertRaises(ValueError, sc.container_exec, 'test', False, {})
def test_container_exec_not_running_with_detach(self, _cl, _um, _sa): """ A ValueError should be raised when the container is not running and detach is requested. """ _sa.return_value = False # The service is not active _um.return_value = False # user mode is False _cl.return_value = "/var/lib/containers/atomic/test.0" # Fake a checkout args = self.Args(backend='ostree') sc = SystemContainers() sc.set_args(args) self.assertRaises(ValueError, sc.container_exec, 'test', True, {}) # Run with detach as True
def test_handle_system_package_files(self, _isi, _raf, _gr): """ This function checks 3 simple cases to verify the basic functionality of handle_system_package_files 1: When 'system_package = absent' 2: When system_package is 'yes' 3: When system_package='no' For 3 above cases, we verify if the expected outcome matches the actual outcome Do note, this is just testing the workflow on a higher level of the subsequent function calls. IOW, the lower level function call 'generate_rpm' or 'rm_add_files_to_host' will not be tested here (it is covered as a whole in integration test) """ expected_checksum = {"test": "test_checksum_xxx"} _gr.return_value = (True, "rpm_file", None) _raf.return_value = expected_checksum _isi.return_value = {"ImageId": {}} manifest = {} # Note, even though we replace the return value, we still need to make sure # entries such as img or destination do exist in options to avoid key error options = { "system_package": "yes", "img": None, "destination": "", "values": {}, "deployment": 1, "name": "test" } test_options_two = { "system_package": "no", "installed_files_checksum": "", "prefix": "", "values": "" } test_options_third = {"system_package": "absent"} sc = SystemContainers() rpm_install_output_one = sc._handle_system_package_files( test_options_third, manifest, "") self.assertEqual( rpm_install_output_one["new_installed_files_checksum"], {}) rpm_install_output_second = sc._handle_system_package_files( options, manifest, "") self.assertEqual(rpm_install_output_second["rpm_installed"], True) rpm_install_output_third = sc._handle_system_package_files( test_options_two, manifest, "") self.assertEqual( rpm_install_output_third["new_installed_files_checksum"], expected_checksum)
def test_get_manifest_attribtues(self): """ This function checks 2 simple cases to verify the functionality of '_get_manifest_attribtues' 1: When the attribute is not in the manifest, a default val should be returned 2: When the key is there and manifest itself exist, its corresponding value should be returned """ manifest = {"rename_files": "test_val"} # Test for the two cases mentioned above test_val_one = SystemContainers._get_manifest_attributes( manifest, "rename_files", None) self.assertEqual(test_val_one, "test_val") test_val_two = SystemContainers._get_manifest_attributes( manifest, "non_existant", "test_two") self.assertEqual(test_val_two, "test_two")
class TestSystemContainers_get_skopeo_args(unittest.TestCase): """ Unit tests for the SystemContainres._get_skopeo_args method. """ def setUp(self): self.sc = SystemContainers() def test_get_skopeo_args(self): """ Verify _get_skopeo_args return proper data when passing in different image uris. """ for test_image, expected_insecure, expected_image in ( # Explicitly insecure ('http:docker.io/busybox:latest', True, 'docker.io/busybox:latest' ), # Implicitly secure ('docker.io/busybox:latest', False, 'docker.io/busybox:latest'), ('https:docker.io/busybox:latest', False, 'docker.io/busybox:latest'), ('oci:docker.io/busybox:latest', False, 'docker.io/busybox:latest')): # Make the call insecure, image = self.sc._get_skopeo_args(test_image) # Verify the results self.assertEqual(expected_insecure, insecure) self.assertEqual(expected_image, image)
def test_container_exec_with_container_running(self, _um, _cc, _sa): """ Expect the container exec command to be used when container is running. """ cmd_call = [util.RUNC_PATH, 'exec', 'test'] if os.isatty(0): # If we are a tty then we need to pop --tty in there cmd_call.insert(2, '--tty') expected_call = call(cmd_call, stderr=ANY, stdin=ANY, stdout=ANY) _sa.return_value = True # The service is active _um.return_value = False # user mode is False args = self.Args(backend='ostree', user=False) sc = SystemContainers() sc.set_args(args) sc.container_exec('test', False, {}) self.assertEqual(_cc.call_args, expected_call)
def test_prepare_rootfs_dirs(self): """ This function checks for 3 different cases for function '_prepare_rootfs_dirs' 1: extract specified with either destination/remote_path 2: remote_path and destination specified 3: only destination specified """ try: # Prepare the temp location for verifying tmpdir = tempfile.mkdtemp() extract_location = os.path.sep.join([tmpdir, "extract"]) remote_location = os.path.sep.join([tmpdir, "remote"]) remote_destination_case = os.path.sep.join([tmpdir, "dest_one"]) destination_location = os.path.sep.join([tmpdir, "dest_two"]) sc = SystemContainers() # Create expected rootfs for future comparison expected_remote_rootfs = os.path.join(remote_location, "rootfs") expected_dest_rootfs = os.path.join(destination_location, "rootfs") # Here, we begin testing 3 different cases mentioned above extract_rootfs = sc._prepare_rootfs_dirs(None, extract_location, extract_only=True) self.assertTrue(os.path.exists(extract_rootfs), True) self.assertEqual(extract_rootfs, extract_location) remote_rootfs = sc._prepare_rootfs_dirs(remote_location, remote_destination_case) self.assertEqual(remote_rootfs, expected_remote_rootfs) self.assertTrue(os.path.exists(remote_destination_case), True) # Note: since the location passed in is not in /var/xx format, canonicalize location # should not have an effect, thus we don't worry about it here destination_rootfs = sc._prepare_rootfs_dirs( None, destination_location) self.assertEqual(destination_rootfs, expected_dest_rootfs) self.assertTrue(os.path.exists(expected_dest_rootfs), True) finally: shutil.rmtree(tmpdir)
def test_write_info_file(self): """ This function checks 2 simple cases to verify functionality of '_write_info_file' 1: When error occurs, the files specified in 'new_install_files' are removed 2: Otherwise, the info file is written to the correct location """ try: # Prepare directories and values tmpdir = tempfile.mkdtemp() installed_file = tempfile.mkstemp(prefix=tmpdir) installed_file_path = installed_file[1] destination_dir = os.path.sep.join([tmpdir, "dest_dir"]) destination_info_path = os.path.join(destination_dir, "info") options = { "destination": destination_dir, "prefix": None, "img": "test", "remote": None, "system_package": "no", "values": {} } rpm_install_content = { "new_installed_files": [installed_file_path], "rpm_installed": False, "new_installed_files_checksum": {} } # Since the destination is not created yet, we test here would result an IOError, # leading to the installed_file to be removed sc = SystemContainers() self.assertRaises(IOError, sc._write_info_file, options, None, rpm_install_content, None, None) self.assertFalse(os.path.exists(installed_file_path)) os.mkdir(destination_dir) sc._write_info_file(options, None, rpm_install_content, None, None) self.assertTrue(os.path.exists(destination_info_path)) finally: shutil.rmtree(tmpdir)
def test_container_exec_without_container_running(self, _ce, _um, _cc, _sa): """ Expect the container to be started if it's not already running. """ expected_args = [util.RUNC_PATH, 'run', 'test'] _sa.return_value = False # The service is not active _um.return_value = False # user mode is False tmpd = tempfile.mkdtemp() try: _ce.return_value = tmpd # Use a temporary directory for testing args = self.Args(backend='ostree', user=False) sc = SystemContainers() sc.set_args(args) shutil.copy('./tests/test-images/system-container-files-hostfs/config.json.template', os.path.join(tmpd, 'config.json')) sc.container_exec('test', False, {}) self.assertEqual(_cc.call_args[0][0], expected_args) finally: shutil.rmtree(tmpd)
def test_pull_as_privileged_user(self): if os.getenv("SKOPEO_NO_OSTREE"): return args = self.Args() testobj = SystemContainers() testobj.set_args(args) testobj.pull_image()
class TestSystemContainers_get_skopeo_args(unittest.TestCase): """ Unit tests for the SystemContainres._get_skopeo_args method. """ def setUp(self): self.sc = SystemContainers() def test_get_skopeo_args(self): """ Verify _get_skopeo_args return proper data when passing in different image uris. """ for test_image, expected_insecure, expected_image in ( # Explicitly insecure ('http:docker.io/busybox:latest', True, 'docker.io/busybox:latest'), # Implicitly secure ('docker.io/busybox:latest', False, 'docker.io/busybox:latest'), ('https:docker.io/busybox:latest', False, 'docker.io/busybox:latest'), ('oci:docker.io/busybox:latest', False, 'docker.io/busybox:latest')): # Make the call insecure, image = self.sc._get_skopeo_args(test_image) # Verify the results self.assertEqual(expected_insecure, insecure) self.assertEqual(expected_image, image)
def setUp(self): self.sc = SystemContainers()
def test_write_config_to_dest(self): """ This function checks 3 different cases for function 'write_config_to_dest' 1: checks when exports/config.json exist, the files are copied correctly 2: checks exports/config.json.template exist, the template is copied, and values inside the template are swapped by values 3: checks the configuration was correct when the above 2 cases do not apply """ def check_attr_in_json_file(json_file, attr_name, value, second_attr=None): # We don't check existance here, because in this context, files do exist with open(json_file, "r") as f: json_val = json.loads(f.read()) actual_val = json_val[attr_name][ second_attr] if second_attr else json_val[attr_name] self.assertEqual(actual_val, value) try: # Prepare the temp directory for verification tmpdir = tempfile.mkdtemp() dest_location = os.path.sep.join([tmpdir, "dest"]) dest_location_config = os.path.join(dest_location, "config.json") # Note: in this context, the location of exports should not matter, as we are only copying files from exports # in this function exports_location = os.path.join(tmpdir, "rootfs/exports") exports_json = os.path.join(exports_location, "config.json") os.makedirs(exports_location) os.mkdir(dest_location) values = {"test_one": "$hello_test"} with open(exports_json, 'w') as json_file: json_file.write(json.dumps(values, indent=4)) json_file.write("\n") new_values = {"hello_test": "new_val"} sc = SystemContainers() sc._write_config_to_dest(dest_location, exports_location) self.assertTrue(os.path.exists(dest_location_config), True) check_attr_in_json_file(dest_location_config, "test_one", "$hello_test") # We remove the file to keep the destination clean for next operation os.remove(dest_location_config) # Rename exports/config.json to exports/config.json.template os.rename(exports_json, exports_json + ".template") sc._write_config_to_dest(dest_location, exports_location, new_values) self.assertTrue(os.path.exists(dest_location_config), True) check_attr_in_json_file(dest_location_config, "test_one", "new_val") os.remove(dest_location_config) # Note: in this case, the configuration is generated and changed via 'generate_default_oci_configuration' which uses runc. # Thus, we assume when user tries to run the unit test with this function, he will have runc installed sc._write_config_to_dest(dest_location, os.path.join(tmpdir, "not_exist")) self.assertTrue(os.path.exists(dest_location_config), True) check_attr_in_json_file(dest_location_config, "root", "rootfs", second_attr="path") finally: shutil.rmtree(tmpdir)
def test_pull_as_nonprivileged_user(self): args = self.Args() args.user = True testobj = SystemContainers() testobj.set_args(args) testobj.pull_image()
class OSTreeBackend(Backend): def __init__(self): self.input = None self.syscontainers = SystemContainers() class Args: def __init__(self): self.system = os.getuid() == 0 self.user = not self.system self.setvalues = {} self.remote = False self.syscontainers.set_args(Args()) @property def backend(self): return "ostree" def available(self): return self.syscontainers.available def _make_container(self, info): container_id = info['Id'] runtime = self.syscontainers.get_container_runtime_info(container_id) container = Container(container_id, backend=self) container.name = container_id container.command = info['Command'] container.id = container_id container.runtime = info['Runtime'] container.image_name = info['Image'] container.image = info['ImageID'] container.created = info['Created'] container.status = container.state = runtime['status'] container.input_name = container_id container.original_structure = info container.deep = True container.running = False if container.status == 'inactive' else True return container def _make_image(self, image, info, remote=False): img_obj = Image(image, backend=self, remote=remote) if remote: return img_obj name = info['Id'] img_obj.input_name = image img_obj.name = image img_obj.config = info img_obj.backend = self img_obj.id = name img_obj.registry, img_obj.repo, img_obj.image, img_obj.tag, _ = Decompose(image).all img_obj.repotags = info['RepoTags'] img_obj.created = info['Created'] img_obj.size = info.get('VirtualSize', None) img_obj.virtual_size = info.get('VirtualSize', None) img_obj.original_structure = info img_obj.deep = True img_obj.labels = info.get('Labels', None) img_obj.version = img_obj.get_label("Version") img_obj.release = img_obj.get_label("Release") ostree_manifest = self.syscontainers.get_manifest(image) if ostree_manifest: ostree_manifest = json_loads(ostree_manifest) img_obj.digest = None if ostree_manifest is None else ostree_manifest.get('Digest') or ostree_manifest.get('digest') img_obj.os = img_obj.get_label("Os") img_obj.arch = img_obj.get_label("Arch") img_obj.graph_driver = None return img_obj def has_image(self, img): if self.syscontainers.has_image(img): return self.inspect_image(img) return None def has_container(self, container): if self.syscontainers.get_checkout(container): return self.inspect_container(container) return None def inspect_image(self, image): try: return self._make_image(image, self.syscontainers.inspect_system_image(image)) except ValueError: return None def inspect_container(self, container): containers = self.syscontainers.get_containers(containers=[container]) if len(containers) == 0: return None return self._make_container(containers[0]) def start_container(self, name): return self.syscontainers.start_service(name) def stop_container(self, con_obj, **kwargs): return self.syscontainers.stop_service(con_obj.id) def get_images(self, get_all=False): return [self._make_image(x['Id'], x) for x in self.syscontainers.get_system_images(get_all=get_all)] def get_containers(self): return [self._make_container(x) for x in self.syscontainers.get_containers()] def pull_image(self, image, remote_image_obj=None, **kwargs): return self.syscontainers.pull_image(image, **kwargs) def delete_image(self, image, force=False): return self.syscontainers.delete_image(image) def version(self, image): return self.get_layers(image) def update(self, name, **kwargs): force = kwargs.get('force', False) if force: raise ValueError("--force is not supported by ostree images") return self.syscontainers.pull_image(name) def install(self, image, name, **kwargs): return self.syscontainers.install(image, name) def uninstall(self, iobject, name=None, **kwargs): return self.syscontainers.uninstall(iobject.name) def prune(self): return self.syscontainers.prune_ostree_images() def validate_layer(self, layer): return self.syscontainers.validate_layer(layer) def _get_layer(self, image): return Layer(self.inspect_image(image)) def get_layers(self, image): layers = [] layer = self._get_layer(image) layers.append(layer) while layer.parent: layer = self._get_layer(layer.parent) layers.append(layer) return layers @staticmethod def get_dangling_images(): return [] def make_remote_image(self, image): img_obj = self._make_remote_image(image) img_obj.populate_remote_inspect_info() return img_obj def _make_remote_image(self, image): return self._make_image(image, None, remote=True) def delete_container(self, container, force=False): return self.syscontainers.uninstall(container) def run(self, iobject, **kwargs): args = kwargs.get('args') try: name = iobject.name except AttributeError: # iobject isn't populated raise ValueError('Unable to find an image named {} in {}'.format( args.image, args.storage)) if len(args.command) == 0: return self.syscontainers.start_service(name) return self.syscontainers.container_exec(name, args.detach, args.command) def tag_image(self, src, dest): return self.syscontainers.tag_image(src, dest)
class OSTreeBackend(Backend): def __init__(self): self.input = None self.syscontainers = SystemContainers() class Args: def __init__(self): self.system = os.getuid() == 0 self.user = not self.system self.setvalues = {} self.remote = False self.syscontainers.set_args(Args()) @property def backend(self): return "ostree" def _make_container(self, info): container_id = info['Id'] runtime = self.syscontainers.get_container_runtime_info(container_id) container = Container(container_id, backend=self) container.name = container_id container.id = container_id container.created = info['Created'] container.status = runtime['status'] container.input_name = container_id container.original_structure = info container.deep = True container.image = info['Image'] return container def _make_image(self, image, info): name = info['Id'] img_obj = Image(image, backend=self, remote=False) img_obj.input_name = image img_obj.name = image img_obj.config = info img_obj.backend = self img_obj.id = name img_obj.registry = None img_obj.repo = None img_obj.image = name img_obj.tag = name img_obj.repotags = info['RepoTags'] img_obj.created = info['Created'] img_obj.size = None img_obj.original_structure = info img_obj.deep = True img_obj.labels = info['Labels'] img_obj.version = img_obj.get_label("Version") img_obj.release = img_obj.get_label("Release") img_obj.digest = None img_obj.os = img_obj.get_label("Os") img_obj.arch = img_obj.get_label("Arch") img_obj.graph_driver = None return img_obj def has_image(self, img): if self.syscontainers.has_image(img): return self.inspect_image(img) return None def has_container(self, container): if self.syscontainers.get_checkout(container): return self.inspect_container(container) return None def inspect_image(self, image): try: return self._make_image(image, self.syscontainers.inspect_system_image(image)) except ValueError: return None def inspect_container(self, container): containers = self.syscontainers.get_containers(containers=[container]) if len(containers) == 0: return None return self._make_container(containers[0]) def start_container(self, name): return self.syscontainers.start_service(name) def stop_container(self, name): return self.syscontainers.stop_service(name) def get_images(self, get_all=False): return [self._make_image(x['Id'], x) for x in self.syscontainers.get_system_images(get_all=get_all)] def get_containers(self): return [self._make_container(x) for x in self.syscontainers.get_containers()] def pull_image(self, image, pull_args): return self.syscontainers.pull_image(image) def delete_image(self, image, force=False): return self.syscontainers.delete_image(image) def version(self, image): return self.get_layers(image) def update(self, name, force=False): if force or not self.syscontainers.has_image(name): return self.syscontainers.update(name) return True def install(self, image, name): return self.syscontainers.install(image, name) def uninstall(self, name): return self.syscontainers.uninstall(name) def prune(self): return self.syscontainers.prune_ostree_images() def validate_layer(self, layer): return self.syscontainers.validate_layer(layer) def _get_layer(self, image): return Layer(self.inspect_image(image)) def get_layers(self, image): layers = [] layer = self._get_layer(image) layers.append(layer) while layer.parent: layer = self._get_layer(layer.parent) layers.append(layer) return layers def get_dangling_images(self): return []
class OSTreeBackend(Backend): def __init__(self): self.input = None self.syscontainers = SystemContainers() class Args: def __init__(self): self.system = os.getuid() == 0 self.user = not self.system self.setvalues = {} self.remote = False self.syscontainers.set_args(Args()) @property def backend(self): return "ostree" def available(self): return self.syscontainers.available def _make_container(self, info): container_id = info['Id'] runtime = self.syscontainers.get_container_runtime_info(container_id) container = Container(container_id, backend=self) container.name = container_id container.command = info['Command'] container.id = container_id container.runtime = info['Runtime'] container.image_name = info['Image'] container.image = info['ImageID'] container.created = info['Created'] container.status = container.state = runtime['status'] container.input_name = container_id container.original_structure = info container.deep = True container.running = False if container.status == 'inactive' else True return container def _make_image(self, image, info, remote=False): img_obj = Image(image, backend=self, remote=remote) if remote: return img_obj name = info['Id'] img_obj.input_name = image img_obj.name = image img_obj.config = info img_obj.backend = self img_obj.id = name img_obj.registry, img_obj.repo, img_obj.image, img_obj.tag, _ = Decompose( image).all img_obj.repotags = info['RepoTags'] img_obj.created = info['Created'] img_obj.size = None img_obj.original_structure = info img_obj.deep = True img_obj.labels = info.get('Labels', None) img_obj.version = img_obj.get_label("Version") img_obj.release = img_obj.get_label("Release") ostree_manifest = self.syscontainers.get_manifest(image) if ostree_manifest: ostree_manifest = json_loads(ostree_manifest) img_obj.digest = None if ostree_manifest is None else ostree_manifest.get( 'Digest') or ostree_manifest.get('digest') img_obj.os = img_obj.get_label("Os") img_obj.arch = img_obj.get_label("Arch") img_obj.graph_driver = None return img_obj def has_image(self, img): if self.syscontainers.has_image(img): return self.inspect_image(img) return None def has_container(self, container): if self.syscontainers.get_checkout(container): return self.inspect_container(container) return None def inspect_image(self, image): try: return self._make_image( image, self.syscontainers.inspect_system_image(image)) except ValueError: return None def inspect_container(self, container): containers = self.syscontainers.get_containers(containers=[container]) if len(containers) == 0: return None return self._make_container(containers[0]) def start_container(self, name): return self.syscontainers.start_service(name) def stop_container(self, con_obj, **kwargs): return self.syscontainers.stop_service(con_obj.id) def get_images(self, get_all=False): return [ self._make_image(x['Id'], x) for x in self.syscontainers.get_system_images(get_all=get_all) ] def get_containers(self): return [ self._make_container(x) for x in self.syscontainers.get_containers() ] def pull_image(self, image, remote_image_obj=None, **kwargs): return self.syscontainers.pull_image(image) def delete_image(self, image, force=False): return self.syscontainers.delete_image(image) def version(self, image): return self.get_layers(image) def update(self, name, **kwargs): force = kwargs.get('force', False) if force: raise ValueError("--force is not supported by ostree images") return self.syscontainers.pull_image(name) def install(self, image, name, **kwargs): return self.syscontainers.install(image, name) def uninstall(self, iobject, name=None, **kwargs): return self.syscontainers.uninstall(iobject.name) def prune(self): return self.syscontainers.prune_ostree_images() def validate_layer(self, layer): return self.syscontainers.validate_layer(layer) def _get_layer(self, image): return Layer(self.inspect_image(image)) def get_layers(self, image): layers = [] layer = self._get_layer(image) layers.append(layer) while layer.parent: layer = self._get_layer(layer.parent) layers.append(layer) return layers @staticmethod def get_dangling_images(): return [] def make_remote_image(self, image): img_obj = self._make_remote_image(image) img_obj.populate_remote_inspect_info() return img_obj def _make_remote_image(self, image): return self._make_image(image, None, remote=True) def delete_container(self, container, force=False): return self.syscontainers.uninstall(container) def run(self, iobject, **kwargs): return self.syscontainers.start_service(iobject.name) def tag_image(self, src, dest): return self.syscontainers.tag_image(src, dest)
class OSTreeBackend(Backend): def __init__(self): self.input = None self.syscontainers = SystemContainers() class Args: def __init__(self): self.system = os.getuid() == 0 self.user = not self.system self.setvalues = {} self.remote = False self.syscontainers.set_args(Args()) @property def backend(self): return "ostree" def _make_container(self, info): container_id = info['Id'] runtime = self.syscontainers.get_container_runtime_info(container_id) container = Container(container_id, backend=self) container.name = container_id container.id = container_id container.created = info['Created'] container.status = runtime['status'] container.input_name = container_id container.original_structure = info container.deep = True container.image = info['Image'] return container def _make_image(self, image, info): name = info['Id'] image = Image(image, backend=self, remote=False) image.name = name image.config = info image.backend = self image.id = name image.registry = None image.repo = None image.image = name image.tag = name image.repotags = info['RepoTags'] image.created = info['Created'] image.size = None image.original_structure = info image.input_name = info['Id'] image.deep = True image.labels = info['Labels'] image.version = image.get_label("Version") image.release = image.get_label("Release") image.digest = None image.os = image.get_label("Os") image.arch = image.get_label("Arch") image.graph_driver = None return image def has_image(self, img): if self.syscontainers.has_image(img): return self.inspect_image(img) return None def has_container(self, container): if self.syscontainers.get_checkout(container): return self.inspect_container(container) return None def inspect_image(self, image): try: return self._make_image( image, self.syscontainers.inspect_system_image(image)) except ValueError: return None def inspect_container(self, container): containers = self.syscontainers.get_containers(containers=[container]) if len(containers) == 0: return None return self._make_container(containers[0]) def start_container(self, name): return self.syscontainers.start_service(name) def stop_container(self, name): return self.syscontainers.stop_service(name) def get_images(self, get_all=False): return [ self._make_image(x['Id'], x) for x in self.syscontainers.get_system_images(get_all=get_all) ] def get_containers(self): return [ self._make_container(x) for x in self.syscontainers.get_containers() ] def pull_image(self, image, pull_args): return self.syscontainers.pull_image(image) def delete_image(self, image, force=False): return self.syscontainers.delete_image(image) def version(self, image): return self.get_layers(image) def update(self, name, force=False): if force or not self.syscontainers.has_image(name): return self.syscontainers.update(name) return True def install(self, image, name): return self.syscontainers.install(image, name) def uninstall(self, name): return self.syscontainers.uninstall(name) def prune(self): return self.syscontainers.prune_ostree_images() def validate_layer(self, layer): return self.syscontainers.validate_layer(layer) def _get_layer(self, image): return Layer(self.inspect_image(image)) def get_layers(self, image): layers = [] layer = self._get_layer(image) layers.append(layer) while layer.parent: layer = self._get_layer(layer.parent) layers.append(layer) return layers
def ensure_ref_is_not_hex(ref): ref_is_hex = SystemContainers._is_hex(ref) self.assertFalse(ref_is_hex)