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

chunked: honor the ForceMask setting #1971

Merged
merged 4 commits into from
Jun 20, 2024

Conversation

giuseppe
Copy link
Member

make sure the ForceMask setting is honored for partial pulls. More details in each commit.

Copy link
Contributor

openshift-ci bot commented Jun 13, 2024

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: giuseppe

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@rhatdan
Copy link
Member

rhatdan commented Jun 15, 2024

LGTM

Copy link
Contributor

@cgwalters cgwalters left a comment

Choose a reason for hiding this comment

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

Looks sane to me, just one comment/question.

if r.Xattrs == nil {
r.Xattrs = make(map[string]string)
}
r.Xattrs[idtools.ContainersOverrideXattr] = base64.StdEncoding.EncodeToString([]byte(value))
Copy link
Contributor

Choose a reason for hiding this comment

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

It feels a bit unclean to mutate the input here; I'd trust you if you said it was safe, but still.

In ostree we have something very similar to the ContainersOverrideXattr in the "bare-user" mode vs "bare" and the code paths in the backend are pretty distinct. Doing something similar here would want instead for e.g. setFileAttrs to take an override parameter or so perhaps.

Copy link
Collaborator

Choose a reason for hiding this comment

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

This should be safe because mergedEntries is an array of values (i.e. copies), created from scratch for this function. … ugh, except that a hash is a reference type, so AFAICS this might be affecting the c.toc field.

Ultimately, that is still safe because c.toc is written at most once, and read exactly once; but the number of assumptions is getting a bit large.

Copy link
Contributor

Choose a reason for hiding this comment

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

In Rust:

  • xattrs would likely be an Option<T> instead of a pointer, so the compiler would have made us check for its presence
  • We likely would have been passing a &TableOfContents or so, and the compiler would have errored out on an attempt to mutate it
  • And if we chose to pass instead &mut TableOfContents the compiler would verify that there weren't other threads (goroutines) that were concurrently reading it, etc.
  • But we can often do something better than mutation for something like this; Rust has efficient iterators over collections, and in this case instead of mutation it'd likely be better to leave the input read-only and instead pass impl Iterator<Item=Xattr> to the function that sets xattrs (instead of an array). It's efficient to do e.g. toc.xattrs.iter().chain(Xattr::new(idtools.CONTAINER_OVERRIDE_XATTR, value)) (although this would blend borrowed and owned values so we may need a Cow or so)

Copy link
Collaborator

Choose a reason for hiding this comment

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

I’d sign up to be a platinum member of the Go haters club, but that’s not really under discussion in this PR. (If you wanted to make a case for rewriting the stack in Rust, I’d not oppose that at all.)


I do agree that this would be safer with a deep copy, but then … Go doesn’t have a language-native deep copy operation either. So it’s either risk of bugs due to overwriting data (if it ever turned from single use into multiple-use) or risk of bugs due to missing a field copy (if we ever added a field), and to me that feels like a wash, up to @giuseppe .

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.

The ForceMask parts LGTM.

pkg/idtools/idtools.go Outdated Show resolved Hide resolved
drivers/overlay/overlay.go Outdated Show resolved Hide resolved
}
if idMappings == nil {
idMappings = &idtools.IDMappings{}
idMappings = idtools.NewIDMappingsFromMaps(d.uidMaps, d.gidMaps)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Warning: I don’t understand the whole picture at all.

Shouldn’t this happen at a (much?) higher level? Looking at store.putLayer, it is done there — and canUseShifting is involved in the decision.

I have no idea which of the two is correct, to be clear.

Copy link
Member Author

@giuseppe giuseppe Jun 19, 2024

Choose a reason for hiding this comment

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

I never understood this part as well :-) I took the chance now to dig deeper into it...

I think we are carrying the feature from Docker (e5f58bf) where it was possible to configure a single uid/gid mapping for all the containers, so the mappings are configured only once for the driver.

In facts this is the setting we get when we configure remap-uids and remap-gids in the storage.conf file.

I'll drop this patch from the current PR and remove the remap-*ids logic completely in a different PR

Copy link
Member Author

Choose a reason for hiding this comment

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

opened a test PR to see how far the CI goes: #1976

Copy link
Collaborator

Choose a reason for hiding this comment

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

If I read the code correctly, the d.[ug]idMaps fields are never used when applying tarballs; and the generic code which triggers shifting or per-container remapping does not know about this option; that makes it really hard to see a use case.

Dealing with that in a separate PR LGTM.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
if options != nil {
idMappings = options.Mappings
forceMask = options.ForceMask
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should this be conditioned on options.ForceMask != nil?

(One point is that the semantics is not documented. Another is that this field is never set when called by c/image, anyway. And yet again, if it is not used, why is it a field of ApplyDiffWithDifferOpts at all…)


AFAICS ApplyDiffOpts.ForceMask is never set when creating non-staged/chunked layers, so maybe we can just remove the filed and simplify?

Copy link
Collaborator

Choose a reason for hiding this comment

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

(Running on macOS, apparently I can’t trust the IDE:) ApplyDiff does

	if d.options.forceMask != nil {
			options.ForceMask = d.options.forceMask
		}

the opposite of this logic… but, also, the field is not used on that path at all, either.

Removing ApplyDiffOpts.ForceMask looks increasingly attractive to me.

Copy link
Member Author

Choose a reason for hiding this comment

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

thanks for spotting it. I'd say the options should have a higher precedence, but I've adapted it to follow what ApplyDiff does.

Maybe something more to simplify along the lines of #1976

if r.Xattrs == nil {
r.Xattrs = make(map[string]string)
}
r.Xattrs[idtools.ContainersOverrideXattr] = base64.StdEncoding.EncodeToString([]byte(value))
Copy link
Collaborator

Choose a reason for hiding this comment

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

I’d sign up to be a platinum member of the Go haters club, but that’s not really under discussion in this PR. (If you wanted to make a case for rewriting the stack in Rust, I’d not oppose that at all.)


I do agree that this would be safer with a deep copy, but then … Go doesn’t have a language-native deep copy operation either. So it’s either risk of bugs due to overwriting data (if it ever turned from single use into multiple-use) or risk of bugs due to missing a field copy (if we ever added a field), and to me that feels like a wash, up to @giuseppe .

@cgwalters
Copy link
Contributor

I’d sign up to be a platinum member of the Go haters club, but that’s not really under discussion in this PR.

In general, everyone should feel free to not respond to my Rust comments...it's partially just cathartic 😄, but also partially about tracking pain points we see in practice.

(If you wanted to make a case for rewriting the stack in Rust, I’d not oppose that at all.)

Now this is totally tangential but I think as you know I've been digging into this repo and also just thinking about how to sanely intersect the ostree/container stuff (which is all in Rust today, although speaking to a C library for substantial parts) with composefs and that led to containers/composefs#286 which could grow into a composefs-native container storage backend...but...yeah, a lot involved there. Rewriting anything is a big risky lift, I don't think it's the right time. But...we could do something like add a /usr/libexec/composefs-container-storage in Rust to composefs that gets forked from c/storage (much like how the composefs C binaries are today) and speak to it via IPC or so. Dunno, anyways: obviously very tangential.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
and also fix a segfault when the xattr map is nil

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
@rhatdan
Copy link
Member

rhatdan commented Jun 20, 2024

LGTM

@rhatdan rhatdan merged commit 768258b into containers:main Jun 20, 2024
17 of 18 checks passed
Comment on lines +2165 to 2167
forceMask := options.ForceMask

if options != nil {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Either the first line can crash, or the second one is unnecessary.

Copy link
Member Author

Choose a reason for hiding this comment

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

thanks, opened a PR: #1984

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.

4 participants