Conversation
90b7949 to
fb4ee42
Compare
fb4ee42 to
cdae8b1
Compare
| defer pathLock(path)() | ||
|
|
There was a problem hiding this comment.
I was a bit intrigued by the mergeRecords() (which, actually doesn't merge, but append), followed by os.WriteFile steps;
Add()obtains a lock for the given path- then calls
mergeRecordswhich reads the file, and appends the new records to the content - Closes the file and returns the new content
- Then
Adddoes aos.WriteFileto ... the same file
From the above; given that we're appending, we wouldn't even need to read the file, and we could just construct the "to be added" content, and .. write to the file?
// Add adds an arbitrary number of Records to an already existing /etc/hosts file
func Add(path string, recs []Record) error {
if len(recs) == 0 {
return nil
}
defer pathLock(path)()
content := bytes.NewBuffer(nil)
for _, r := range recs {
if _, err := r.WriteTo(content); err != nil {
return err
}
}
f, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, 0o644)
if err != nil {
return err
}
_, err = f.Write(content.Bytes())
_ = f.Close()
return err
}
libnetwork/sandbox_dns_unix.go
Outdated
|
|
||
| extraContent := make([]etchosts.Record, 0, len(sb.config.extraHosts)) | ||
| extraContent := make([]etchosts.Record, 0, len(sb.config.extraHosts)+len(ifaceIPs)) | ||
| for _, extraHost := range sb.config.extraHosts { |
There was a problem hiding this comment.
Not new, but I noticed while looking at this code; the extraHost is shadowing the extraHost type defined in this package; perhaps rename it to host (can be separate commit)
edit: looks like the second commit is touching this loop, so might as well change it as part of that one 👍
libnetwork/sandbox_dns_unix.go
Outdated
| extraContent = append(extraContent, sb.makeHostsRecs(ifaceIPs)...) | ||
|
|
||
| // Assume IPv6 support, unless it's definitely disabled. | ||
| buildf := etchosts.Build |
There was a problem hiding this comment.
Also not new, but wondering why we used the buildF indirect; this could probably be written as;
// Assume IPv6 support, unless it's definitely disabled.
if en, ok := sb.IPv6Enabled(); ok && !en {
return etchosts.BuildNoIPv6(sb.config.hostsPath, extraContent)
}
return etchosts.Build(sb.config.hostsPath, extraContent)☝️ was also curious (because it mentions "definitely disabled"), should it also skip if !ok, or only if !en ?
There was a problem hiding this comment.
☝️ was also curious (because it mentions "definitely disabled"), should it also skip if !ok, or only if !en ?
If !ok, maybe there is IPv6 in the container, but it can't be sure. So, it includes the IPv6 records by calling Build instead of BuildNoIPv6 ... I think it's alright.
|
I think I just spotted a bug in our logic (unrelated to this PR) here; moby/libnetwork/sandbox_dns_unix.go Lines 128 to 135 in 4f4e34f In the above, we copy the hosts's moby/libnetwork/sandbox_dns_unix.go Lines 147 to 149 in 4f4e34f ☝️ I think we need to always do the i.e., something like; if sb.config.useDefaultSandBox {
// We are working under the assumption that the origin file option had been properly expressed by the upper layer
// if not here we are going to error out
if err := copyFile(sb.config.originHostsPath, sb.config.hostsPath); err != nil && !os.IsNotExist(err) {
return types.InternalErrorf("could not copy source hosts file %s to %s: %v", sb.config.originHostsPath, sb.config.hostsPath, err)
}
if len(sb.config.extraHosts) == 0 {
// nothing to add; we're done.
return nil
}
} |
I'm not convinced that's an unintentional bug. This was introduced in: This PR doesn't justify why this condition was tighten, but it references this issue: Which has no mentions of
Currently the docs says (see here):
Now let's imagine the following situation:
With your proposal, the container would end up with two entries, one for each IP address. I'm afraid that if we implement what you're suggesting, we're going to break someone, somewhere. That's way to late, but I think the correct UX would have been to disallow EDIT: I think we should add a proper comment stating why it's done that way. I always find this condition confusing and need a bit of time to find out a good reason to keep it that way. |
Signed-off-by: Rob Murray <[email protected]>
cdae8b1 to
5e5cd8c
Compare
|
Thank you @thaJeztah ... I cherry-picked your commits to this branch (wasn't quite sure what github would do if I merged your PR) - they all look good, I didn't see any reason to squash or modify anything. While we're in the area, it's tempting to deal with this FIXME, but there's no need to mix a functional change with the refactoring in this PR so I'll try to look at it separately ... moby/libnetwork/etchosts/etchosts.go Lines 132 to 135 in eed5779 |
Yes, that was my other thinking as well; when running with Currently we're doing something in between and we either use
At least 💯 on that. I also think we should still consider the "produce an error" idea; ISTR we did something for that when trying to use |
Merging works as well (but you'd get a "merge" commit in your branch, so usually a "rebase" after to get rid of those). It's pretty neat actually, as it's an easy way to bring in suggestions. |
|
Perhaps (but not a "strong" blocker sqash the "rename var that shadowed type" commit with your second commit; that would make git-blame slightly easier to find back the actually relevant changes (instead of seeing "rename var") |
Also, libnetwork: Sandbox.buildHostsFile: rename var that shadowed type Co-authored-by: Sebastiaan van Stijn <[email protected]> Signed-off-by: Rob Murray <[email protected]>
This regex is constructed using user-input, which could technically produce an invalid regex. Given that we have an error-return to our availability, let's return any error we get, instead of panicking. Signed-off-by: Sebastiaan van Stijn <[email protected]>
The `mergeRecords` function wasn't actually _merging_ anything, but only appended records to the existing `/etc/hosts` content. However, doing so was split across two functions; `Add` and `mergeRecords()`; - `Add()` obtains a lock for the given path - then calls `mergeRecords` which reads the file-content and appends the new records to the content. - Closes the file and returns the new content - Then `Add` does a `os.WriteFile` to ... the same file Given that we're appending, we won't have to read the file's content, and we can append to the file itself. Signed-off-by: Sebastiaan van Stijn <[email protected]>
We already have the filehandle open, so we could just truncate, and overwrite the content. Signed-off-by: Sebastiaan van Stijn <[email protected]>
Call the respective (`etchosts.BuildNoIPv6` or `etchosts.Build`) functions directly instead of using the intermediate `buildf` variable. Signed-off-by: Sebastiaan van Stijn <[email protected]>
5e5cd8c to
7c1e41a
Compare
Done. |
Ah, thank you - it was the merge commit I wanted to avoid. Will do that next time. |
Signed-off-by: Rob Murray <[email protected]>
I've been around that loop before too - so, added a comment pointing at @akerouanton's analysis above. |
| func (sb *Sandbox) addHostsEntries(_ context.Context, ifaceIP []netip.Addr) error { | ||
| return nil |
There was a problem hiding this comment.
Still curious if this cannot be implemented on Windows, or if we just never did.
- What I did
Follow up on:
- How I did it
Don't update /etc/hosts separately for each initial network
Collect endpoint addresses, then add them to the
/etc/hostsfile in a single updateUse netip.Addr instead of string when building /etc/hosts
Use
netip.Addrinstead ofstringfor/etc/hostsgenerationAnd (from @thaJeztah) - libnetwork: Sandbox.buildHostsFile: rename var that shadowed type
libnetwork/etchosts: don't panic on invalid regex
This regex is constructed using user-input, which could technically
produce an invalid regex.
Given that we have an error-return to our availability, let's return
any error we get, instead of panicking.
libnetwork/etchosts: Add: combine with "mergeRecords()"
The
mergeRecordsfunction wasn't actually merging anything, but onlyappended records to the existing
/etc/hostscontent. However, doing sowas split across two functions;
AddandmergeRecords();Add()obtains a lock for the given pathmergeRecordswhich reads the file-content and appends thenew records to the content.
Adddoes aos.WriteFileto ... the same fileGiven that we're appending, we won't have to read the file's content, and
we can append to the file itself.
libnetwork/etchosts: Delete: truncate file instead of close and write
We already have the filehandle open, so we could just truncate, and
overwrite the content.
libnetwork: Sandbox.buildHostsFile: remove intermediate var
Call the respective (
etchosts.BuildNoIPv6oretchosts.Build) functionsdirectly instead of using the intermediate
buildfvariable.Add a comment explaining host-networking hosts file generation
- How to verify it
Existing tests.
- Description for the changelog