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

fix: parseImageRef tag parsing (#2411) #2412

Closed

Conversation

danchenko-dmitry
Copy link
Contributor

@danchenko-dmitry danchenko-dmitry commented Jan 31, 2025

Description

I've changed behaviour of parseImageRef func.
before:
In case when imageRef -> "my-private-repo.company.com/my-app:some-tag@sha256:1420cefd4b20014b3361951c22593de6e9a2476bbbadd1759464eab5bfc0d34f"
It returns empty tag in Artifact.Tag;

after:
In new version this behaviour fixed and it returns tag instead empty string.
you can see it it "15. private registry image ref tag & with digest" test.

Related issues

Checklist

  • I've read the guidelines for contributing to this repository.
  • I've added tests that prove my fix is effective or that my feature works.
  • [ Not need] I've updated the documentation with the relevant information (if needed).
  • [Not need] I've added usage information (if the PR introduces new options)
  • I've included a "before" and "after" example to the description (if the PR is a user interface change).

@CLAassistant
Copy link

CLAassistant commented Jan 31, 2025

CLA assistant check
All committers have signed the CLA.

hasTag = true
}

ref, err := containerimage.ParseReference(namePart, containerimage.WeakValidation)
Copy link
Contributor

Choose a reason for hiding this comment

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

this function calls twice.

}

if hasDigest {
digestRef, err := containerimage.ParseReference(imageRef, containerimage.WeakValidation)
Copy link
Contributor

Choose a reason for hiding this comment

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

the second call.

Comment on lines 219 to 220
var hasDigest bool
var hasTag bool
Copy link
Contributor

Choose a reason for hiding this comment

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

do we really need these variables?
artifact.Digest == "" means hasDigest is false, right?

Comment on lines 221 to 226
if len(parts) > 1 {
hasDigest = true
}
if len(strings.Split(namePart,":"))>1{
hasTag = true
}
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 improve these if-statements

Comment on lines 242 to 247
case ok && hasTag:
artifact.Tag = tagged.TagStr()
case ok && !hasTag && !hasDigest:
artifact.Tag = tagged.TagStr()
case ok && hasTag && hasDigest:
artifact.Tag = tagged.TagStr()
Copy link
Contributor

Choose a reason for hiding this comment

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

ok should be true for all cases, right?
and artifact.Tag = tagged.TagStr() calls for all cases.
honestly it doesn't look like a good way to check tags/digest.

@afdesk
Copy link
Contributor

afdesk commented Feb 3, 2025

@danchenko-dmitry thanks for your contribution and your time.

i left some comments. and think we should refactor this code.
and please, fix the linter suggestions.

@afdesk
Copy link
Contributor

afdesk commented Feb 3, 2025

@danchenko-dmitry please correct me.
it seems google/go-containerregistry should parse such cases correctly: google/go-containerregistry#391 (google/go-containerregistry#351)

@afdesk
Copy link
Contributor

afdesk commented Feb 3, 2025

also in any case, you can take a look at NewDigest function to re-use the code, it looks like a good sample

@danchenko-dmitry
Copy link
Contributor Author

google/go-containerregistry#39

I've prepared demo repo to demonstrate how it works:
https://github.com/danchenko-dmitry/tag-sandbox
This fix doesn't work in our case.

@afdesk
Copy link
Contributor

afdesk commented Feb 3, 2025

@danchenko-dmitry thanks!
it seems i understood a reason - containerimage.ParseReference returns iegher tag or digest, right?
can we do something simplier to get a tag and a digest? for ex:

update:

artifactTag = strings.TrimPrefix(strings.TrimSuffix(strings.TrimPrefix(imageRef, ref.Context().Name()), "@"+artifactDigest), ":")

https://go.dev/play/p/d3BZ2biZf_p

I'm not sure about this solution. Just the first idea.
maybe there is something more gracefully

wdyt?

@danchenko-dmitry
Copy link
Contributor Author

wdyt?

Well, thank you for your support.
I've tried to refactor this code and make it more readable and more clear.
I've tried to consider all your comments and here is all I've got.
I hope you will be satisfied .. :-)

@simar7
Copy link
Member

simar7 commented Feb 3, 2025

@danchenko-dmitry thanks for your PR! It looks like the tests and the linter are failing. Could you look into fixing those?

@danchenko-dmitry
Copy link
Contributor Author

@danchenko-dmitry thanks for your PR! It looks like the tests and the linter are failing. Could you look into fixing those?

Done. Thanks!

@@ -155,7 +155,7 @@ func (p *plugin) ParseReportData(ctx trivyoperator.PluginContext, imageRef strin

imageDigest := p.getImageDigest(reports)

registry, artifact, err := p.parseImageRef(imageRef, imageDigest)
registry, artifact, err := ParseImageRef(imageRef, imageDigest)
Copy link
Contributor

Choose a reason for hiding this comment

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

why do we need this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My point is:

  1. We don't need this function as a method. It doesn't use private or public variables.
  2. Making it a standalone function simplifies testing (we don't need to initialize the object plugin ...)

Comment on lines 7722 to 7734
name: "7. short repo with private repo with tag",
imageRef: "my-private-repo.company.com/my-app:1.2.3",
imageID: "sha256:2bc57c6bcb194869d18676e003dfed47b87d257fce49667557fb8eb1f324d5d6",
registry: v1alpha1.Registry{
Server: "my-private-repo.company.com",
},
artifact: v1alpha1.Artifact{
Repository: "my-app",
Digest: "sha256:2bc57c6bcb194869d18676e003dfed47b87d257fce49667557fb8eb1f324d5d6",
Tag: "1.2.3",
},
err: nil,
},
Copy link
Contributor

Choose a reason for hiding this comment

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

what are the diifs between "2. with tag"?
is there a specific case for private repositories in ParseImageRef?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agree. I thought that more samples to test in different situations make it more covered by tests.
But your point also has meaning.
Less code - less support. If some case will be needed in the future it is easy to add it.
I will remove duplicates.

Comment on lines +244 to +247
server := ""
repository := ""
digest := ""
tag := ""
Copy link
Contributor

Choose a reason for hiding this comment

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

do we really need these variables?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, these variables "collect" values from two sources: containerimage.NewTag and containerimage.NewDigest.

In cases "server" and "repository" we don't care what source will used when both are available. (because they are equal)

"digest" and "tag" fills if it available.

The whole structure of code was made to simplify flow and remove sophisticated conditions.

I think using these variables (as one place collects data) will be simpler than other any cases.

Comment on lines +230 to +237
_tag, _err := containerimage.NewTag(refParts[0], containerimage.WeakValidation)
if _err == nil {
pTag = &_tag
}
artifact := v1alpha1.Artifact{
Repository: ref.Context().RepositoryStr(),

_digest, _err := containerimage.NewDigest(imageRef, containerimage.WeakValidation)
if _err == nil {
pDigest = &_digest
Copy link
Contributor

Choose a reason for hiding this comment

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

it looks like rewriting containerimage.ParseReference(imageRef)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, thats right!
It was an aim ... Using ParseReference will cause second call with other arguments.
I've decided to rewrite ParseReference and "customize" it logic & lay code on library then lay on own custom code.

Copy link
Contributor

@afdesk afdesk Feb 4, 2025

Choose a reason for hiding this comment

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

artifact.Tag = strings.TrimPrefix(strings.TrimSuffix(strings.TrimPrefix(imageRef, ref.Context().Name()), "@"+artifactDigest), ":")

doesn't this code work correctly?

Copy link
Contributor

Choose a reason for hiding this comment

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

I mean if you keep your test and add this one-line code for digest, will the tests pass?

case containerimage.Digest:
artifact.Digest = t.DigestStr()

Copy link
Contributor Author

Choose a reason for hiding this comment

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

artifact.Tag = strings.TrimPrefix(strings.TrimSuffix(strings.TrimPrefix(imageRef, ref.Context().Name()), "@"+artifactDigest), ":")

doesn't this code work correctly?

This code works correctly. I've checked it on another PR #2418
So we have two opportunities.

@afdesk
Copy link
Contributor

afdesk commented Feb 4, 2025

@danchenko-dmitry thanks for your work!

I left some comments.
the main opinions are next:

  1. can we simplify changes into smaller, more manageable updates?
  2. Some tests appear to be redundant. Could we review and remove any that don't add significant value?

Let me know what you think!

@afdesk afdesk requested a review from simar7 February 4, 2025 10:09
@danchenko-dmitry
Copy link
Contributor Author

danchenko-dmitry commented Feb 4, 2025

I left some comments. the main opinions are next:

  1. can we simplify changes into smaller, more manageable updates?

Totally agree. The previous version of the function wasn't simple and clear. Rewriting was simpler than smooth evolution ...
I know - it is not the best practice for collaboration... But in these particular case, I've decided to perform it quicker.

  1. Some tests appear to be redundant. Could we review and remove any that don't add significant value?

Yes, I will remove redundant tests. You are right that less code is easiest to maintain.

Let me know what you think!

Thanks for your support! I motivated to do code better.

@afdesk
Copy link
Contributor

afdesk commented Feb 5, 2025

in favor #2418

@afdesk afdesk closed this Feb 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Empty tag in all reports when deployed with digester
5 participants