def test_build_config_with_default_values(self): config_dict = {"image": "some_image_name"} config = V1DockerfileType.from_dict(config_dict) assert config.image_tag == "latest" assert config.filename == POLYAXON_DOCKERFILE_NAME assert config.shell == POLYAXON_DOCKER_SHELL assert config.workdir == POLYAXON_DOCKER_WORKDIR config_dict = {} with self.assertRaises(ValidationError): V1DockerfileType.from_dict(config_dict)
def test_docker_build_context(self, generate_create): build_context = V1DockerfileType(image="foo") self.runner.invoke( docker, [ "generate", "--build-context={}".format( build_context.to_dict(dump=True)) ], ) assert generate_create.call_count == 1
def test_get_generated_dockerfile_path(self): # Create a repo folder repo_path = os.path.join(tempfile.mkdtemp(), "repo") os.mkdir(repo_path) build_context = V1DockerfileType(image="busybox") builder = DockerFileGenerator(build_context=build_context, destination=repo_path) assert builder.dockerfile_path == "{}/{}".format( repo_path, POLYAXON_DOCKERFILE_NAME) builder.clean()
def test_generate(self): # Create a repo folder tmp_path = tempfile.mkdtemp() assert not os.path.isfile("{}/{}".format(tmp_path, POLYAXON_DOCKERFILE_NAME)) build_context = V1DockerfileType( image="busybox", workdir_path=tmp_path, lang_env="en_US.UTF-8", uid=100, gid=100, ) DockerFileGenerator(build_context=build_context, destination=tmp_path).create() assert os.path.isfile("{}/{}".format(tmp_path, POLYAXON_DOCKERFILE_NAME))
def test_build_repo_with_install_step_copy_path_config(self): config_dict = { "image": "tensorflow:1.3.0", "path": ["./module"], "copy": ["/foo/bar"], "run": ["pip install tensor2tensor"], "env": { "LC_ALL": "en_US.UTF-8" }, "filename": "dockerfile", "workdir": "", "shell": "sh", } config = V1DockerfileType.from_dict(config_dict) assert config.to_dict() == config_dict assert config.image_tag == "1.3.0"
def test_build_repo_with_security_context(self): config_dict = { "image": "tensorflow:1.3.0", "run": ["pip install tensor2tensor"], "env": { "LC_ALL": "en_US.UTF-8" }, "uid": 1000, "gid": 3000, "filename": "dockerfile", "workdir": "", "shell": "sh", } config = V1DockerfileType.from_dict(config_dict) assert config.to_dict() == config_dict assert config.image_tag == "1.3.0" assert config.uid == 1000 assert config.gid == 3000
def test_build_config_image_use_cases(self): # Latest config_dict = {"image": "some_image_name"} config = V1DockerfileType.from_dict(config_dict) assert config.image_tag == "latest" # Latest from with docker registry url config_dict = { "image": "registry.foobar.com/my/docker/some_image_name" } config = V1DockerfileType.from_dict(config_dict) assert config.image_tag == "latest" # Latest from with docker registry url with port config_dict = {"image": "registry.foobar.com:4567/some_image_name"} config = V1DockerfileType.from_dict(config_dict) assert config.image_tag == "latest" # Some tag config_dict = {"image": "some_image_name:4567"} config = V1DockerfileType.from_dict(config_dict) assert config.image_tag == "4567" # Some tag config_dict = {"image": "some_image_name:foo"} config = V1DockerfileType.from_dict(config_dict) assert config.image_tag == "foo" # Some tag from with docker registry url config_dict = { "image": "registry.foobar.com/my/docker/some_image_name:foo" } config = V1DockerfileType.from_dict(config_dict) assert config.image_tag == "foo" # Some tag from with docker registry url with port config_dict = {"image": "registry.foobar.com:4567/some_image_name:foo"} config = V1DockerfileType.from_dict(config_dict) assert config.image_tag == "foo"
def test_get_dockerfile_init_container(self): dockerfile_args = V1DockerfileType(image="test/test") container = get_dockerfile_init_container( polyaxon_init=V1PolyaxonInitContainer(image="foo", image_tag=""), dockerfile_args=dockerfile_args, env=None, contexts=PluginsContextsSpec.from_config(V1Plugins(auth=True)), run_path="test", run_instance="foo.bar.runs.uuid", ) assert INIT_DOCKERFILE_CONTAINER_PREFIX in container.name assert container.image == "foo" assert container.image_pull_policy is None assert container.command == ["polyaxon", "docker", "generate"] assert container.args == [ "--build-context={}".format(dockerfile_args.to_dict(dump=True)), "--destination={}".format(CONTEXT_MOUNT_ARTIFACTS), "--copy-path={}".format( CONTEXT_MOUNT_RUN_OUTPUTS_FORMAT.format("test")), "--track", ] assert container.env == [ get_run_instance_env_var(run_instance="foo.bar.runs.uuid") ] assert container.resources == get_init_resources() assert container.volume_mounts == [ get_connections_context_mount( name=constants.CONTEXT_VOLUME_ARTIFACTS, mount_path=CONTEXT_MOUNT_ARTIFACTS, ), get_auth_context_mount(read_only=True), ] dockerfile_args = V1DockerfileType( image="test/test", lang_env="LANG", run=["step1", "step2"], env=[["key1", "val1"], ["key2", "val2"]], uid=2222, gid=2222, ) container = get_dockerfile_init_container( polyaxon_init=V1PolyaxonInitContainer( image="init/init", image_tag="", image_pull_policy="IfNotPresent"), env=[], dockerfile_args=dockerfile_args, mount_path="/somepath", contexts=PluginsContextsSpec.from_config(V1Plugins(auth=True)), run_path="test", run_instance="foo.bar.runs.uuid", ) assert INIT_DOCKERFILE_CONTAINER_PREFIX in container.name assert container.image == "init/init" assert container.image_pull_policy == "IfNotPresent" assert container.command == ["polyaxon", "docker", "generate"] assert container.args == [ "--build-context={}".format(dockerfile_args.to_dict(dump=True)), "--destination=/somepath", "--copy-path={}".format( CONTEXT_MOUNT_RUN_OUTPUTS_FORMAT.format("test")), "--track", ] assert container.env == [ get_run_instance_env_var(run_instance="foo.bar.runs.uuid") ] assert container.resources == get_init_resources() assert container.volume_mounts == [ get_connections_context_mount(name=get_volume_name("/somepath"), mount_path="/somepath"), get_auth_context_mount(read_only=True), ]
def test_build_config(self): config_dict = {"image": "some_image_name"} config = V1DockerfileType.from_dict(config_dict) assert config.image_tag == "latest"
def test_does_not_accept_dockerfiles(self): config_dict = {"dockerfile": "foo/bar"} with self.assertRaises(ValidationError): V1DockerfileType.from_dict(config_dict)
def test_valid_image(self): config_dict = {"image": None} with self.assertRaises(ValidationError): V1DockerfileType.from_dict(config_dict) config_dict = {"image": ""} with self.assertRaises(ValidationError): V1DockerfileType.from_dict(config_dict) config_dict = {"image": "some_image_name:sdf:sdf:foo"} with self.assertRaises(ValidationError): V1DockerfileType.from_dict(config_dict) config_dict = { "image": "registry.foobar.com/my/docker/some_image_name:foo:foo" } with self.assertRaises(ValidationError): V1DockerfileType.from_dict(config_dict) config_dict = {"image": "some_image_name / foo"} with self.assertRaises(ValidationError): V1DockerfileType.from_dict(config_dict) config_dict = {"image": "some_image_name /foo:sdf"} with self.assertRaises(ValidationError): V1DockerfileType.from_dict(config_dict) config_dict = {"image": "some_image_name /foo :sdf"} with self.assertRaises(ValidationError): V1DockerfileType.from_dict(config_dict) config_dict = { "image": "registry.foobar.com:foo:foo/my/docker/some_image_name:foo" } with self.assertRaises(ValidationError): V1DockerfileType.from_dict(config_dict) config_dict = { "image": "registry.foobar.com:foo:foo/my/docker/some_image_name" } with self.assertRaises(ValidationError): V1DockerfileType.from_dict(config_dict) config_dict = { "image": "registry.foobar.com:/my/docker/some_image_name:foo" } with self.assertRaises(ValidationError): V1DockerfileType.from_dict(config_dict)
def test_render_works_as_expected(self): # pylint:disable=too-many-statements # Create a repo folder repo_path = os.path.join(tempfile.mkdtemp(), "repo") os.mkdir(repo_path) build_context = V1DockerfileType(image="busybox") # By default it should use FROM image declare WORKDIR builder = DockerFileGenerator( build_context=build_context, destination=repo_path ) dockerfile = builder.render() builder.clean() assert "FROM busybox" in dockerfile assert "WORKDIR {}".format(POLYAXON_DOCKER_WORKDIR) in dockerfile assert "COPY" not in dockerfile # By default it should use FROM image declare WORKDIR, and work build_context = V1DockerfileType(image="busybox", workdir_path=repo_path) builder = DockerFileGenerator( build_context=build_context, destination=repo_path ) dockerfile = builder.render() builder.clean() assert "COPY {}".format(repo_path) in dockerfile # No lang env assert "LC_ALL" not in dockerfile assert "LANG" not in dockerfile assert "LANGUAGE" not in dockerfile # Add env vars build_context = V1DockerfileType( image="busybox", workdir_path=repo_path, env=[("BLA", "BLA")] ) builder = DockerFileGenerator( build_context=build_context, destination=repo_path ) dockerfile = builder.render() assert "ENV BLA BLA" in dockerfile assert "groupadd" not in dockerfile assert "useradd" not in dockerfile builder.clean() # Add copy steps copy = ["polyaxon_requirements.txt", "polyaxon_setup.sh", "environment.yml"] # Add run steps to act on them run = [ "pip install -r polyaxon_requirements.txt", "./polyaxon_setup.sh", "conda env update -n base -f environment.yml", ] build_context = V1DockerfileType( image="busybox", workdir_path=repo_path, copy=copy, run=run ) builder = DockerFileGenerator( build_context=build_context, destination=repo_path ) dockerfile = builder.render() assert "COPY {} {}".format(copy[0], POLYAXON_DOCKER_WORKDIR) in dockerfile assert "COPY {} {}".format(copy[1], POLYAXON_DOCKER_WORKDIR) in dockerfile assert "COPY {} {}".format(copy[2], POLYAXON_DOCKER_WORKDIR) in dockerfile assert "RUN {}".format(run[0]) in dockerfile assert "RUN {}".format(run[1]) in dockerfile assert "RUN {}".format(run[2]) in dockerfile assert "groupadd" not in dockerfile assert "useradd" not in dockerfile builder.clean() # Add uid but no gid build_context = V1DockerfileType( image="busybox", workdir_path=repo_path, uid=1000 ) builder = DockerFileGenerator( build_context=build_context, destination=repo_path ) dockerfile = builder.render() assert "groupadd" not in dockerfile assert "useradd" not in dockerfile assert "1000" not in dockerfile builder.clean() # Add gid but no uid build_context = V1DockerfileType( image="busybox", workdir_path=repo_path, gid=1000 ) builder = DockerFileGenerator( build_context=build_context, destination=repo_path ) dockerfile = builder.render() assert "groupadd" not in dockerfile assert "useradd" not in dockerfile assert "1000" not in dockerfile builder.clean() # Add uid and gid build_context = V1DockerfileType( image="busybox", workdir_path=repo_path, uid=1000, gid=1000 ) builder = DockerFileGenerator( build_context=build_context, destination=repo_path ) dockerfile = builder.render() assert "groupadd" in dockerfile assert "useradd" in dockerfile assert "-u 1000" in dockerfile assert "-g 1000" in dockerfile builder.clean() # Add lan env build_context = V1DockerfileType( image="busybox", workdir_path=repo_path, lang_env="en_US.UTF-8" ) builder = DockerFileGenerator( build_context=build_context, destination=repo_path ) dockerfile = builder.render() assert "en_US.UTF-8" in dockerfile assert "LC_ALL" in dockerfile assert "LANG" in dockerfile assert "LANGUAGE" in dockerfile builder.clean()