Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load and display image tags for neuro images #873

Merged
merged 12 commits into from
Jul 8, 2019
Merged

Load and display image tags for neuro images #873

merged 12 commits into from
Jul 8, 2019

Conversation

anayden
Copy link
Contributor

@anayden anayden commented Jul 1, 2019

Addresses #852

@@ -114,7 +114,8 @@ def image() -> None:

images = await root.client.images.ls()
for image in images:
click.echo(image)
for tag in images[image]:
click.echo(f"{image} - {tag}")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about we output images with tags in the format that we can re-use for other commands? I believe, it's image://user/ubuntu:tag

result: Dict[URL, List[str]] = {}
for repo in ret["repositories"]:
if repo.startswith("image://"):
name = str(repo)[8:] # len("image://") = 8
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's create a constant for it, prefix = "image://"; name = str(repo)[len(prefix):]

url = URL(f"image://{repo}")
result[url] = []
async with self._registry.request(
"GET", URL(f"{name}/tags/list")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this is not yet implemented in platform-registry, let's comment this out for now or wrap with try-catch-ignore

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been merged already

@asvetlov
Copy link
Contributor

asvetlov commented Jul 3, 2019

Your implementation has O(N*M) complexity which is not desirable.

Please add a new client.images.tags(image) method for /v2/*/tags/list and keep /v2/_catalog untouched.

@serhiy-storchaka
Copy link
Contributor

@anayden, you can use "Closes #xxx" or "Fixes #xxx" to close automatically the corresponded issue.

@codecov
Copy link

codecov bot commented Jul 5, 2019

Codecov Report

Merging #873 into master will decrease coverage by 0.12%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #873      +/-   ##
==========================================
- Coverage   91.37%   91.24%   -0.13%     
==========================================
  Files          37       37              
  Lines        3617     3610       -7     
  Branches      527      520       -7     
==========================================
- Hits         3305     3294      -11     
- Misses        213      218       +5     
+ Partials       99       98       -1
Impacted Files Coverage Δ
neuromation/api/images.py 95.12% <100%> (+0.43%) ⬆️
neuromation/cli/image.py 100% <100%> (ø) ⬆️
neuromation/cli/storage.py 78.07% <0%> (-6.83%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 539d4c6...e62b6fe. Read the comment docs.

@codecov
Copy link

codecov bot commented Jul 5, 2019

Codecov Report

Merging #873 into master will decrease coverage by 1.37%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #873      +/-   ##
==========================================
- Coverage   91.37%   89.99%   -1.38%     
==========================================
  Files          37       38       +1     
  Lines        3617     3608       -9     
  Branches      527      516      -11     
==========================================
- Hits         3305     3247      -58     
- Misses        213      263      +50     
+ Partials       99       98       -1
Impacted Files Coverage Δ
neuromation/api/images.py 93.33% <100%> (-1.36%) ⬇️
neuromation/cli/image.py 100% <100%> (ø) ⬆️
neuromation/api/utils.py 80% <0%> (-16.67%) ⬇️
neuromation/cli/storage.py 77.27% <0%> (-7.62%) ⬇️
neuromation/cli/utils.py 88.1% <0%> (-3.35%) ⬇️
neuromation/cli/main.py 59.7% <0%> (-2%) ⬇️
neuromation/api/jobs.py 94.26% <0%> (-1.86%) ⬇️
neuromation/cli/formatters/jobs.py 95.65% <0%> (-1.74%) ⬇️
neuromation/api/abc.py 91.66% <0%> (-0.65%) ⬇️
... and 5 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 539d4c6...3658b0c. Read the comment docs.

name = str(image)[len(prefix) :]
async with self._registry.request("GET", URL(f"{name}/tags/list")) as resp:
ret = await resp.json()
return [tag for tag in ret.get("tags", [])]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just return ret.get("tags", [])?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, of course! that's an artefact from refactoring


Examples:

neuro image tags image://myfriend/alpine:shared
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the argument can contain a tag?

Copy link
Contributor Author

@anayden anayden Jul 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it can't. Fixed the example

@@ -117,6 +118,27 @@ def image() -> None:
click.echo(image)


@command()
@click.argument("image_name")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not an image name. May be rename the argument to simply image?


async def tags(self, image: URL) -> List[str]:
prefix = "image://"
name = str(image)[len(prefix) :]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if image does not start with "image://"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Added a check and a test for that behavior

@command()
@click.argument("image_name")
@async_cmd()
async def tags(root: Root, image_name: str) -> None:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR's title says about neuro images. Should we add an alias neuro images or correct the title and the original issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we work with a single image here, I believe the command should be neuro image, not neuro images. I think the issue should be rephrased
cc @dalazx

"""
List tags for image in platform registry.

Image name must be URL with image:// scheme.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it needed to add support for relative URIs like image:myimage?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use ImageNameParser to parse image: str to image: DockerImage

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, CLI methods for all image operations must use the same image URI parser -- this is the only way not to confuse the users

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a difference. Other operations accept image URI with tag, but this operation should only accept image URI without tag.

result.append(url)
return result

async def tags(self, image: URL) -> List[str]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, we should accept image: str similarly to API's method async def run(...), which accepts Container with image: str

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't care right now.
It may be changed in the following PR.
I'm working on images API stabilization and have no final decision yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added DockerImage support. This will work even with images with tags, but I'd keep this as undocumented and not officially supported feature :)

Copy link
Contributor

@asvetlov asvetlov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's merge when green

@anayden anayden merged commit e700202 into master Jul 8, 2019
@anayden anayden deleted the an/load_tags branch July 8, 2019 15:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants