-
Notifications
You must be signed in to change notification settings - Fork 72
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
feat: Prefer local image #381
feat: Prefer local image #381
Conversation
@pmengelbert can we add an integration test that validates this? |
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #381 +/- ##
==========================================
- Coverage 33.02% 32.59% -0.44%
==========================================
Files 17 17
Lines 1626 1617 -9
==========================================
- Hits 537 527 -10
+ Misses 1060 1058 -2
- Partials 29 32 +3 ☔ View full report in Codecov by Sentry. |
f8e79dc
to
1e0e435
Compare
pkg/pkgmgr/dpkg.go
Outdated
probed := mkFolders.Run(llb.Shlex(probeCmd)).Root() | ||
probed := mkFolders. | ||
Run(llb.Args([]string{ | ||
`/bin/busybox`, `env`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can get rid of env
and use llb.AddEnv
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
pkg/pkgmgr/dpkg.go
Outdated
outState := llb.Diff(busyBoxApplied, probed) | ||
if err := buildkit.SolveToLocal(ctx, dm.config.Client, &outState, dm.workingFolder); err != nil { | ||
typeBytes, err := buildkit.ExtractFileFromState(ctx, dm.config.Client, &outState, filepath.Join(resultsPath, statusdOutputFilename)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This diff can be removed and instead do
Run(
// run args
).
AddMount(resultsPath, llb.Scratch())
The return value of AddMount
is the content of the mounted directory after the command has run.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure why this is, but changing to using .AddMount
results in the buildkit.WithArrayFile
calls not working. Those files just aren't in the container when the command is run. Any ideas why that might be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(this only applies to the corresponding spot in rpm.go
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that its the contents of the mount only.
So if some file foo
that gets written to resultsPath/foo
, it will be in /foo
for the result of .AddMount
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The issue I was having was because the files I was using in llb.MkFile
were in the resultsPath
directory. The Mount was clobbering that directory. I'm not entirely clear on the order of operation here, but it seems like adding AddMount
at the end.
I worked around the issue by instead using a separate inputPath
for the call to llb.MkFile
. However, I'm not clear on the order of operations here, or on the syntax. Is the syntax AddMount(dst, src)
, returning src post-modification? In this case, "mount the (empty) filesystem from a scratch container into the resultsPath
directory, and return that scratch container after it has been modified by the run
command"? If that's what's happening, then it's clear why the directory was being clobbered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is the result of changing what is at the mount point.
If files are being written to that location first then yes they are being bind-mounted over with llb.Scratch
.
Instead you can write the files to a different state (resultsBase:= llb.Scratch().File(llb.Mkfile(...))
, then use resultsBase
in the AddMount
instead of llb.Scratch
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did this not get pushed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did this not get pushed?
Fixed
pkg/pkgmgr/rpm.go
Outdated
probed = buildkit.WithArrayFile(&probed, dbListPath, rpmDBList) | ||
probed = probed.Run(llb.Args([]string{ | ||
`/usr/sbin/busybox`, `env`, | ||
buildkit.Env("TOOL_LIST_PATH", toolListPath), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment about env
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, the reason I did it this way was that llb.AddEnv
will result in env vars that are persisted into the image & included in the container at runtime -- is that correct?
In any case, it doesn't matter because these containers are discarded, so I'll switch to llb.AddEnv
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It all depends on what you are returning.
Each state modification leaves the last state alone.
You can also add it to just the run step.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can also add it to just the run step.
Ah, I missed that that was an option. That's what I was looking for!
pkg/pkgmgr/rpm.go
Outdated
probed := buildkit.WithArrayFile(&mkFolders, toolListPath, toolList) | ||
probed = buildkit.WithArrayFile(&probed, dbListPath, rpmDBList) | ||
probed = probed.Run(llb.Args([]string{ | ||
`/usr/sbin/busybox`, `env`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also not sure I understand what is going on with the busybox exec here.
Should just be able to execute sh
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One would hope, but in practice busybox env
just refused to execute sh
. But since we are removing the env
above, this will not be a problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
f95b8c4
to
f706029
Compare
pkg/pkgmgr/rpm.go
Outdated
outState := llb.Diff(toolsApplied, probed) | ||
if err := buildkit.SolveToLocal(ctx, rm.config.Client, &outState, rm.workingFolder); err != nil { | ||
return err | ||
// probed := mkFolders.Run(llb.Shlex(probeToolsCmd)).Run(llb.Shlex(probeDBCmd)).Root() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need to remove this line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
}) | ||
} | ||
|
||
func ArrayFile(input []string) []byte { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be easy to add a unit test for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Unit Test
how do we want to handle the do we expect all images to have a prefix? or will this PR address non-prefixed images? |
this seems to skip showing the commands being run, is that intentional? previously:
with this PR:
|
I'll look into this |
This is coming from
|
This is fixed now. |
8290bfd
to
dca0f9b
Compare
This is fixed by the (currently) most recent commit: Line 256 in dca0f9b
|
ffacf6d
to
c43fa52
Compare
Integration and unit tests are done |
@pmengelbert looks like e2e is failing with |
The gateway client has options which allow for fetching the image config locally before attempting to find it remotely. However, this commit is broken, since the `buildkit.Config` object now has a reference to a gateway client; however, `buildkit.SolveToLocal` requires a normal buildkit client. The following commit will replace `buildkit.SolveToLocal` with `buildkit.ExtractFileFromState`. Implement `buildkit.ExtractFileFromState` This code will still not compile, since the signature of `buildkit.SolveToLocal` is not satisfied by its calls. Replace `SolveToLocal` in `probeDPKGStatus` method In this case, we will write the status type to a file, which we thereafter read from the state as a single byte. Fix error in awk script There was a confusion in the awk script between bash arrays and awk arrays. You cannot pass in an awk array via the command line (see https://stackoverflow.com/a/33106291). The strings will be split by space to produce the array, so the parentheses are unnecessary here. Use `ExtractFileFromState` for dpkg `installUpdates` Read the bytes and return them, instead of writing them to the local filesystem. Use `ExtractFileFromState` in `unpackAndMergeUpdates` In dpkg.go APK: Use `ExtractFileFromState` for `upgradePackages` Do not use `SolveToLocal`. Use `ExtractFileFromState` for `probeRPMStatus` Replace `buildkit.SolveToLocal` in rpm.go In all places Update `patchWithContext` to pass the correct client Fix errors and achieve parity with `main` branch This commit passes the integration tests as well as the `main` branch does. Update unit tests Signed-off-by: Peter Engelbert <[email protected]>
In the Test Patch `docker/custom-unix` test, Docker is run in a `DIND` container, in order to be absolutely sure that docker > 24.0.0 is used. This is because the containerd snapshotter is required for copa (which requires docker > 22), and the package repo available to the github runner does not have docker 24 available. When running tests relevant to this PR, we need to pull/retag an image into the docker instance we are testing. In this case, that is the docker instance in the `DIND` container. Accordingly, when performing the pull and tag operations, we need to propagate the location of the custom docker address and include that in the `docker` cli invocation. This should fix the `docker/custom-unix` test in the CI. Another change is required to fix the other errors. Signed-off-by: Peter Engelbert <[email protected]>
acfe7eb
to
b3e92df
Compare
Signed-off-by: Peter Engelbert <[email protected]>
Signed-off-by: Peter Engelbert <[email protected]>
Signed-off-by: Peter Engelbert <[email protected]>
Only the buildkit instance running within the docker daemon can work with locally-built or locally-tagged images. As a result, skip tests for local-only images when the daemon in question is not docker itself. i.e., don't test local images in buildx or with stock buildkit. Signed-off-by: Peter Engelbert <[email protected]>
Signed-off-by: Peter Engelbert <[email protected]>
8cebf36
to
5c3c249
Compare
This is necessary, because `copa` invokes `docker` directly to export the patched image. Signed-off-by: Peter Engelbert <[email protected]>
5c3c249
to
e7c9904
Compare
integration/patch_test.go
Outdated
@@ -44,14 +48,33 @@ func TestPatch(t *testing.T) { | |||
|
|||
for _, img := range images { | |||
img := img | |||
|
|||
// Only the buildkit instance running within the docker daemon can work |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds like this only works with docker with containerd snapshotter, is that right? can we add this to docs please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Add to docs that copa only works with standard docker if using the containerd snapshotter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
This is the proper way to do this. Signed-off-by: Peter Engelbert <[email protected]>
Signed-off-by: Peter Engelbert <[email protected]>
website/docs/quick-start.md
Outdated
> **NOTE:** if you're scanning and patching an image that is local-only | ||
> (i.e. built or tagged locally but not pushed to a registry), you are | ||
> limited to using `docker`'s built-in buildkit service. See | ||
> [Prerequisites][#prerequisites] for more information. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
> **NOTE:** if you're scanning and patching an image that is local-only | |
> (i.e. built or tagged locally but not pushed to a registry), you are | |
> limited to using `docker`'s built-in buildkit service. See | |
> [Prerequisites][#prerequisites] for more information. | |
> [!NOTE] | |
> if you're scanning and patching an image that is local-only (i.e. built or tagged locally but not pushed to a registry), `copa` is limited to using `docker`'s built-in buildkit service, and must use [`containerd image store`](https://docs.docker.com/storage/containerd/) feature due to <reason>. See [Prerequisites][#prerequisites] for more information. |
please add the <reason>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pmengelbert sorry, i edited my comment while you were addressing this, let's make sure to add the reason
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, thanks.
Co-authored-by: Sertaç Özercan <[email protected]> Signed-off-by: Peter Engelbert <[email protected]>
Co-authored-by: Sertaç Özercan <[email protected]> Signed-off-by: Peter Engelbert <[email protected]>
Co-authored-by: Sertaç Özercan <[email protected]> Signed-off-by: Peter Engelbert <[email protected]>
Signed-off-by: Peter Engelbert <[email protected]>
See diff for more info. Signed-off-by: Peter Engelbert <[email protected]>
Use gateway client for config resolution
Implement
buildkit.ExtractFileFromState
This code will still not compile, since the signature of
buildkit.SolveToLocal
is not satisfied by its calls.Replace
SolveToLocal
inprobeDPKGStatus
methodIn this case, we will write the status type to a file, which we thereafter read from the state as a single byte.
Fix error in awk script
Use
ExtractFileFromState
for dpkginstallUpdates
Use
ExtractFileFromState
inunpackAndMergeUpdates
APK: Use
ExtractFileFromState
forupgradePackages
Do not use
SolveToLocal
.Use
ExtractFileFromState
forprobeRPMStatus
Replace
buildkit.SolveToLocal
in rpm.goUpdate
patchWithContext
to pass the correct clientFix errors and achieve parity with
main
branchUpdate unit tests
Closes #177