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

Allow config authors to always use Prefix #1368

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

lsm5
Copy link
Member

@lsm5 lsm5 commented Sep 1, 2021

Previously an unset Location was only allowed for wildcarded Prefixes.
This commit will allow any valid Prefix.

Fixes: #1191 (comment)

Signed-off-by: Lokesh Mandvekar [email protected]

@vrothberg @mtrmac @ashcrow PTAL

Copy link
Member

@vrothberg vrothberg left a comment

Choose a reason for hiding this comment

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

Needs tests and changes to docs. AFAIR the docs state the location must be set, and we need to explain how rewriting works when location is empty.

The tests should make sure that rewriting the reference will return the input.

@lsm5
Copy link
Member Author

lsm5 commented Sep 1, 2021

Done. PTAL.

@TomSweeneyRedHat
Copy link
Member

LGTM

@lsm5
Copy link
Member Author

lsm5 commented Sep 1, 2021

@mtrmac removing the entire check for empty location from rewriteReference seemed to cause failures in TestRewriteReferenceFailedDuringParseNamed . So, let me know if the FIXME comment still needs to exist there.

Copy link
Member

@vrothberg vrothberg left a comment

Choose a reason for hiding this comment

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

I'd love a test with at least one registries.conf file with an empty location and set prefix.

@@ -82,7 +82,7 @@ location = "internal-registry-for-example.net/bar"
requests for the image `example.com/foo/myimage:latest` will actually work with the
`internal-registry-for-example.net/bar/myimage:latest` image.

With a `prefix` containing a wildcard in the format: "*.example.com" for subdomain matching,
With any valid `prefix` with or without a wildcard in the format: "*.example.com" for subdomain matching,
the location can be empty. In such a case,
Copy link
Member

Choose a reason for hiding this comment

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

