def test_share_layers_docker_image(docker_client, cli, datafiles, tmp_path): """ We have the following dependency graphs: (1) multiple-deps.bst |-> layer1.bst |-> layer2.bst |-> layer3.bst (2) nested-deps.bst -> layer2-nest.bst -| | V |------------------------->layer1.bst Test that both images share the layer associated with layer1.bst """ test_element1 = "nested-overwrite.bst" test_element2 = "multiple-deps.bst" project = str(datafiles) checkout_dir = os.path.join(str(tmp_path), "checkout") checkout_dir1 = os.path.join(checkout_dir, "test1") checkout_dir2 = os.path.join(checkout_dir, "test2") build_and_checkout(test_element1, checkout_dir1, cli, project) build_and_checkout(test_element2, checkout_dir2, cli, project) tag1 = get_image_tag(load_image(docker_client, checkout_dir1)) tag2 = get_image_tag(load_image(docker_client, checkout_dir2)) fs1 = docker_client.images.get(tag1).attrs["RootFS"]["Layers"] fs2 = docker_client.images.get(tag2).attrs["RootFS"]["Layers"] # one of the layers should be shared assert len(set(fs1).intersection(set(fs2))) == 1
def test_custom_tag(docker_client, cli, datafiles, tmp_path): test_element = "diamond-deps.bst" project = str(datafiles) checkout_dir = os.path.join(str(tmp_path), "checkout") build_and_checkout(test_element, checkout_dir, cli, project) tag = get_image_tag(load_image(docker_client, checkout_dir)) assert tag.split(":")[1] == "this-is-a-tag"
def test_default_tag(docker_client, cli, datafiles, tmp_path): test_element = "hello-world-image.bst" project = str(datafiles) checkout_dir = os.path.join(str(tmp_path), "checkout") build_and_checkout(test_element, checkout_dir, cli, project) tag = get_image_tag(load_image(docker_client, checkout_dir)) assert tag.split(":")[1] == "latest"
def test_multiple_deps_docker_image(docker_client, cli, datafiles, tmp_path): test_element = "multiple-deps.bst" project = str(datafiles) checkout_dir = os.path.join(str(tmp_path), "checkout") build_and_checkout(test_element, checkout_dir, cli, project) tag = get_image_tag(load_image(docker_client, checkout_dir)) image_attrs = docker_client.images.get(tag).attrs assert len(image_attrs["RootFS"]["Layers"]) == 3 _test_no_file_duplication( _get_layer_files(untar(os.path.join(checkout_dir, "image.tar"))))
def test_multiple_tags(docker_client, cli, datafiles, tmp_path): project = str(datafiles) checkout_dir = os.path.join(str(tmp_path), "checkout") expected_tags = [ "bst-plugins-container-tests/multiple-tags/name1:tag1", "bst-plugins-container-tests/multiple-tags/name1:tag2", "bst-plugins-container-tests/multiple-tags/name2:tag1", "bst-plugins-container-tests/multiple-tags/name2:tag2", "bst-plugins-container-tests/multiple-tags/name3:tag6", ] build_and_checkout("multiple-tags.bst", checkout_dir, cli, project) tags = load_image(docker_client, checkout_dir)[0].tags assert sorted(tags) == sorted(expected_tags)
def test_diamond_deps_docker_image(docker_client, cli, datafiles, tmp_path): test_element = "diamond-deps.bst" project = str(datafiles) checkout_dir = os.path.join(str(tmp_path), "checkout") build_and_checkout(test_element, checkout_dir, cli, project) tag = get_image_tag(load_image(docker_client, checkout_dir)) _check_meta_data(docker_client, tag) image_attrs = docker_client.images.get(tag).attrs assert len(image_attrs["RootFS"]["Layers"]) == 2 # assert that there is no file duplication layer_files = _get_layer_files( untar(os.path.join(checkout_dir, "image.tar"))) _test_no_file_duplication(layer_files)
def test_single_build_dep_docker_image(cli, docker_client, datafiles, tmp_path): test_element = "hello-world-image.bst" project = str(datafiles) checkout_dir = os.path.join(str(tmp_path), "checkout") hello_exec = os.path.join(project, "files", "hello-world-image-fs", "hello") # need to reset permission as copying files into `DATA_DIR` changes permissions os.chmod(hello_exec, READ_WRITE_USER_PERMISSION) build_and_checkout(test_element, checkout_dir, cli, project) tag = get_image_tag(load_image(docker_client, checkout_dir)) # compare output of docker run output = docker_client.containers.run(tag).decode("utf-8") with open(os.path.join(project, "files", "hello-world_output.txt")) as expected_output: assert output == expected_output.read() _check_meta_data(docker_client, tag)
def test_nested_overwrite_docker_image(docker_client, cli, datafiles, tmp_path): # pylint: disable=too-many-locals test_element = "nested-overwrite.bst" project = str(datafiles) checkout_dir = os.path.join(str(tmp_path), "checkout") container_fs_export_dir = os.path.join(str(tmp_path), "fs_extract") exported_tar = os.path.join(container_fs_export_dir, "image.tar") os.makedirs(container_fs_export_dir) build_and_checkout(test_element, checkout_dir, cli, project) tag = get_image_tag(load_image(docker_client, checkout_dir)) image_attrs = docker_client.images.get(tag).attrs assert len(image_attrs["RootFS"]["Layers"]) == 2 # assert that file is indeed overwritten extract_path = untar(os.path.join(checkout_dir, "image.tar")) assert (_get_number_of_file_duplications( _get_layer_files(extract_path)) == 2) # check overwritten file is content is as expected container = docker_client.containers.create(tag, command="/bin/sh") with open(exported_tar, "wb+") as tar_handle: for chunk in container.export(): tar_handle.write(chunk) with tarfile.open(exported_tar) as tar_handle: tar_handle.extractall(path=container_fs_export_dir) try: with open(os.path.join(container_fs_export_dir, "layer1", "hello.txt")) as produced_file: with open( os.path.join(project, "files", "layers", "layer2", "hello.txt")) as actual_file: assert produced_file.read() == actual_file.read() except FileNotFoundError: assert False
def test_filesystem_equality(cli, datafiles, docker_client, docker_registry, tmp_path): # pylint: disable=too-many-locals """ Check that creating a docker_image from a base filesystem, and reimporting this image as a docker_source results in the same filesystem. """ project = str(datafiles) file_system = os.path.join("files", "layers") yaml = YAML() yaml.default_flow_style = False client_to_registry = "{}:5000".format(get_docker_host(docker_client)) # create example-tar.bst local_fs = "local-fs.bst" local_fs_element = { "kind": "import", "sources": [{ "kind": "local", "path": "./{}".format(file_system) }], } create_element(yaml, local_fs, local_fs_element, project) image_name = "example-image" # create example-image.bst example_image = "example-image.bst" example_image_element = { "kind": "docker_image", "config": { "image-names": [ "{}:latest".format(image_name), "bst-plugins-container-tests/{}:latest".format(image_name), ] }, "build-depends": [local_fs], } create_element(yaml, example_image, example_image_element, project) # checkout and push image image_checkout_dir = os.path.join(str(tmp_path), "image_checkout") build_and_checkout(example_image, image_checkout_dir, cli, project) load_image(docker_client, image_checkout_dir) push_image(docker_client, docker_registry, image_name) # create docker source element docker_source = "example-image-source.bst" docker_source_element = { "kind": "import", "sources": [{ "kind": "docker", "registry-url": "http://{}".format(client_to_registry), "image": image_name, "track": "latest", }], } create_element(yaml, docker_source, docker_source_element, project) # source track Docker-sourced import element result = cli.run(project=project, args=["source", "track", docker_source]) result.assert_success() # build Docker-sourced import element tar_checkout_dir = os.path.join(str(tmp_path), "tar_checkout") build_and_checkout(docker_source, tar_checkout_dir, cli, project) # assert files systems are equal layers_dir = os.path.join(project, "files", "layers") assert os.listdir(tar_checkout_dir) == os.listdir(layers_dir) # assert file systems have the same contents _compare_directory_files(layers_dir, tar_checkout_dir)