def test_get_registry_hostname__bad_url_empty_hostname( self, registry_url: str) -> None: with pytest.raises(ValueError, match="Empty hostname in registry URL"): _ImageNameParser( default_user="******", default_cluster="test-cluster", registry_url=URL(registry_url), )
def test_parse_as_neuro_image__registry_has_port__image_in_bad_repo( self) -> None: my_parser = _ImageNameParser(default_user="******", registry_url=URL("http://localhost:5000")) image = "localhost:9999/bob/library/ubuntu:v10.04" with pytest.raises(ValueError, match="scheme 'image://' is required"): my_parser.parse_as_neuro_image(image)
def test_get_registry_hostname(self, registry_url: str) -> None: parser = _ImageNameParser( default_user="******", default_cluster="test-cluster", registry_url=URL(registry_url), ) assert parser._registry == "reg.neu.ro"
def convert(self, value: str, param: Optional[click.Parameter], ctx: Optional[click.Context]) -> RemoteImage: assert ctx is not None root = cast(Root, ctx.obj) config = Factory(root.config_path)._read() image_parser = _ImageNameParser(config.auth_token.username, config.cluster_config.registry_url) return image_parser.parse_as_neuro_image(value, allow_tag=False)
def test_parse_remote__registry_has_port__image_in_good_repo(self) -> None: my_parser = _ImageNameParser(default_user="******", registry_url=URL("http://localhost:5000")) image = "localhost:5000/bob/library/ubuntu:v10.04" parsed = my_parser.parse_remote(image) assert parsed == RemoteImage(name="library/ubuntu", tag="v10.04", owner="bob", registry="localhost:5000")
def test_is_in_neuro_registry__registry_has_port(self) -> None: my_parser = _ImageNameParser( default_user="******", default_cluster="test-cluster", registry_url=URL("http://localhost:5000"), ) image = "ubuntu:v10.04" parsed = my_parser.parse_as_local_image(image) assert parsed == LocalImage(name="ubuntu", tag="v10.04")
def test_is_in_neuro_registry__registry_has_port__local_image( self) -> None: my_parser = _ImageNameParser( default_user="******", default_cluster="test-cluster", registry_url=URL("http://localhost:5000"), ) image = "ubuntu:v10.04" assert my_parser.is_in_neuro_registry(image) is False
def test_is_in_neuro_registry__registry_has_port__image_in_good_repo( self) -> None: my_parser = _ImageNameParser( default_user="******", default_cluster="test-cluster", registry_url=URL("http://localhost:5000"), ) image = "localhost:5000/bob/library/ubuntu:v10.04" assert my_parser.is_in_neuro_registry(image) is True
def parse_resource_for_sharing(uri: str, root: Root) -> URL: """ Parses the neuromation resource URI string. Available schemes: storage, image, job. For image URIs, tags are not allowed. """ if uri.startswith("image:"): parser = _ImageNameParser(root.username, root.registry_url) image = parser.parse_as_neuro_image(uri, allow_tag=False) uri = str(image) return uri_from_cli(uri, root.username, allowed_schemes=("storage", "image", "job"))
def convert(self, value: str, param: Optional[click.Parameter], ctx: Optional[click.Context]) -> LocalImage: assert ctx is not None root = cast(Root, ctx.obj) config = Factory(root.config_path)._read() image_parser = _ImageNameParser(config.auth_token.username, config.cluster_config.registry_url) if image_parser.is_in_neuro_registry(value): raise click.BadParameter("remote image cannot be used as local", ctx, param, self.name) else: parsed_image = image_parser.parse_as_local_image(value) return parsed_image
def test_parse_remote__registry_has_port__image_in_other_repo( self) -> None: my_parser = _ImageNameParser(default_user="******", registry_url=URL("http://localhost:5000")) image = "example.com:9999/bob/library/ubuntu:v10.04" parsed = my_parser.parse_remote(image) # NOTE: "owner" is parsed only for images in neuromation registry assert parsed == RemoteImage( name="bob/library/ubuntu", tag="v10.04", owner=None, registry="example.com:9999", )
def test_parse_remote__registry_has_port__neuro_image(self) -> None: my_parser = _ImageNameParser( default_user="******", default_cluster="test-cluster", registry_url=URL("http://localhost:5000"), ) image = "image://test-cluster/bob/library/ubuntu:v10.04" parsed = my_parser.parse_remote(image) assert parsed == RemoteImage.new_neuro_image( name="library/ubuntu", tag="v10.04", owner="bob", cluster_name="test-cluster", registry="localhost:5000", )
def test_get_registry_hostname_with_port(self, registry_url: str) -> None: parser = _ImageNameParser(default_user="******", registry_url=URL(registry_url)) assert parser._registry == "reg.neu.ro:5000"
class TestImages: parser = _ImageNameParser(default_user="******", registry_url=URL("https://registry-dev.neu.ro")) @asynctest.mock.patch( "aiodocker.Docker.__init__", side_effect=ValueError( "text Either DOCKER_HOST or local sockets are not available text"), ) async def test_unavailable_docker(self, patched_init: Any, make_client: _MakeClient) -> None: image = self.parser.parse_as_neuro_image("image://bob/image:bananas") local_image = self.parser.parse_as_local_image("bananas:latest") async with make_client("https://api.localhost.localdomain") as client: with pytest.raises(DockerError, match=r"Docker engine is not available.+"): await client.images.pull(image, local_image) @asynctest.mock.patch("aiodocker.Docker.__init__", side_effect=ValueError("something went wrong")) async def test_unknown_docker_error(self, patched_init: Any, make_client: _MakeClient) -> None: image = self.parser.parse_as_neuro_image("image://bob/image:bananas") local_image = self.parser.parse_as_local_image("bananas:latest") async with make_client("https://api.localhost.localdomain") as client: with pytest.raises(ValueError, match=r"something went wrong"): await client.images.pull(image, local_image) @asynctest.mock.patch("aiodocker.images.DockerImages.tag") async def test_push_non_existent_image(self, patched_tag: Any, make_client: _MakeClient) -> None: patched_tag.side_effect = DockerError(404, {"message": "Mocked error"}) image = self.parser.parse_as_neuro_image( "image://bob/image:bananas-no-more") local_image = self.parser.parse_as_local_image("bananas:latest") async with make_client("https://api.localhost.localdomain") as client: with pytest.raises(ValueError, match=r"not found"): await client.images.push(local_image, image) @asynctest.mock.patch("aiodocker.images.DockerImages.tag") @asynctest.mock.patch("aiodocker.images.DockerImages.push") async def test_push_image_to_foreign_repo( self, patched_push: Any, patched_tag: Any, make_client: _MakeClient) -> None: patched_tag.return_value = True patched_push.side_effect = DockerError(403, {"message": "Mocked error"}) image = self.parser.parse_as_neuro_image( "image://bob/image:bananas-no-more") local_image = self.parser.parse_as_local_image("bananas:latest") async with make_client("https://api.localhost.localdomain") as client: with pytest.raises(AuthorizationError): await client.images.push(local_image, image) @asynctest.mock.patch("aiodocker.images.DockerImages.tag") @asynctest.mock.patch("aiodocker.images.DockerImages.push") async def test_push_image_with_docker_api_error( self, patched_push: Any, patched_tag: Any, make_client: _MakeClient) -> None: async def error_generator() -> AsyncIterator[Dict[str, Any]]: yield {"error": True, "errorDetail": {"message": "Mocked message"}} patched_tag.return_value = True patched_push.return_value = error_generator() image = self.parser.parse_as_neuro_image( "image://bob/image:bananas-wrong-food") local_image = self.parser.parse_as_local_image("bananas:latest") async with make_client("https://api.localhost.localdomain") as client: with pytest.raises(DockerError) as exc_info: await client.images.push(local_image, image) assert exc_info.value.status == 900 assert exc_info.value.message == "Mocked message" @asynctest.mock.patch("aiodocker.images.DockerImages.tag") @asynctest.mock.patch("aiodocker.images.DockerImages.push") async def test_success_push_image(self, patched_push: Any, patched_tag: Any, make_client: _MakeClient) -> None: async def message_generator() -> AsyncIterator[Dict[str, Any]]: yield {} patched_tag.return_value = True patched_push.return_value = message_generator() image = self.parser.parse_as_neuro_image( "image://bob/image:bananas-is-here") local_image = self.parser.parse_as_local_image("bananas:latest") async with make_client("https://api.localhost.localdomain") as client: result = await client.images.push(local_image, image) assert result == image @asynctest.mock.patch("aiodocker.images.DockerImages.tag") @asynctest.mock.patch("aiodocker.images.DockerImages.push") async def test_success_push_image_no_target( self, patched_push: Any, patched_tag: Any, make_client: _MakeClient) -> None: async def message_generator() -> AsyncIterator[Dict[str, Any]]: yield {} patched_tag.return_value = True patched_push.return_value = message_generator() image = self.parser.parse_as_neuro_image("image://user/bananas:latest") local_image = self.parser.parse_as_local_image("bananas:latest") async with make_client("https://api.localhost.localdomain") as client: result = await client.images.push(local_image) assert result == image @asynctest.mock.patch("aiodocker.images.DockerImages.pull") async def test_pull_non_existent_image(self, patched_pull: Any, make_client: _MakeClient) -> None: patched_pull.side_effect = DockerError(404, {"message": "Mocked error"}) async with make_client("https://api.localhost.localdomain") as client: image = self.parser.parse_as_neuro_image( "image://bob/image:no-bananas-here") local_image = self.parser.parse_as_local_image("bananas:latest") with pytest.raises(ValueError, match=r"not found"): await client.images.pull(image, local_image) @asynctest.mock.patch("aiodocker.images.DockerImages.pull") async def test_pull_image_from_foreign_repo( self, patched_pull: Any, make_client: _MakeClient) -> None: patched_pull.side_effect = DockerError(403, {"message": "Mocked error"}) image = self.parser.parse_as_neuro_image( "image://bob/image:not-your-bananas") local_image = self.parser.parse_as_local_image("bananas:latest") async with make_client("https://api.localhost.localdomain") as client: with pytest.raises(AuthorizationError): await client.images.pull(image, local_image) @asynctest.mock.patch("aiodocker.images.DockerImages.pull") async def test_pull_image_with_docker_api_error(self, patched_pull: Any, make_client: Any) -> None: async def error_generator() -> AsyncIterator[Dict[str, Any]]: yield {"error": True, "errorDetail": {"message": "Mocked message"}} patched_pull.return_value = error_generator() image = self.parser.parse_as_neuro_image("image://bob/image:nuts-here") async with make_client("https://api.localhost.localdomain") as client: with pytest.raises(DockerError) as exc_info: await client.images.pull(image, image) assert exc_info.value.status == 900 assert exc_info.value.message == "Mocked message" @asynctest.mock.patch("aiodocker.images.DockerImages.tag") @asynctest.mock.patch("aiodocker.images.DockerImages.pull") async def test_success_pull_image(self, patched_pull: Any, patched_tag: Any, make_client: _MakeClient) -> None: async def message_generator() -> AsyncIterator[Dict[str, Any]]: yield {} patched_tag.return_value = True patched_pull.return_value = message_generator() image = self.parser.parse_as_neuro_image("image://bob/image:bananas") local_image = self.parser.parse_as_local_image("bananas:latest") async with make_client("https://api.localhost.localdomain") as client: result = await client.images.pull(image, local_image) assert result == local_image @asynctest.mock.patch("aiodocker.images.DockerImages.tag") @asynctest.mock.patch("aiodocker.images.DockerImages.pull") async def test_success_pull_image_no_target( self, patched_pull: Any, patched_tag: Any, make_client: _MakeClient) -> None: async def message_generator() -> AsyncIterator[Dict[str, Any]]: yield {} patched_tag.return_value = True patched_pull.return_value = message_generator() image = self.parser.parse_as_neuro_image("image://bob/bananas:latest") local_image = self.parser.parse_as_local_image("bananas:latest") async with make_client("https://api.localhost.localdomain") as client: result = await client.images.pull(image) assert result == local_image
def test_is_in_neuro_registry__registry_has_port__image_in_bad_repo( self) -> None: my_parser = _ImageNameParser(default_user="******", registry_url=URL("http://localhost:5000")) image = "localhost:9999/bob/library/ubuntu:v10.04" assert my_parser.is_in_neuro_registry(image) is False
class TestImageParser: parser = _ImageNameParser(default_user="******", registry_url=URL("https://reg.neu.ro")) @pytest.mark.parametrize( "image", [ "image://me/ubuntu:v10.04", "image://~/ubuntu:v10.04", "image:///ubuntu:v10.04", "image:ubuntu:v10.04", "ubuntu:v10.04", ], ) def test_has_tag_ok(self, image: str) -> None: assert self.parser.has_tag(image) def test_has_tag_no_tag(self) -> None: image = "ubuntu" assert not self.parser.has_tag(image) def test_has_tag_no_tag_with_slash(self) -> None: image = "library/ubuntu" assert not self.parser.has_tag(image) def test_has_tag_empty_tag(self) -> None: image = "ubuntu:" with pytest.raises(ValueError, match="empty tag"): self.parser.has_tag(image) def test_has_tag_empty_tag_with_slash(self) -> None: image = "library/ubuntu:" with pytest.raises(ValueError, match="empty tag"): self.parser.has_tag(image) def test_has_tag_empty_image_name(self) -> None: image = ":latest" with pytest.raises(ValueError, match="empty name"): self.parser.has_tag(image) def test_has_tag_too_many_tags(self) -> None: image = "ubuntu:v10.04:latest" with pytest.raises(ValueError, match="too many tags"): self.parser.has_tag(image) @pytest.mark.parametrize( "registry_url", [ "http://reg.neu.ro", "https://reg.neu.ro", "https://reg.neu.ro/bla/bla" ], ) def test_get_registry_hostname(self, registry_url: str) -> None: parser = _ImageNameParser(default_user="******", registry_url=URL(registry_url)) assert parser._registry == "reg.neu.ro" @pytest.mark.parametrize( "registry_url", ["http://reg.neu.ro:5000", "http://reg.neu.ro:5000/bla/bla"]) def test_get_registry_hostname_with_port(self, registry_url: str) -> None: parser = _ImageNameParser(default_user="******", registry_url=URL(registry_url)) assert parser._registry == "reg.neu.ro:5000" @pytest.mark.parametrize( "registry_url", ["", "reg.neu.ro", "reg.neu.ro:5000", "https://", "https:///bla/bla"], ) def test_get_registry_hostname__bad_url_empty_hostname( self, registry_url: str) -> None: with pytest.raises(ValueError, match="Empty hostname in registry URL"): _ImageNameParser(default_user="******", registry_url=URL(registry_url)) def test_split_image_name_no_tag(self) -> None: splitted = self.parser._split_image_name("ubuntu", self.parser.default_tag) assert splitted == ("ubuntu", "latest") def test_split_image_name_with_tag(self) -> None: splitted = self.parser._split_image_name("ubuntu:v10.04", self.parser.default_tag) assert splitted == ("ubuntu", "v10.04") def test_split_image_name_empty_tag(self) -> None: with pytest.raises(ValueError, match="empty tag"): self.parser._split_image_name("ubuntu:", self.parser.default_tag) def test_split_image_name_two_tags(self) -> None: with pytest.raises(ValueError, match="too many tags"): self.parser._split_image_name("ubuntu:v10.04:LTS", self.parser.default_tag) def test_split_image_name_with_registry_port_no_tag(self) -> None: splitted = self.parser._split_image_name("localhost:5000/ubuntu", self.parser.default_tag) assert splitted == ("localhost:5000/ubuntu", "latest") def test_split_image_name_with_registry_port_with_tag(self) -> None: splitted = self.parser._split_image_name( "localhost:5000/ubuntu:v10.04", self.parser.default_tag) assert splitted == ("localhost:5000/ubuntu", "v10.04") def test_split_image_name_with_registry_port_two_tags(self) -> None: with pytest.raises(ValueError, match="too many tags"): self.parser._split_image_name("localhost:5000/ubuntu:v10.04:LTS", self.parser.default_tag) def test_split_image_name_with_registry_port_empty_tag(self) -> None: with pytest.raises(ValueError, match="empty tag"): self.parser._split_image_name("localhost:5000/ubuntu:", self.parser.default_tag) def test_split_image_name_with_registry_port_slash_in_tag(self) -> None: with pytest.raises(ValueError, match="invalid tag"): self.parser._split_image_name("localhost:5000/ubuntu:v10/04", self.parser.default_tag) # public method: parse_local @pytest.mark.parametrize( "url", ["image://", "image:///", "image://bob", "image://bob/"]) def test_parse_as_neuro_image__no_image_name(self, url: str) -> None: with pytest.raises(ValueError, match="no image name specified"): self.parser.parse_as_neuro_image(url) def test_parse_as_local_image_empty_fail(self) -> None: image = "" with pytest.raises(ValueError, match="empty image name"): self.parser.parse_as_local_image(image) def test_parse_as_local_image_dash_fail(self) -> None: image = "-zxc" with pytest.raises(ValueError, match="image cannot start with dash"): self.parser.parse_as_local_image(image) def test_parse_as_local_image_with_image_scheme_fail(self) -> None: image = "image://ubuntu" with pytest.raises( ValueError, match="scheme 'image://' is not allowed for local images"): self.parser.parse_as_local_image(image) def test_parse_as_local_image_with_other_scheme_ok(self) -> None: image = "http://ubuntu" parsed = self.parser.parse_as_local_image(image) # instead of parser, the docker client will fail assert parsed == LocalImage(name="http://ubuntu", tag="latest") def test_parse_as_local_image_no_tag(self) -> None: image = "ubuntu" parsed = self.parser.parse_as_local_image(image) assert parsed == LocalImage(name="ubuntu", tag="latest") def test_parse_as_local_image_with_tag(self) -> None: image = "ubuntu:v10.04" parsed = self.parser.parse_as_local_image(image) assert parsed == LocalImage(name="ubuntu", tag="v10.04") def test_parse_as_local_image_2_tag_fail(self) -> None: image = "ubuntu:v10.04:LTS" with pytest.raises(ValueError, match="too many tags"): self.parser.parse_as_local_image(image) # public method: parse_remote @pytest.mark.parametrize( "url", [ "image://bob/ubuntu:v10.04?key=value", "image://bob/ubuntu?key=value", "image:///ubuntu?key=value", "image:ubuntu?key=value", ], ) def test_parse_as_neuro_image__with_query__fail(self, url: str) -> None: with pytest.raises(ValueError, match="query is not allowed"): self.parser.parse_as_neuro_image(url) @pytest.mark.parametrize( "url", [ "image://bob/ubuntu:v10.04#fragment", "image://bob/ubuntu#fragment", "image:///ubuntu#fragment", "image:ubuntu#fragment", ], ) def test_parse_as_neuro_image__with_fragment__fail(self, url: str) -> None: with pytest.raises(ValueError, match="fragment is not allowed"): self.parser.parse_as_neuro_image(url) def test_parse_as_neuro_image__with_user__fail(self) -> None: url = "image://user@bob/ubuntu" with pytest.raises(ValueError, match="user is not allowed"): self.parser.parse_as_neuro_image(url) def test_parse_as_neuro_image__with_password__fail(self) -> None: url = "image://:password@bob/ubuntu" with pytest.raises(ValueError, match="password is not allowed"): self.parser.parse_as_neuro_image(url) def test_parse_as_neuro_image__with_port__fail(self) -> None: url = "image://bob:443/ubuntu" with pytest.raises(ValueError, match="port is not allowed"): self.parser.parse_as_neuro_image(url) def test_parse_as_neuro_image_empty_fail__fail(self) -> None: image = "" with pytest.raises(ValueError, match="empty image name"): self.parser.parse_as_neuro_image(image) def test_parse_as_neuro_image_dash_fail__fail(self) -> None: image = "-zxc" with pytest.raises(ValueError, match="image cannot start with dash"): self.parser.parse_as_neuro_image(image) def test_parse_as_neuro_image_no_scheme_fail(self) -> None: image = "ubuntu" with pytest.raises( ValueError, match="scheme 'image://' is required for remote images"): self.parser.parse_as_neuro_image(image) def test_parse_as_neuro_image_invalid_scheme_1_fail(self) -> None: image = "ubuntu:latest" with pytest.raises( ValueError, match="scheme 'image://' is required for remote images"): self.parser.parse_as_neuro_image(image) def test_parse_as_neuro_image_invalid_scheme_2_fail(self) -> None: image = "http://ubuntu" with pytest.raises( ValueError, match="scheme 'image://' is required for remote images"): self.parser.parse_as_neuro_image(image) def test_parse_as_neuro_image_with_scheme_with_user_with_tag(self) -> None: image = "image://bob/ubuntu:v10.04" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="ubuntu", tag="v10.04", owner="bob", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_with_user_with_tag_2( self) -> None: image = "image://bob/library/ubuntu:v10.04" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="library/ubuntu", tag="v10.04", owner="bob", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_with_user_no_tag(self) -> None: image = "image://bob/ubuntu" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="ubuntu", tag="latest", owner="bob", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_with_user_no_tag_2(self) -> None: image = "image://bob/library/ubuntu" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="library/ubuntu", tag="latest", owner="bob", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_no_slash_no_user_no_tag( self) -> None: image = "image:ubuntu" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="ubuntu", tag="latest", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_no_slash_no_user_no_tag_2( self) -> None: image = "image:library/ubuntu" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="library/ubuntu", tag="latest", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_no_slash_no_user_with_tag( self) -> None: image = "image:ubuntu:v10.04" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="ubuntu", tag="v10.04", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_no_slash_no_user_with_tag_2( self) -> None: image = "image:library/ubuntu:v10.04" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="library/ubuntu", tag="v10.04", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_1_slash_no_user_no_tag( self) -> None: image = "image:/ubuntu" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="ubuntu", tag="latest", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_1_slash_no_user_no_tag_2( self) -> None: image = "image:/library/ubuntu" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="library/ubuntu", tag="latest", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_1_slash_no_user_with_tag( self) -> None: image = "image:/ubuntu:v10.04" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="ubuntu", tag="v10.04", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_1_slash_no_user_with_tag_2( self) -> None: image = "image:/library/ubuntu:v10.04" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="library/ubuntu", tag="v10.04", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_2_slash_user_no_tag_fail( self) -> None: image = "image://ubuntu" with pytest.raises(ValueError, match="no image name specified"): self.parser.parse_as_neuro_image(image) def test_parse_as_neuro_image_with_scheme_2_slash_user_with_tag_fail( self) -> None: image = "image://ubuntu:v10.04" with pytest.raises(ValueError, match="port can't be converted to integer"): self.parser.parse_as_neuro_image(image) def test_parse_as_neuro_image_with_scheme_3_slash_no_user_no_tag( self) -> None: image = "image:///ubuntu" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="ubuntu", tag="latest", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_3_slash_no_user_no_tag_2( self) -> None: image = "image:///library/ubuntu" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="library/ubuntu", tag="latest", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_3_slash_no_user_with_tag( self) -> None: image = "image:///ubuntu:v10.04" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="ubuntu", tag="v10.04", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_3_slash_no_user_with_tag_2( self) -> None: image = "image:///library/ubuntu:v10.04" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="library/ubuntu", tag="v10.04", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_4_slash_no_user_with_tag( self) -> None: image = "image:////ubuntu:v10.04" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="ubuntu", tag="v10.04", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_4_slash_no_user_with_tag_2( self) -> None: image = "image:////library/ubuntu:v10.04" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="library/ubuntu", tag="v10.04", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_4_slash_no_user_no_tag( self) -> None: image = "image:////ubuntu" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="ubuntu", tag="latest", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_4_slash_no_user_no_tag_2( self) -> None: image = "image:////library/ubuntu" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="library/ubuntu", tag="latest", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_tilde_user_no_tag(self) -> None: image = "image://~/ubuntu" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="ubuntu", tag="latest", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_tilde_user_no_tag_2( self) -> None: image = "image://~/library/ubuntu" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="library/ubuntu", tag="latest", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_tilde_user_with_tag( self) -> None: image = "image://~/ubuntu:v10.04" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="ubuntu", tag="v10.04", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_with_scheme_tilde_user_with_tag_2( self) -> None: image = "image://~/library/ubuntu:v10.04" parsed = self.parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="library/ubuntu", tag="v10.04", owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_no_scheme_no_slash_no_tag_fail(self) -> None: image = "ubuntu" with pytest.raises(ValueError, match="scheme 'image://' is required"): self.parser.parse_as_neuro_image(image) def test_parse_as_neuro_image_no_scheme_no_slash_with_tag_fail( self) -> None: image = "ubuntu:v10.04" with pytest.raises(ValueError, match="scheme 'image://' is required"): self.parser.parse_as_neuro_image(image) def test_parse_as_neuro_image_no_scheme_1_slash_no_tag_fail(self) -> None: image = "library/ubuntu" with pytest.raises(ValueError, match="scheme 'image://' is required"): self.parser.parse_as_neuro_image(image) def test_parse_as_neuro_image_no_scheme_1_slash_with_tag_fail( self) -> None: image = "library/ubuntu:v10.04" with pytest.raises(ValueError, match="scheme 'image://' is required"): self.parser.parse_as_neuro_image(image) def test_parse_as_neuro_image_no_scheme_2_slash_no_tag_fail(self) -> None: image = "docker.io/library/ubuntu" with pytest.raises(ValueError, match="scheme 'image://' is required"): self.parser.parse_as_neuro_image(image) def test_parse_as_neuro_image_no_scheme_2_slash_with_tag_fail( self) -> None: image = "docker.io/library/ubuntu:v10.04" with pytest.raises(ValueError, match="scheme 'image://' is required"): self.parser.parse_as_neuro_image(image) def test_parse_as_neuro_image_no_scheme_3_slash_no_tag_fail(self) -> None: image = "something/docker.io/library/ubuntu" with pytest.raises(ValueError, match="scheme 'image://' is required"): self.parser.parse_as_neuro_image(image) def test_is_neuro_registry_with_registry_prefix(self) -> None: assert self.parser.is_in_neuro_registry("reg.neu.ro/user/image:tag") assert not self.parser.is_in_neuro_registry( 'docker.io/library/ubuntu"') def test_parse_as_neuro_image_with_registry_prefix(self) -> None: image = self.parser.parse_as_neuro_image("reg.neu.ro/user/image:tag") assert str(image) == "image://user/image:tag" def test_parse_as_neuro_image_no_scheme_3_slash_with_tag_fail( self) -> None: image = "something/docker.io/library/ubuntu:v10.04" with pytest.raises(ValueError, match="scheme 'image://' is required"): self.parser.parse_as_neuro_image(image) def test_parse_as_neuro_image_allow_tag_false_with_scheme_no_tag( self) -> None: image = "image:ubuntu" parsed = self.parser.parse_as_neuro_image(image, allow_tag=False) assert parsed == RemoteImage(name="ubuntu", tag=None, owner="alice", registry="reg.neu.ro") def test_parse_as_neuro_image_allow_tag_false_no_scheme_no_tag( self) -> None: image = "ubuntu" with pytest.raises(ValueError, match="scheme 'image://' is required"): self.parser.parse_as_neuro_image(image, allow_tag=False) def test_parse_as_neuro_image_allow_tag_false_no_scheme_with_tag( self) -> None: image = "ubuntu:latest" with pytest.raises(ValueError, match="tag is not allowed"): self.parser.parse_as_neuro_image(image, allow_tag=False) def test_convert_to_local_image(self) -> None: neuro_image = RemoteImage(name="ubuntu", tag="latest", owner="artem", registry="reg.com") local_image = self.parser.convert_to_local_image(neuro_image) assert local_image == LocalImage(name="ubuntu", tag="latest") def test_convert_to_neuro_image(self) -> None: local_image = LocalImage(name="ubuntu", tag="latest") neuro_image = self.parser.convert_to_neuro_image(local_image) assert neuro_image == RemoteImage(name="ubuntu", tag="latest", owner="alice", registry="reg.neu.ro") def test_normalize_is_neuro_image(self) -> None: image = "image://~/ubuntu" assert self.parser.normalize(image) == "image://alice/ubuntu:latest" def test_normalize_is_local_image(self) -> None: image = "docker.io/library/ubuntu" assert self.parser.normalize( image) == "docker.io/library/ubuntu:latest" def test_normalize_invalid_image_name_left_as_is(self) -> None: image = "image://ubuntu" assert self.parser.normalize(image) == "image://ubuntu" # corner case 'image:latest' def test_parse_as_neuro_image__ambiguous_case__fail(self) -> None: url = "image:latest" with pytest.raises(ValueError, match="ambiguous value"): self.parser.parse_as_neuro_image(url) def test_parse_as_local_image__ambiguous_case__fail(self) -> None: url = "image:latest" with pytest.raises(ValueError, match="ambiguous value"): self.parser.parse_as_local_image(url) # other corner cases def test_is_in_neuro_registry__registry_has_port__neuro_image( self) -> None: my_parser = _ImageNameParser(default_user="******", registry_url=URL("http://localhost:5000")) image = "image://bob/library/ubuntu:v10.04" assert my_parser.is_in_neuro_registry(image) is True def test_is_in_neuro_registry__registry_has_port__image_in_good_repo( self) -> None: my_parser = _ImageNameParser(default_user="******", registry_url=URL("http://localhost:5000")) image = "localhost:5000/bob/library/ubuntu:v10.04" assert my_parser.is_in_neuro_registry(image) is True def test_is_in_neuro_registry__registry_has_port__image_in_bad_repo( self) -> None: my_parser = _ImageNameParser(default_user="******", registry_url=URL("http://localhost:5000")) image = "localhost:9999/bob/library/ubuntu:v10.04" assert my_parser.is_in_neuro_registry(image) is False def test_is_in_neuro_registry__registry_has_port__local_image( self) -> None: my_parser = _ImageNameParser(default_user="******", registry_url=URL("http://localhost:5000")) image = "ubuntu:v10.04" assert my_parser.is_in_neuro_registry(image) is False def test_is_in_neuro_registry__registry_has_port(self) -> None: my_parser = _ImageNameParser(default_user="******", registry_url=URL("http://localhost:5000")) image = "ubuntu:v10.04" parsed = my_parser.parse_as_local_image(image) assert parsed == LocalImage(name="ubuntu", tag="v10.04") def test_parse_as_neuro_image__registry_has_port__neuro_image( self) -> None: my_parser = _ImageNameParser(default_user="******", registry_url=URL("http://localhost:5000")) image = "image://bob/library/ubuntu:v10.04" parsed = my_parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="library/ubuntu", tag="v10.04", owner="bob", registry="localhost:5000") def test_parse_as_neuro_image__registry_has_port__image_in_good_repo( self) -> None: my_parser = _ImageNameParser(default_user="******", registry_url=URL("http://localhost:5000")) image = "localhost:5000/bob/library/ubuntu:v10.04" parsed = my_parser.parse_as_neuro_image(image) assert parsed == RemoteImage(name="library/ubuntu", tag="v10.04", owner="bob", registry="localhost:5000") def test_parse_as_neuro_image__registry_has_port__image_in_bad_repo( self) -> None: my_parser = _ImageNameParser(default_user="******", registry_url=URL("http://localhost:5000")) image = "localhost:9999/bob/library/ubuntu:v10.04" with pytest.raises(ValueError, match="scheme 'image://' is required"): my_parser.parse_as_neuro_image(image) def test_parse_remote__registry_has_port__neuro_image(self) -> None: my_parser = _ImageNameParser(default_user="******", registry_url=URL("http://localhost:5000")) image = "image://bob/library/ubuntu:v10.04" parsed = my_parser.parse_remote(image) assert parsed == RemoteImage(name="library/ubuntu", tag="v10.04", owner="bob", registry="localhost:5000") def test_parse_remote__registry_has_port__image_in_good_repo(self) -> None: my_parser = _ImageNameParser(default_user="******", registry_url=URL("http://localhost:5000")) image = "localhost:5000/bob/library/ubuntu:v10.04" parsed = my_parser.parse_remote(image) assert parsed == RemoteImage(name="library/ubuntu", tag="v10.04", owner="bob", registry="localhost:5000") def test_parse_remote__registry_has_port__image_in_other_repo( self) -> None: my_parser = _ImageNameParser(default_user="******", registry_url=URL("http://localhost:5000")) image = "example.com:9999/bob/library/ubuntu:v10.04" parsed = my_parser.parse_remote(image) # NOTE: "owner" is parsed only for images in neuromation registry assert parsed == RemoteImage( name="bob/library/ubuntu", tag="v10.04", owner=None, registry="example.com:9999", )