This sentence seems a bit too complicated. I suggest: "The location can be empty if the prefix is set."

}
reg.Prefix = reg.Location
} else {
// Allow config authors to always use Prefix.
Copy link
Member

Choose a reason for hiding this comment

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

I don't find the comment helpful. I'd prefer a comment stating that either prefix OR location OR both must be set.

@rhatdan
Copy link
Member

rhatdan commented Sep 16, 2021

@lsm5 any update on this PR?

@lsm5
Copy link
Member Author

lsm5 commented Sep 16, 2021

@rhatdan working on it..

@lsm5 lsm5 force-pushed the wildcard-cert-fixes-2 branch 2 times, most recently from 38823ca to 48ddd0e Compare September 20, 2021 14:39
@lsm5
Copy link
Member Author

lsm5 commented Sep 22, 2021

@mtrmac @vrothberg PTAL

Copy link
Member

@vrothberg vrothberg left a comment

Choose a reason for hiding this comment

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

LGTM
@mtrmac PTAL

@lsm5
Copy link
Member Author

lsm5 commented Sep 27, 2021

@mtrmac ping PTAL

@vrothberg
Copy link
Member

@mtrmac ping PTAL

On PTO until next week.

Previously an unset Location was only allowed for wildcarded Prefixes.
This commit will allow configs with emtpy location or empty prefix, so
long as the other is valid.

Remove wildcard prefix check for empty location in rewriteReference.

Fixes:
1. containers#1191 (comment)
2. containers#1191 (comment)

Co-authored-by: Miloslav Trmač <[email protected]>
Signed-off-by: Lokesh Mandvekar <[email protected]>
@lsm5
Copy link
Member Author

lsm5 commented Oct 5, 2021

@mtrmac PTAL

Copy link
Collaborator

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

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

Thanks for the PR, and I apologize for the late review.

ACK overall; a few more simplifications seem possible.

@@ -82,8 +82,7 @@ location = "internal-registry-for-example.net/bar"
requests for the image `example.com/foo/myimage:latest` will actually work with the
`internal-registry-for-example.net/bar/myimage:latest` image.

With a `prefix` containing a wildcard in the format: "*.example.com" for subdomain matching,
the location can be empty. In such a case,
With any valid `prefix`, the location can be emtpy. In such a case,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
With any valid `prefix`, the location can be emtpy. In such a case,
With any valid `prefix`, the location can be empty. In such a case,

but we don’t exactly mean “empty”, we mean “missing” / “not provided by the user”; that this shows up as "" is just an implementation detail of our Go implementation (our lazy Go implementation, it would probably be possible to accurate… and reject "" values).

Comment on lines +85 to 86
With any valid `prefix`, the location can be emtpy. In such a case,
prefix matching will occur, but no reference rewrite will occur. The
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ultimately, the “Choosing a [[registry]] TOML table” already describes the matching semantics, and that’s where it should be documented.

This is a paragraph about the location field, in a “Remapping and mirroring registries” section; maybe all this needs to say is something like “if only one of prefix and location is provided, the original requested image reference will be used as-is without redirection”.

@@ -82,8 +82,7 @@ location = "internal-registry-for-example.net/bar"
requests for the image `example.com/foo/myimage:latest` will actually work with the
`internal-registry-for-example.net/bar/myimage:latest` image.

With a `prefix` containing a wildcard in the format: "*.example.com" for subdomain matching,
the location can be empty. In such a case,
With any valid `prefix`, the location can be emtpy. In such a case,
prefix matching will occur, but no reference rewrite will occur. The
original requested image string will be used as-is. But other settings like
`insecure` / `blocked` / `mirrors` will be applied to matching images.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I’m not sure we even need the example for doing nothing; we almost certainly don’t need two.

Also the “But other settings like” sentence is duplicated above and below the example, probably unnecessarily.

@@ -82,8 +82,7 @@ location = "internal-registry-for-example.net/bar"
requests for the image `example.com/foo/myimage:latest` will actually work with the
Copy link
Collaborator

Choose a reason for hiding this comment

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

Above, in

By default, this equal to prefix (in which case prefix can be omitted …

the parenthesized aside doesn’t make sense, if location is unset, prefix can’t be omitted.

Basically I think we should document it this way:

  • prefix is how the right section is chosen. (It is ~assumed to be always set.)
  • location is how we redirect; if unset, no redirection happens.
  • As a special case, (prefix unset + location set) is interpreted the same as (prefix set + location unset)

We already document the special case in the “Choosing a [[registry]] TOML table” section, so maybe we can just not discuss it here at all.

}
reg.Location = reg.Prefix
} else {
return &InvalidRegistries{s: "invalid condition: both location and prefix are unset"}
Copy link
Collaborator

Choose a reason for hiding this comment

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

(Absolutely non-blocking, this is pre-existing and has more instances, i.e. basically a note to self to improve this later: invalid condition is not very helpful in a user-facing message.)

} else {
// Prefix and Location cannot both be empty.
// Either one at least must be set.
if reg.Prefix != "" {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This could be simpler as

if reg.Prefix == "" && reg.Location == "" { fail }
if reg.Location != "" { reg.Location, err = parseLocation(…); if err … }
if reg.Prefix == "" { reg.Prefix = reg.Location }
else { reg.Prefix, err = parseLocation(…); if err … } 

or perhaps

// Validate individual fields
if reg.Location != "" { reg.Location, err = parseLocation(…); if err … }
if reg.Prefix != "" { reg.Prefix, err = parseLocation(…); if err … } 
// Validate the combination, normalize to have reg.Prefix always set
if reg.Prefix == "" {
    if reg.Location == "" { fail }
    else { reg.Prefix = reg.Location }
}

Either way, please remove the parseLocation call above this line, and make parseLocation fail on "" again.

Comment on lines +387 to +388
assert.Nil(t, err)
assert.NotNil(t, reg)
Copy link
Collaborator

Choose a reason for hiding this comment

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

(Non-blocking: These should be require.. OTOH this is consistent with the rest, and only matters on test failures.)

Copy link
Member Author

Choose a reason for hiding this comment

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

so would you prefer require be used for all other existing test cases too? Or only for the missing-location + set-prefix case?

I could make a separate PR if we need to change it throughout the file.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I honestly don’t think this is worth much worrying about; if you find updating pre-existing test cases fun, sure, go for it, but it’s not work that results in anything users could notice and consider valuable while using the software. As far as “clean code” goes, require is a bit more correct but consistency is also nice, so to me that’s not a strong reason to prefer either.

(Just to be explicit: require should be used for testing prerequisites that must be true for other checks to be even valid to do, e.g.

ptr, err := testSubject()
require.NoError(t, err)
assert.Equal(t, …, *ptr) // would crash if testSubject returned (nil, err) and the above were assert.NoError(…)

But there is a minimal practical difference; with assert.NoError(t, err) the test crashes with a backtrace, with require.NoError(t, err) the test fails with an error message containing err. It doesn’t matter at all if the test completely succeeds. If the test fails because err is set, in both cases the test fails, it’s easy enough to identify the location of the failure, and probably something about testSubject needs to be updated. require is only better in that it includes the actual error text in the test failure output, and that could help with a inconsistent rarely-occurring failure in CI.)

Copy link
Member Author

Choose a reason for hiding this comment

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

ack, that's really helpful thanks, I'll consider introducing that in a future PR, will make a note in the test file for now.

Copy link
Collaborator

Choose a reason for hiding this comment

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

But there is a minimal practical difference; with assert.NoError(t, err) the test crashes with a backtrace, with require.NoError(t, err) the test fails with an error message containing err.

I’m sorry, this is nonsense of course; assert.NoError(t, err) does report the unexpected error value first, it’s just the later use of *ptr that crashes. So really the difference between failures of the two implementations is basically cosmetic.

@mtrmac mtrmac added the kind/feature A request for, or a PR adding, new functionality label Dec 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/feature A request for, or a PR adding, new functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants