From bf3f207a49bf2fd2126b85c36b013eed52cd891a Mon Sep 17 00:00:00 2001 From: Mario Loriedo Date: Wed, 24 Jul 2024 16:26:16 +0200 Subject: [PATCH] Convert additional build context paths on Windows Signed-off-by: Mario Loriedo --- build_windows.md | 6 +-- pkg/bindings/images/build.go | 20 ++++++++++ pkg/bindings/images/build_test.go | 43 ++++++++++++++++++++++ pkg/machine/e2e/README.md | 61 +++++++++++++++++++++++++------ pkg/machine/e2e/basic_test.go | 40 ++++++++++++++++++++ 5 files changed, 155 insertions(+), 15 deletions(-) diff --git a/build_windows.md b/build_windows.md index 10c4321f3d..4ee7b320c6 100644 --- a/build_windows.md +++ b/build_windows.md @@ -24,8 +24,8 @@ Windows. - [Create and start a podman machine](#create-and-start-a-podman-machine) - [Run a container using podman](#run-a-container-using-podman) - [Build and test the Podman Windows installer](#build-and-test-the-podman-windows-installer) - - [Build the installer](#build-the-installer) - - [Test the installer](#test-the-installer) + - [Build the Windows installer](#build-the-windows-installer) + - [Test the Windows installer](#test-the-windows-installer) - [Build and test the standalone `podman.msi` file](#build-and-test-the-standalone-podmanmsi-file) - [Verify the installation](#verify-the-installation) - [Uninstall and clean-up](#uninstall-and-clean-up) @@ -480,7 +480,7 @@ $foldersToCheck = @( "$env:USERPROFILE.config\containers\" "$env:USERPROFILE.local\share\containers\" "$ENV:LOCALAPPDATA\containers\" - "$ENV:APPDATA\containers\containers.conf.d\99-podman-machine-provider.conf" + "$ENV:PROGRAMDATA\containers\containers.conf.d\99-podman-machine-provider.conf" ) $foldersToCheck | ForEach-Object {Test-Path -Path $PSItem} ``` diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go index 58b3c25af0..93c4e2e29c 100644 --- a/pkg/bindings/images/build.go +++ b/pkg/bindings/images/build.go @@ -22,6 +22,7 @@ import ( "github.com/containers/podman/v5/pkg/auth" "github.com/containers/podman/v5/pkg/bindings" "github.com/containers/podman/v5/pkg/domain/entities/types" + "github.com/containers/podman/v5/pkg/specgen" "github.com/containers/podman/v5/pkg/util" "github.com/containers/storage/pkg/fileutils" "github.com/containers/storage/pkg/ioutils" @@ -49,6 +50,21 @@ type BuildResponse struct { Aux json.RawMessage `json:"aux,omitempty"` } +// Modify the build contexts that uses a local windows path. The windows path is +// converted into the corresping guest path in the default Windows machine +// (e.g. C:\test ==> /mnt/c/test). +func convertAdditionalBuildContexts(additionalBuildContexts map[string]*define.AdditionalBuildContext) { + for _, context := range additionalBuildContexts { + if !context.IsImage && !context.IsURL { + path, err := specgen.ConvertWinMountPath(context.Value) + // It's not worth failing if the path can't be converted + if err == nil { + context.Value = path + } + } + } +} + // Build creates an image using a containerfile reference func Build(ctx context.Context, containerFiles []string, options types.BuildOptions) (*types.BuildReport, error) { if options.CommonBuildOpts == nil { @@ -90,6 +106,10 @@ func Build(ctx context.Context, containerFiles []string, options types.BuildOpti params.Add("t", tag) } if additionalBuildContexts := options.AdditionalBuildContexts; len(additionalBuildContexts) > 0 { + // TODO: Additional build contexts should be packaged and sent as tar files + // For the time being we make our best to make them accessible on remote + // machines too (i.e. on macOS and Windows). + convertAdditionalBuildContexts(additionalBuildContexts) additionalBuildContextMap, err := jsoniter.Marshal(additionalBuildContexts) if err != nil { return nil, err diff --git a/pkg/bindings/images/build_test.go b/pkg/bindings/images/build_test.go index e4035d5f86..b895262777 100644 --- a/pkg/bindings/images/build_test.go +++ b/pkg/bindings/images/build_test.go @@ -3,6 +3,7 @@ package images import ( "testing" + "github.com/containers/buildah/define" "github.com/stretchr/testify/assert" ) @@ -15,3 +16,45 @@ func TestBuildMatchIID(t *testing.T) { func TestBuildNotMatchStatusMessage(t *testing.T) { assert.False(t, iidRegex.MatchString("Copying config a883dafc480d466ee04e0d6da986bd78eb1fdd2178d04693723da3a8f95d42f4")) } + +func TestConvertAdditionalBuildContexts(t *testing.T) { + additionalBuildContexts := map[string]*define.AdditionalBuildContext{ + "context1": { + IsURL: false, + IsImage: false, + Value: "C:\\test", + DownloadedCache: "", + }, + "context2": { + IsURL: false, + IsImage: false, + Value: "/test", + DownloadedCache: "", + }, + "context3": { + IsURL: true, + IsImage: false, + Value: "https://a.com/b.tar", + DownloadedCache: "", + }, + "context4": { + IsURL: false, + IsImage: true, + Value: "quay.io/a/b:c", + DownloadedCache: "", + }, + } + + convertAdditionalBuildContexts(additionalBuildContexts) + + expectedGuestValues := map[string]string{ + "context1": "/mnt/c/test", + "context2": "/test", + "context3": "https://a.com/b.tar", + "context4": "quay.io/a/b:c", + } + + for key, value := range additionalBuildContexts { + assert.Equal(t, expectedGuestValues[key], value.Value) + } +} diff --git a/pkg/machine/e2e/README.md b/pkg/machine/e2e/README.md index 93fcdf9ea6..ae6873f42d 100644 --- a/pkg/machine/e2e/README.md +++ b/pkg/machine/e2e/README.md @@ -1,49 +1,86 @@ # Running the machine tests -This document is a quick how-to run machine tests. Not all dependencies, like -`gvproxy` are documented. You must install `gvproxy` in all cases described below. +This document is a quick how-to run machine tests. Not all dependencies, like +`gvproxy` are documented. You must install `gvproxy` in all cases described +below. ## General notes ### Environment must be clean -You must not have any machines defined before running tests. Consider running `podman machine reset` prior to running tests. + +You must not have any machines defined before running tests. Consider running +`podman machine reset` prior to running tests. + +### ### Scoping tests -You can scope tests in the machine suite by adding various incantations of `FOCUS=`. For example, add `FOCUS_FILE=basic_test.go` to only run basic test. Or add `FOCUS="simple init with start"` to only run one test case. For windows, the syntax differs slightly. In windows, executing something like following achieves the same result: + +You can scope tests in the machine suite by adding various incantations of +`FOCUS=`. For example, add `FOCUS_FILE=basic_test.go` to only run basic test. Or +add `FOCUS="simple init with start"` to only run one test case. For windows, the +syntax differs slightly. In windows, executing something like following achieves +the same result: `./winmake localmachine "basic_test.go start_test.go"` +To focus on one specific test on windows, run `ginkgo` manually: + +```pwsh +$remotetags = "remote exclude_graphdriver_btrfs btrfs_noversion exclude_graphdriver_devicemapper containers_image_openpgp" +$focus_file = "basic_test.go" +$focus_test = "podman build contexts" +./test/tools/build/ginkgo.exe ` + -v --tags "$remotetags" -timeout=90m --trace --no-color ` + --focus-file $focus_file ` + --focus "$focus_test" ` + ./pkg/machine/e2e/. +``` + +Note that ginkgo.exe is built when running the command +`winmake.ps1 localmachine` so make sure to run it before trying the command +above. + ## Linux ### QEMU -1. `make localmachine` +1. `make localmachine` ## Microsoft Windows ### Hyper-V + 1. Open a powershell as admin +1. `.\winmake.ps1 podman-remote && .\winmake.ps1 win-gvproxy` +1. `$env:CONTAINERS_HELPER_BINARY_DIR="$pwd\bin\windows"` 1. `$env:CONTAINERS_MACHINE_PROVIDER="hyperv"` -1. `./winmake localmachine` - +1. `.\winmake localmachine` ### WSL + 1. Open a powershell as a regular user -1. Build and copy win-sshproxy into bin/ -1. `./winmake localmachine` +1. `.\winmake.ps1 podman-remote && .\winmake.ps1 win-gvproxy` +1. `$env:CONTAINERS_HELPER_BINARY_DIR="$pwd\bin\windows"` +1. `$env:CONTAINERS_MACHINE_PROVIDER="wsl"` +1. `.\winmake localmachine` ## MacOS -Macs now support two different machine providers: `applehv` and `libkrun`. The `applehv` provider is the default. -Note: On macOS, an error will occur if the path length of `$TMPDIR` is longer than 22 characters. Please set the appropriate path to `$TMPDIR`. Also, if `$TMPDIR` is empty, `/private/tmp` will be set. +Macs now support two different machine providers: `applehv` and `libkrun`. The +`applehv` provider is the default. + +Note: On macOS, an error will occur if the path length of `$TMPDIR` is longer +than 22 characters. Please set the appropriate path to `$TMPDIR`. Also, if +`$TMPDIR` is empty, `/private/tmp` will be set. ### Apple Hypervisor + 1. `brew install vfkit` 1. `make podman-remote` 1. `make localmachine` - ### [Libkrun](https://github.com/containers/libkrun) + 1. `brew install krunkit` 1. `make podman-remote` 1. `export CONTAINERS_MACHINE_PROVIDER="libkrun"` diff --git a/pkg/machine/e2e/basic_test.go b/pkg/machine/e2e/basic_test.go index daed59828f..2ff04a5444 100644 --- a/pkg/machine/e2e/basic_test.go +++ b/pkg/machine/e2e/basic_test.go @@ -207,6 +207,46 @@ var _ = Describe("run basic podman commands", func() { Expect(ls).To(Exit(0)) Expect(ls.outputToString()).To(ContainSubstring(testString)) }) + + It("podman build contexts", func() { + skipIfVmtype(define.HyperVVirt, "FIXME: #23429 - Error running podman build with option --build-context on Hyper-V") + skipIfVmtype(define.QemuVirt, "FIXME: #23433 - Additional build contexts should be sent as additional tar files") + name := randomString() + i := new(initMachine) + session, err := mb.setName(name).setCmd(i.withImage(mb.imagePath).withNow()).run() + Expect(err).ToNot(HaveOccurred()) + Expect(session).To(Exit(0)) + + mainContextDir := GinkgoT().TempDir() + cfile := filepath.Join(mainContextDir, "test1") + err = os.WriteFile(cfile, []byte(name), 0o644) + Expect(err).ToNot(HaveOccurred()) + + additionalContextDir := GinkgoT().TempDir() + cfile = filepath.Join(additionalContextDir, "test2") + err = os.WriteFile(cfile, []byte(name), 0o644) + Expect(err).ToNot(HaveOccurred()) + + cfile = filepath.Join(mainContextDir, "Containerfile") + err = os.WriteFile(cfile, []byte("FROM quay.io/libpod/alpine_nginx\nCOPY test1 /\nCOPY --from=test-context test2 /\n"), 0o644) + Expect(err).ToNot(HaveOccurred()) + + bm := basicMachine{} + build, err := mb.setCmd(bm.withPodmanCommand([]string{"build", "-t", name, "--build-context", "test-context=" + additionalContextDir, mainContextDir})).run() + Expect(err).ToNot(HaveOccurred()) + Expect(build).To(Exit(0)) + Expect(build.outputToString()).To(ContainSubstring("COMMIT")) + + run, err := mb.setCmd(bm.withPodmanCommand([]string{"run", name, "cat", "/test1"})).run() + Expect(err).ToNot(HaveOccurred()) + Expect(run).To(Exit(0)) + Expect(build.outputToString()).To(ContainSubstring(name)) + + run, err = mb.setCmd(bm.withPodmanCommand([]string{"run", name, "cat", "/test2"})).run() + Expect(err).ToNot(HaveOccurred()) + Expect(run).To(Exit(0)) + Expect(build.outputToString()).To(ContainSubstring(name)) + }) }) func testHTTPServer(port string, shouldErr bool, expectedResponse string) {