Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package apptainer for openSUSE:Factory checked in at 2023-09-28 00:25:00 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/apptainer (Old) and /work/SRC/openSUSE:Factory/.apptainer.new.23327 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "apptainer" Thu Sep 28 00:25:00 2023 rev:22 rq:1113853 version:1.2.3 Changes: -------- --- /work/SRC/openSUSE:Factory/apptainer/apptainer.changes 2023-07-28 22:20:42.209322419 +0200 +++ /work/SRC/openSUSE:Factory/.apptainer.new.23327/apptainer.changes 2023-09-28 00:30:23.663282854 +0200 @@ -1,0 +2,25 @@ +Wed Sep 27 10:17:11 UTC 2023 - Christian Goll <cg...@suse.com> + +- removed CRYPTOGAMS license as not known in OBS and OpenSSL is + also valid + +------------------------------------------------------------------- +Mon Sep 25 08:57:57 UTC 2023 - Christian Goll <cg...@suse.com> + +- updated to 1.2.3 with following changes: + * The apptainer push/pull commands now show a progress bar for the oras + protocol like there was for docker and library protocols. + * The --nv and --rocm flags can now be used simultaneously. + * Fix the use of APPTAINER_CONFIGDIR with apptainer instance start and action + commands that refer to instance://. + * Fix the issue that apptainer would not read credentials from the Docker + fallback path ~/.docker/config.json if missing in the apptainer + credentials. + +------------------------------------------------------------------- +Tue Aug 29 15:34:36 UTC 2023 - Lubos Kocman <lubos.koc...@suse.com> + +- Update license for the package to cover also OpenSSL and CRYPTOGAMS + part of chacha_ppc64le.s + +------------------------------------------------------------------- Old: ---- apptainer-1.2.2.tar.gz New: ---- apptainer-1.2.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ apptainer.spec ++++++ --- /var/tmp/diff_new_pack.Lsb2Lg/_old 2023-09-28 00:30:25.435346818 +0200 +++ /var/tmp/diff_new_pack.Lsb2Lg/_new 2023-09-28 00:30:25.435346818 +0200 @@ -23,10 +23,12 @@ #%%define vers_suffix -rc.1 Summary: Application and environment virtualization -License: BSD-3-Clause-LBNL +# CRYPTOGAMS isn't known in OBS +#License: BSD-3-Clause-LBNL and (OpenSSL or CRYPTOGAMS) +License: BSD-3-Clause-LBNL AND OpenSSL Group: Productivity/Clustering/Computing Name: apptainer -Version: 1.2.2 +Version: 1.2.3 Release: 0 # https://spdx.org/licenses/BSD-3-Clause-LBNL.html URL: https://apptainer.org ++++++ apptainer-1.2.2.tar.gz -> apptainer-1.2.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apptainer-1.2.2/.github/workflows/ci.yml new/apptainer-1.2.3/.github/workflows/ci.yml --- old/apptainer-1.2.2/.github/workflows/ci.yml 2023-07-27 18:28:18.000000000 +0200 +++ new/apptainer-1.2.3/.github/workflows/ci.yml 2023-09-14 17:00:48.000000000 +0200 @@ -324,7 +324,7 @@ # See https://github.com/apptainer/apptainer/issues/796 - name: Update fuse-overlayfs version run: | - sudo sh -c "echo 'deb http://archive.ubuntu.com/ubuntu kinetic universe' >/etc/apt/sources.list.d/kinetic.list" + sudo sh -c "echo 'deb http://old-releases.ubuntu.com/ubuntu kinetic universe' >/etc/apt/sources.list.d/kinetic.list" sudo apt-get -q update && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y fuse-overlayfs - name: Enable full cgroups v2 delegation diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apptainer-1.2.2/CHANGELOG.md new/apptainer-1.2.3/CHANGELOG.md --- old/apptainer-1.2.2/CHANGELOG.md 2023-07-27 18:28:18.000000000 +0200 +++ new/apptainer-1.2.3/CHANGELOG.md 2023-09-14 17:00:48.000000000 +0200 @@ -5,11 +5,24 @@ and re-branded as Apptainer. For older changes see the [archived Singularity change log](https://github.com/apptainer/singularity/blob/release-3.8/CHANGELOG.md). +## v1.2.3 - \[2023-09-14\] + +- The `apptainer push/pull` commands now show a progress bar for the oras + protocol like there was for docker and library protocols. +- The `--nv` and `--rocm` flags can now be used simultaneously. +- Fix the use of `APPTAINER_CONFIGDIR` with `apptainer instance start` + and action commands that refer to `instance://`. +- Ignore undefined macros, to fix yum bootstrap agent on el7. +- Fix the issue that apptainer would not read credentials from the Docker + fallback path `~/.docker/config.json` if missing in the apptainer + credentials. + ## v1.2.2 - \[2023-07-27\] - Fix `$APPTAINER_MESSAGELEVEL` to correctly set the logging level. - Fix build failures when in setuid mode and unprivileged user namespaces are unavailable and the `--fakeroot` option is not selected. +- Remove `Requires: fuse` from rpm packaging. ## v1.2.1 - \[2023-07-24\] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apptainer-1.2.2/CONTRIBUTORS.md new/apptainer-1.2.3/CONTRIBUTORS.md --- old/apptainer-1.2.2/CONTRIBUTORS.md 2023-07-27 18:28:18.000000000 +0200 +++ new/apptainer-1.2.3/CONTRIBUTORS.md 2023-09-14 17:00:48.000000000 +0200 @@ -94,6 +94,7 @@ - Thomas Hamel <hm...@t-hamel.fr> - Tim Wright <7im.wri...@protonmail.com> - Tobias Poschwatta <poschwa...@zib.de> +- Tobias Ribizel <m...@ribizel.de> - Tru Huynh <t...@pasteur.fr> - Tyson Whitehead <twhiteh...@gmail.com> - Vanessa Sochat <vs...@users.noreply.github.com> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apptainer-1.2.2/INSTALL.md new/apptainer-1.2.3/INSTALL.md --- old/apptainer-1.2.2/INSTALL.md 2023-07-27 18:28:18.000000000 +0200 +++ new/apptainer-1.2.3/INSTALL.md 2023-09-14 17:00:48.000000000 +0200 @@ -137,7 +137,7 @@ for example: ```sh -git checkout v1.2.2 +git checkout v1.2.3 ``` ## Compiling Apptainer @@ -272,7 +272,7 @@ <!-- markdownlint-disable MD013 --> ```sh -VERSION=1.2.2 # this is the apptainer version, change as you need +VERSION=1.2.3 # this is the apptainer version, change as you need # Fetch the source wget https://github.com/apptainer/apptainer/releases/download/v${VERSION}/apptainer-${VERSION}.tar.gz ``` @@ -324,7 +324,7 @@ <!-- markdownlint-disable MD013 --> ```sh -VERSION=1.2.2 # this is the latest apptainer version, change as you need +VERSION=1.2.3 # this is the latest apptainer version, change as you need ./mconfig make -C builddir rpm sudo rpm -ivh ~/rpmbuild/RPMS/x86_64/apptainer-$(echo $VERSION|tr - \~)*.x86_64.rpm diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apptainer-1.2.2/dist/rpm/apptainer.spec.in new/apptainer-1.2.3/dist/rpm/apptainer.spec.in --- old/apptainer-1.2.2/dist/rpm/apptainer.spec.in 2023-07-27 18:28:18.000000000 +0200 +++ new/apptainer-1.2.3/dist/rpm/apptainer.spec.in 2023-09-14 17:00:48.000000000 +0200 @@ -113,8 +113,6 @@ Requires: fakeroot Requires: fuse-overlayfs Requires: e2fsprogs -# only gocryptfs requires fuse -Requires: fuse # Uncomment this for the epel build, but we don't want it for the Apptainer # release build because there the same rpm is shared across OS versions #%%if 0%{?el7} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apptainer-1.2.2/e2e/cache/cache.go new/apptainer-1.2.3/e2e/cache/cache.go --- old/apptainer-1.2.2/e2e/cache/cache.go 2023-07-27 18:28:18.000000000 +0200 +++ new/apptainer-1.2.3/e2e/cache/cache.go 2023-09-14 17:00:48.000000000 +0200 @@ -293,11 +293,11 @@ ) shamap := map[string]string{ - "arm64": "d715de5d9a2e1542c095a0f60145e23ec8b436fe1ff7b5d65da5a631d7ffac11", - "amd64": "6cf8f2587c2cfe28a808632580a02e3bbb4367061eeeee9b9a2386f4f841b1e9", - "arm32v6": "8ccd8f775eb6236695f649d396643a3f4ff5775ff2b2327417bf1e2c006615f7", - "amd64uri": "285fa2a74d0b116c214ff958d80bfe00db2dad1e0c3e6602b63d304490646d37", - "arm64v8uri": "292623b2234c665b6409a8c249efcce087428e2ccf347fa440d97c35772e5741", + "arm64": "b118e86313b8da65a597ae0f773fb7cac49fac8e6666147a9443b172288c5306", + "amd64": "f38acf33dd020a91d4673e16c6ab14048b00a5fd83e334edd8b33d339103cf83", + "arm32v6": "9fe584fc821b9ceaf4e04cd21ed191dfa553517728da94e3f50632523b3ab374", + "amd64uri": "82e895f183a2f926f72ad8d28c3c36444ce37de4f9e1efeba35f4ed1643232d6", + "arm64v8uri": "a101aa43bebd5f853837120fc8f28cae7ebe1c5f7f14a4d51a8c6d275f1456a9", } files := retrieveFileNames(t, cacheDir) @@ -314,7 +314,7 @@ e2e.AsSubtest("pull image failure because of wrong --arch"), e2e.WithProfile(e2e.UserProfile), e2e.WithCommand("pull"), - e2e.WithArgs([]string{"--force", "--arch", "amd", sifname, "docker://alpine:3.17"}...), + e2e.WithArgs([]string{"--force", "--arch", "amd", sifname, "docker://alpine:3.6"}...), e2e.ExpectExit(255, e2e.ExpectError(e2e.ContainMatch, "arch: amd is not valid")), ) @@ -323,7 +323,7 @@ e2e.AsSubtest("pull image failure because --arch-variant is required"), e2e.WithProfile(e2e.UserProfile), e2e.WithCommand("pull"), - e2e.WithArgs([]string{"--force", "--arch", "arm", sifname, "docker://alpine:3.17"}...), + e2e.WithArgs([]string{"--force", "--arch", "arm", sifname, "docker://alpine:3.6"}...), e2e.ExpectExit(255, e2e.ExpectError(e2e.ContainMatch, "arm needs variant specification")), ) @@ -332,7 +332,7 @@ e2e.AsSubtest("pull image failure because of wrong --arch-variant"), e2e.WithProfile(e2e.UserProfile), e2e.WithCommand("pull"), - e2e.WithArgs([]string{"--force", "--arch", "arm64", "--arch-variant", "v9", sifname, "docker://alpine:3.17"}...), + e2e.WithArgs([]string{"--force", "--arch", "arm64", "--arch-variant", "v9", sifname, "docker://alpine:3.6"}...), e2e.ExpectExit(255, e2e.ExpectError(e2e.ContainMatch, "arch: arm64v9 is not valid")), ) @@ -342,7 +342,7 @@ e2e.AsSubtest("pull amd64 image"), e2e.WithProfile(e2e.UserProfile), e2e.WithCommand("pull"), - e2e.WithArgs([]string{"--force", "--arch", "amd64", sifname, "docker://alpine:3.17"}...), + e2e.WithArgs([]string{"--force", "--arch", "amd64", sifname, "docker://alpine:3.6"}...), e2e.ExpectExit(0), ) ensureCachedWithSha(t, cacheDir, shamap["amd64"]) @@ -352,7 +352,7 @@ e2e.AsSubtest("pull arm64 image"), e2e.WithProfile(e2e.UserProfile), e2e.WithCommand("pull"), - e2e.WithArgs([]string{"--force", "--arch", "arm64", sifname, "docker://alpine:3.17"}...), + e2e.WithArgs([]string{"--force", "--arch", "arm64", sifname, "docker://alpine:3.6"}...), e2e.ExpectExit(0), ) ensureCachedWithSha(t, cacheDir, shamap["arm64"]) @@ -362,7 +362,7 @@ e2e.AsSubtest("pull arm32v6 image"), e2e.WithProfile(e2e.UserProfile), e2e.WithCommand("pull"), - e2e.WithArgs([]string{"--force", "--arch", "arm", "--arch-variant", "6", sifname, "docker://alpine:3.17"}...), + e2e.WithArgs([]string{"--force", "--arch", "arm", "--arch-variant", "6", sifname, "docker://alpine:3.6"}...), e2e.ExpectExit(0), ) ensureCachedWithSha(t, cacheDir, shamap["arm32v6"]) @@ -378,7 +378,7 @@ e2e.AsSubtest("pull amd64 image by explicitly defining arch"), e2e.WithProfile(e2e.UserProfile), e2e.WithCommand("pull"), - e2e.WithArgs([]string{"--force", sifname, "docker://amd64/alpine:3.17"}...), + e2e.WithArgs([]string{"--force", sifname, "docker://amd64/alpine:3.6"}...), e2e.ExpectExit(0), ) ensureCachedWithSha(t, cacheDir, shamap["amd64uri"]) @@ -388,10 +388,10 @@ e2e.AsSubtest("pull arm64 image by explicitly defining arch"), e2e.WithProfile(e2e.UserProfile), e2e.WithCommand("pull"), - e2e.WithArgs([]string{"--force", sifname, "docker://arm64v8/alpine:3.17"}...), + e2e.WithArgs([]string{"--force", sifname, "docker://arm64v8/alpine:3.6"}...), e2e.ExpectExit(0), ) - ensureCachedWithSha(t, cacheDir, shamap["arm64v8"]) + ensureCachedWithSha(t, cacheDir, shamap["arm64v8uri"]) files = retrieveFileNames(t, cacheDir) if len(files) != 5 { @@ -405,7 +405,7 @@ e2e.AsSubtest("pull amd64 image using different arch and uri"), e2e.WithProfile(e2e.UserProfile), e2e.WithCommand("pull"), - e2e.WithArgs([]string{"--force", "--arch", "386", sifname, "docker://amd64/alpine:3.17"}...), + e2e.WithArgs([]string{"--force", "--arch", "386", sifname, "docker://amd64/alpine:3.6"}...), e2e.ExpectExit(0), ) @@ -414,7 +414,7 @@ e2e.AsSubtest("pull amd64 image using different arch and uri with docker.io prefix"), e2e.WithProfile(e2e.UserProfile), e2e.WithCommand("pull"), - e2e.WithArgs([]string{"--force", "--arch", "386", sifname, "docker://docker.io/amd64/alpine:3.17"}...), + e2e.WithArgs([]string{"--force", "--arch", "386", sifname, "docker://docker.io/amd64/alpine:3.6"}...), e2e.ExpectExit(0), ) @@ -423,7 +423,7 @@ e2e.AsSubtest("pull arm64 image using different arch and uri"), e2e.WithProfile(e2e.UserProfile), e2e.WithCommand("pull"), - e2e.WithArgs([]string{"--force", "--arch", "amd64", sifname, "docker://arm64v8/alpine:3.17"}...), + e2e.WithArgs([]string{"--force", "--arch", "amd64", sifname, "docker://arm64v8/alpine:3.6"}...), e2e.ExpectExit(0), ) @@ -432,7 +432,7 @@ e2e.AsSubtest("pull arm64 image using different arch and uri with docker.io prefix"), e2e.WithProfile(e2e.UserProfile), e2e.WithCommand("pull"), - e2e.WithArgs([]string{"--force", "--arch", "amd64", sifname, "docker://docker.io/arm64v8/alpine:3.17"}...), + e2e.WithArgs([]string{"--force", "--arch", "amd64", sifname, "docker://docker.io/arm64v8/alpine:3.6"}...), e2e.ExpectExit(0), ) @@ -441,7 +441,7 @@ e2e.AsSubtest("build arm64 image using uri"), e2e.WithProfile(e2e.UserProfile), e2e.WithCommand("build"), - e2e.WithArgs([]string{"--force", sifname, "docker://arm64v8/alpine:3.17"}...), + e2e.WithArgs([]string{"--force", sifname, "docker://arm64v8/alpine:3.6"}...), e2e.ExpectExit(0), ) @@ -450,7 +450,7 @@ e2e.AsSubtest("build amd64 image using uri"), e2e.WithProfile(e2e.UserProfile), e2e.WithCommand("build"), - e2e.WithArgs([]string{"--force", sifname, "docker://amd64/alpine:3.17"}...), + e2e.WithArgs([]string{"--force", sifname, "docker://amd64/alpine:3.6"}...), e2e.ExpectExit(0), ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apptainer-1.2.2/e2e/instance/instance.go new/apptainer-1.2.3/e2e/instance/instance.go --- old/apptainer-1.2.2/e2e/instance/instance.go 2023-07-27 18:28:18.000000000 +0200 +++ new/apptainer-1.2.3/e2e/instance/instance.go 2023-09-14 17:00:48.000000000 +0200 @@ -40,6 +40,7 @@ type ctx struct { env e2e.TestEnv profile e2e.Profile + withEnv []string } // Test that a basic echo server instance can be started, communicated with, @@ -359,6 +360,40 @@ } } +// Test instances when using an alternate configdir +func (c *ctx) testInstanceWithConfigDir(t *testing.T) { + dir, err := os.MkdirTemp(c.env.TestDir, "InstanceWithConfigDir") + if err != nil { + t.Fatalf("Failed to create temporary directory: %v", err) + } + defer os.RemoveAll(dir) + + c.withEnv = append(os.Environ(), "APPTAINER_CONFIGDIR="+dir) + defer func() { + c.withEnv = []string{} + }() + + name := "movedConfig" + c.env.RunApptainer( + t, + e2e.WithProfile(c.profile), + e2e.WithCommand("instance start"), + e2e.WithArgs(c.env.ImagePath, name), + e2e.WithEnv(c.withEnv), + e2e.ExpectExit(0), + ) + + c.expectInstance(t, name, 1) + c.execInstance(t, name, "id") + c.stopInstance(t, name) + + e2e.Privileged(func(t *testing.T) { + if _, err := os.Stat(dir + "/instances/app"); err != nil { + t.Fatalf("failed %v", err) + } + })(t) +} + // E2ETests is the main func to trigger the test suite func E2ETests(env e2e.TestEnv) testhelper.Tests { c := &ctx{ @@ -388,6 +423,7 @@ {"StopAll", c.testStopAll}, {"GhostInstance", c.testGhostInstance}, {"CheckpointInstance", c.testCheckpointInstance}, + {"InstanceWithConfigDir", c.testInstanceWithConfigDir}, } profiles := []e2e.Profile{ @@ -396,7 +432,6 @@ } for _, profile := range profiles { - profile := profile t.Run(profile.String(), func(t *testing.T) { c.profile = profile for _, tt := range tests { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apptainer-1.2.2/e2e/instance/instance_utils.go new/apptainer-1.2.3/e2e/instance/instance_utils.go --- old/apptainer-1.2.2/e2e/instance/instance_utils.go 2023-07-27 18:28:18.000000000 +0200 +++ new/apptainer-1.2.3/e2e/instance/instance_utils.go 2023-09-14 17:00:48.000000000 +0200 @@ -45,6 +45,7 @@ e2e.WithProfile(c.profile), e2e.WithCommand("instance stop"), e2e.WithArgs(args...), + e2e.WithEnv(c.withEnv), e2e.PostRun(func(t *testing.T) { success = !t.Failed() }), @@ -65,6 +66,7 @@ e2e.WithProfile(c.profile), e2e.WithCommand("exec"), e2e.WithArgs(args...), + e2e.WithEnv(c.withEnv), e2e.PostRun(func(t *testing.T) { success = !t.Failed() }), @@ -92,6 +94,7 @@ e2e.WithProfile(c.profile), e2e.WithCommand("instance list"), e2e.WithArgs([]string{"--json", name}...), + e2e.WithEnv(c.withEnv), e2e.ExpectExit(0, listInstancesFn), ) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apptainer-1.2.2/e2e/remote/remote.go new/apptainer-1.2.3/e2e/remote/remote.go --- old/apptainer-1.2.2/e2e/remote/remote.go 2023-07-27 18:28:18.000000000 +0200 +++ new/apptainer-1.2.3/e2e/remote/remote.go 2023-09-14 17:00:48.000000000 +0200 @@ -11,15 +11,18 @@ package remote import ( + "errors" "fmt" "io" "log" "os" + "path/filepath" "strings" "testing" "github.com/apptainer/apptainer/e2e/internal/e2e" "github.com/apptainer/apptainer/e2e/internal/testhelper" + "github.com/apptainer/apptainer/pkg/syfs" ) type ctx struct { @@ -932,6 +935,98 @@ } } +func (c ctx) testDockerFallbackConfig(t *testing.T) { + e2e.EnsureImage(t, c.env) + + tmpdir, err := os.MkdirTemp(c.env.TestDir, "pull_test.") + if err != nil { + t.Fatalf("Failed to create temporary directory for pull test: %+v", err) + } + t.Cleanup(func() { + if !t.Failed() { + os.RemoveAll(tmpdir) + } + }) + + var ( + registry = fmt.Sprintf("oras://%s", c.env.TestRegistry) + repo = fmt.Sprintf("oras://%s/private/e2e:1.0.0", c.env.TestRegistry) + ) + + c.env.RunApptainer( + t, + e2e.AsSubtest(`remote login`), + e2e.WithProfile(e2e.UserProfile), + e2e.WithCommand("remote login"), + e2e.WithArgs([]string{"-u", e2e.DefaultUsername, "-p", e2e.DefaultPassword, registry}...), + e2e.ExpectExit(0), + ) + + c.env.RunApptainer( + t, + e2e.AsSubtest(`push image`), + e2e.WithProfile(e2e.UserProfile), + e2e.WithCommand("push"), + e2e.WithArgs([]string{c.env.ImagePath, repo}...), + e2e.ExpectExit(0), + ) + + user := e2e.CurrentUser(t) + defaultConfig := filepath.Join(user.Dir, ".apptainer", syfs.DockerConfFile) + dockerPath := filepath.Join(user.Dir, ".docker") + dockerConfig := filepath.Join(dockerPath, "config.json") + + c.env.RunApptainer( + t, + e2e.AsSubtest(`try pulling oras image`), + e2e.WithProfile(e2e.UserProfile), + e2e.WithCommand("pull"), + e2e.WithArgs([]string{"--disable-cache", "--force", filepath.Join(tmpdir, "image.sif"), repo}...), + e2e.ExpectExit(0), + e2e.PostRun(func(t *testing.T) { + // move the ~/.apptainer/docker-config.json to ~/.docker/config.json + if _, err := os.Stat(defaultConfig); err != nil && errors.Is(err, os.ErrNotExist) { + t.Fatalf("Failed to find the default config: %s", defaultConfig) + } + + err := os.MkdirAll(dockerPath, 0o755) + if err != nil { + t.Fatalf("Failed to create docker config path: %s", dockerPath) + } + + err = os.Rename(defaultConfig, dockerConfig) + if err != nil { + t.Fatalf("Failed to move default apptainer config: %s to docker config path: %s", defaultConfig, dockerConfig) + } + }), + ) + + c.env.RunApptainer( + t, + e2e.AsSubtest(`try pulling oras image again`), + e2e.WithProfile(e2e.UserProfile), + e2e.WithCommand("pull"), + e2e.WithArgs([]string{"--disable-cache", "--force", filepath.Join(tmpdir, "image.sif"), repo}...), + e2e.ExpectExit(0), + e2e.PostRun(func(t *testing.T) { + // move back + err := os.Rename(dockerConfig, defaultConfig) + if err != nil { + t.Fatalf("Failed to move docker config: %s to apptainr default config path: %s", dockerConfig, defaultConfig) + } + }), + ) + + c.env.RunApptainer( + t, + e2e.AsSubtest(`logout`), + e2e.WithProfile(e2e.UserProfile), + e2e.WithCommand("remote logout"), + e2e.WithArgs([]string{registry}...), + e2e.ExpectExit(0), + ) +} + // E2ETests is the main func to trigger the test suite func E2ETests(env e2e.TestEnv) testhelper.Tests { c := ctx{ @@ -952,5 +1047,6 @@ "oci login repeated": np(c.remoteLoginRepeated), "keyserver": np(c.remoteKeyserver), "use exclusive": np(c.remoteUseExclusive), + "docker fallback config": np(c.testDockerFallbackConfig), } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apptainer-1.2.2/internal/pkg/build/sources/conveyorPacker_yum.go new/apptainer-1.2.3/internal/pkg/build/sources/conveyorPacker_yum.go --- old/apptainer-1.2.2/internal/pkg/build/sources/conveyorPacker_yum.go 2023-07-27 18:28:18.000000000 +0200 +++ new/apptainer-1.2.3/internal/pkg/build/sources/conveyorPacker_yum.go 2023-09-14 17:00:48.000000000 +0200 @@ -129,9 +129,13 @@ rpmDBBackend, err := rpm.GetMacro("_db_backend") if err != nil { - return err + if err != rpm.ErrMacroUndefined { + return err + } + sylog.Debugf("Undefined macro _db_backend is ignored.") } - if rpmDBBackend != "bdb" { + + if err == nil && rpmDBBackend != "bdb" { sylog.Warningf("Your host system is using the %s RPM database backend.", rpmDBBackend) sylog.Warningf("Bootstrapping of older distributions that use the bdb backend will fail.") } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apptainer-1.2.2/internal/pkg/client/oras/oras.go new/apptainer-1.2.3/internal/pkg/client/oras/oras.go --- old/apptainer-1.2.2/internal/pkg/client/oras/oras.go 2023-07-27 18:28:18.000000000 +0200 +++ new/apptainer-1.2.3/internal/pkg/client/oras/oras.go 2023-09-14 17:00:48.000000000 +0200 @@ -86,13 +86,13 @@ } } -func getResolver(ctx context.Context, ociAuth *ocitypes.DockerAuthConfig, noHTTPS, push bool) (remotes.Resolver, error) { +func getResolver(ctx context.Context, ociAuth *ocitypes.DockerAuthConfig, noHTTPS, push, progressBar bool) (remotes.Resolver, error) { opts := docker.ResolverOptions{Credentials: genCredfn(ociAuth), PlainHTTP: noHTTPS} if ociAuth != nil && (ociAuth.Username != "" || ociAuth.Password != "") { return docker.NewResolver(opts), nil } - cli, err := oras_docker.NewClient(syfs.DockerConf()) + cli, err := oras_docker.NewClientWithDockerFallback(syfs.DockerConf()) if err != nil { sylog.Warningf("Couldn't load auth credential file: %s", err) return docker.NewResolver(opts), nil @@ -109,7 +109,16 @@ httpClient.Transport = newOrasUploadTransport() } - return cli.Resolver(ctx, httpClient, noHTTPS) + solver, err := cli.Resolver(ctx, httpClient, noHTTPS) + if err != nil { + return solver, err + } + + if progressBar { + return &resolver{solver}, nil + } + + return solver, nil } // DownloadImage downloads a SIF image specified by an oci reference to a file using the included credentials @@ -128,7 +137,7 @@ sylog.Infof("No tag or digest found, using default: %s", SifDefaultTag) } - resolver, err := getResolver(ctx, ociAuth, noHTTPS, false) + resolver, err := getResolver(ctx, ociAuth, noHTTPS, false, true) if err != nil { return fmt.Errorf("while getting resolver: %s", err) } @@ -213,7 +222,7 @@ sylog.Infof("No tag or digest found, using default: %s", SifDefaultTag) } - resolver, err := getResolver(ctx, ociAuth, noHTTPS, true) + resolver, err := getResolver(ctx, ociAuth, noHTTPS, true, true) if err != nil { return fmt.Errorf("while getting resolver: %s", err) } @@ -273,7 +282,7 @@ ref := strings.TrimPrefix(uri, "oras://") ref = strings.TrimPrefix(ref, "//") - resolver, err := getResolver(ctx, ociAuth, noHTTPS, false) + resolver, err := getResolver(ctx, ociAuth, noHTTPS, false, false) if err != nil { return "", fmt.Errorf("while getting resolver: %s", err) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apptainer-1.2.2/internal/pkg/client/oras/resolver.go new/apptainer-1.2.3/internal/pkg/client/oras/resolver.go --- old/apptainer-1.2.2/internal/pkg/client/oras/resolver.go 1970-01-01 01:00:00.000000000 +0100 +++ new/apptainer-1.2.3/internal/pkg/client/oras/resolver.go 2023-09-14 17:00:48.000000000 +0200 @@ -0,0 +1,144 @@ +// Copyright (c) Contributors to the Apptainer project, established as +// Apptainer a Series of LF Projects LLC. +// For website terms of use, trademark policy, privacy policy and other +// project policies see https://lfprojects.org/policies +// Copyright (c) 2020, Control Command Inc. All rights reserved. +// Copyright (c) 2020-2022, Sylabs Inc. All rights reserved. +// This software is licensed under a 3-clause BSD license. Please consult the +// LICENSE.md file distributed with the sources of this project regarding your +// rights to use or distribute this software. + +// This file is to add progress bar support for oras protocol. +package oras + +import ( + "context" + "io" + + "github.com/apptainer/apptainer/internal/pkg/client" + libClient "github.com/apptainer/container-library-client/client" + "github.com/containerd/containerd/content" + "github.com/containerd/containerd/remotes" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" +) + +type resolver struct { + remotes.Resolver +} + +type pusher struct { + remotes.Pusher +} + +type fetcher struct { + remotes.Fetcher +} + +type contentWriter struct { + content.Writer + mwriter io.Writer + pb libClient.ProgressBar +} + +type fetchWriter struct { + *io.PipeWriter + pb libClient.ProgressBar +} + +func (r *resolver) Resolve(ctx context.Context, ref string) (name string, desc ocispec.Descriptor, err error) { + return r.Resolver.Resolve(ctx, ref) +} + +func (r *resolver) Fetcher(ctx context.Context, ref string) (remotes.Fetcher, error) { + f, err := r.Resolver.Fetcher(ctx, ref) + if err != nil { + return &fetcher{}, err + } + + return &fetcher{f}, nil +} + +func (r *resolver) Pusher(ctx context.Context, ref string) (remotes.Pusher, error) { + p, err := r.Resolver.Pusher(ctx, ref) + if err != nil { + return &pusher{}, err + } + + return &pusher{p}, nil +} + +func (p *pusher) Push(ctx context.Context, desc ocispec.Descriptor) (content.Writer, error) { + writer, err := p.Pusher.Push(ctx, desc) + if err != nil { + return &contentWriter{}, err + } + + in, out := io.Pipe() + mwriter := io.MultiWriter(writer, out) + pb := &client.DownloadProgressBar{} + pb.Init(desc.Size) + + go func() { + _, err := io.Copy(io.Discard, in) + if err != nil { + pb.Abort(true) + in.CloseWithError(err) + } + pb.Wait() + in.Close() + }() + + return &contentWriter{ + Writer: writer, + mwriter: mwriter, + pb: pb, + }, nil +} + +func (f *fetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.ReadCloser, error) { + reader, err := f.Fetcher.Fetch(ctx, desc) + if err != nil { + return &io.PipeReader{}, err + } + + pb := &client.DownloadProgressBar{} + pb.Init(desc.Size) + + in, out := io.Pipe() + writer := &fetchWriter{ + PipeWriter: out, + pb: pb, + } + + go func() { + _, err := io.Copy(writer, reader) + if err != nil { + pb.Abort(true) + out.CloseWithError(err) + } + pb.Wait() + out.Close() + }() + + return in, nil +} + +func (w *contentWriter) Write(p []byte) (n int, err error) { + n, err = w.mwriter.Write(p) + if err != nil { + w.pb.Abort(true) + return n, err + } + w.pb.IncrBy(n) + return n, err +} + +func (pw *fetchWriter) Write(p []byte) (n int, err error) { + n, err = pw.PipeWriter.Write(p) + if err != nil { + pw.pb.Abort(true) + return n, err + } + pw.pb.IncrBy(n) + return n, err +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apptainer-1.2.2/internal/pkg/instance/instance_linux.go new/apptainer-1.2.3/internal/pkg/instance/instance_linux.go --- old/apptainer-1.2.2/internal/pkg/instance/instance_linux.go 2023-07-27 18:28:18.000000000 +0200 +++ new/apptainer-1.2.3/internal/pkg/instance/instance_linux.go 2023-09-14 17:00:48.000000000 +0200 @@ -91,19 +91,22 @@ } var u *user.User + var configDir string if username == "" { u, err = user.CurrentOriginal() + if err != nil { + return "", err + } + configDir = syfs.ConfigDir() } else { u, err = user.GetPwNam(username) - } - - if err != nil { - return "", err - } - - configDir, err := syfs.ConfigDirForUsername(u.Name) - if err != nil { - return "", err + if err != nil { + return "", err + } + configDir, err = syfs.ConfigDirForUsername(u.Name) + if err != nil { + return "", err + } } return filepath.Join(configDir, instancePath, subDir, hostname, u.Name), nil diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apptainer-1.2.2/internal/pkg/remote/credential/login_handler.go new/apptainer-1.2.3/internal/pkg/remote/credential/login_handler.go --- old/apptainer-1.2.2/internal/pkg/remote/credential/login_handler.go 2023-07-27 18:28:18.000000000 +0200 +++ new/apptainer-1.2.3/internal/pkg/remote/credential/login_handler.go 2023-09-14 17:00:48.000000000 +0200 @@ -75,7 +75,7 @@ if err != nil { return nil, err } - cli, err := docker.NewClient(syfs.DockerConf()) + cli, err := docker.NewClientWithDockerFallback(syfs.DockerConf()) if err != nil { return nil, err } @@ -108,7 +108,7 @@ } func (h *ociHandler) logout(u *url.URL) error { - cli, err := docker.NewClient(syfs.DockerConf()) + cli, err := docker.NewClientWithDockerFallback(syfs.DockerConf()) if err != nil { return err } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apptainer-1.2.2/internal/pkg/runtime/engine/apptainer/prepare_linux.go new/apptainer-1.2.3/internal/pkg/runtime/engine/apptainer/prepare_linux.go --- old/apptainer-1.2.2/internal/pkg/runtime/engine/apptainer/prepare_linux.go 2023-07-27 18:28:18.000000000 +0200 +++ new/apptainer-1.2.3/internal/pkg/runtime/engine/apptainer/prepare_linux.go 2023-09-14 17:00:48.000000000 +0200 @@ -665,6 +665,8 @@ // //nolint:maintidx func (e *EngineOperations) prepareInstanceJoinConfig(starterConfig *starter.Config) error { + os.Setenv("APPTAINER_CONFIGDIR", e.EngineConfig.GetConfigDir()) + name := instance.ExtractName(e.EngineConfig.GetImage()) file, err := instance.Get(name, instance.AppSubDir) if err != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apptainer-1.2.2/internal/pkg/runtime/engine/apptainer/process_linux.go new/apptainer-1.2.3/internal/pkg/runtime/engine/apptainer/process_linux.go --- old/apptainer-1.2.2/internal/pkg/runtime/engine/apptainer/process_linux.go 2023-07-27 18:28:18.000000000 +0200 +++ new/apptainer-1.2.3/internal/pkg/runtime/engine/apptainer/process_linux.go 2023-09-14 17:00:48.000000000 +0200 @@ -347,6 +347,8 @@ } if e.EngineConfig.GetInstance() { + os.Setenv("APPTAINER_CONFIGDIR", e.EngineConfig.GetConfigDir()) + name := e.CommonConfig.ContainerID if err := os.Chdir("/"); err != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apptainer-1.2.2/internal/pkg/runtime/launch/launcher_linux.go new/apptainer-1.2.3/internal/pkg/runtime/launch/launcher_linux.go --- old/apptainer-1.2.2/internal/pkg/runtime/launch/launcher_linux.go 2023-07-27 18:28:18.000000000 +0200 +++ new/apptainer-1.2.3/internal/pkg/runtime/launch/launcher_linux.go 2023-09-14 17:00:48.000000000 +0200 @@ -45,6 +45,7 @@ apptainercallback "github.com/apptainer/apptainer/pkg/plugin/callback/runtime/engine/apptainer" apptainerConfig "github.com/apptainer/apptainer/pkg/runtime/engine/apptainer/config" "github.com/apptainer/apptainer/pkg/runtime/engine/config" + "github.com/apptainer/apptainer/pkg/syfs" "github.com/apptainer/apptainer/pkg/sylog" "github.com/apptainer/apptainer/pkg/util/apptainerconf" "github.com/apptainer/apptainer/pkg/util/capabilities" @@ -267,6 +268,7 @@ // Additional directory overrides. l.engineConfig.SetScratchDir(l.cfg.ScratchDirs) l.engineConfig.SetWorkdir(l.cfg.WorkDir) + l.engineConfig.SetConfigDir(syfs.ConfigDir()) // Container networking configuration. l.engineConfig.SetNetwork(l.cfg.Network) @@ -791,8 +793,12 @@ l.cfg.Nvidia = true } - if l.cfg.Nvidia && l.cfg.Rocm { - sylog.Warningf("--nv and --rocm cannot be used together. Only --nv will be applied.") + if l.cfg.Rocm { + err := l.setRocmConfig() + // This is currently unnecessary, but useful for not missing future errors + if err != nil { + return err + } } if l.cfg.Nvidia { @@ -809,10 +815,6 @@ } return fmt.Errorf("--fakeroot does not support --nvccli in set-uid installations") } - - if l.cfg.Rocm { - return l.setRocmConfig() - } return nil } @@ -866,7 +868,7 @@ if err != nil { sylog.Warningf("While finding nv bind points: %v", err) } - l.setGPUBinds(libs, bins, ipcs, "nv") + l.addGPUBinds(libs, bins, ipcs, "nv") return nil } @@ -879,12 +881,12 @@ if err != nil { sylog.Warningf("While finding ROCm bind points: %v", err) } - l.setGPUBinds(libs, bins, []string{}, "nv") + l.addGPUBinds(libs, bins, []string{}, "rocm") return nil } -// setGPUBinds sets EngineConfig entries to bind the provided list of libs, bins, ipc files. -func (l *Launcher) setGPUBinds(libs, bins, ipcs []string, gpuPlatform string) { +// addGPUBinds adds EngineConfig entries to bind the provided list of libs, bins, ipc files. +func (l *Launcher) addGPUBinds(libs, bins, ipcs []string, gpuPlatform string) { files := make([]string, len(bins)+len(ipcs)) if len(files) == 0 { sylog.Warningf("Could not find any %s files on this host!", gpuPlatform) @@ -899,12 +901,12 @@ for i, ipc := range ipcs { files[i+len(bins)] = ipc } - l.engineConfig.SetFilesPath(files) + l.engineConfig.AppendFilesPath(files...) } if len(libs) == 0 { sylog.Warningf("Could not find any %s libraries on this host!", gpuPlatform) } else { - l.engineConfig.SetLibrariesPath(libs) + l.engineConfig.AppendLibrariesPath(libs...) } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apptainer-1.2.2/pkg/runtime/engine/apptainer/config/config.go new/apptainer-1.2.3/pkg/runtime/engine/apptainer/config/config.go --- old/apptainer-1.2.2/pkg/runtime/engine/apptainer/config/config.go 2023-07-27 18:28:18.000000000 +0200 +++ new/apptainer-1.2.3/pkg/runtime/engine/apptainer/config/config.go 2023-09-14 17:00:48.000000000 +0200 @@ -97,6 +97,7 @@ Image string `json:"image"` ImageArg string `json:"imageArg"` Workdir string `json:"workdir,omitempty"` + ConfigDir string `json:"configdir,omitempty"` CgroupsJSON string `json:"cgroupsJSON,omitempty"` HomeSource string `json:"homedir,omitempty"` HomeDest string `json:"homeDest,omitempty"` @@ -263,6 +264,17 @@ return e.JSON.Workdir } +// SetConfigDir sets a config directory path. +func (e *EngineConfig) SetConfigDir(name string) { + e.JSON.ConfigDir = name +} + +// GetConfigDir retrieves the config directory path if it is set, or +// otherwise an empty string. +func (e *EngineConfig) GetConfigDir() string { + return e.JSON.ConfigDir +} + // SetScratchDir set a scratch directory path. func (e *EngineConfig) SetScratchDir(scratchdir []string) { e.JSON.ScratchDir = scratchdir @@ -659,6 +671,21 @@ return e.JSON.TargetGID } +// ConcatenateSliceDeduplicate concatenates two string slices and returns a string slice without duplicated entries. +func ConcatenateSliceDeduplicate(first []string, second []string) []string { + dedup := make(map[string]struct{}) + for _, slice := range [][]string{first, second} { + for _, elem := range slice { + dedup[elem] = struct{}{} + } + } + slice := make([]string, 0, len(dedup)) + for elem := range dedup { + slice = append(slice, elem) + } + return slice +} + // SetLibrariesPath sets libraries to bind in container // /.singularity.d/libs directory. func (e *EngineConfig) SetLibrariesPath(libraries []string) { @@ -668,7 +695,7 @@ // AppendLibrariesPath adds libraries to bind in container // /.singularity.d/libs directory. func (e *EngineConfig) AppendLibrariesPath(libraries ...string) { - e.JSON.LibrariesPath = append(e.JSON.LibrariesPath, libraries...) + e.JSON.LibrariesPath = ConcatenateSliceDeduplicate(e.JSON.LibrariesPath, libraries) } // GetLibrariesPath returns libraries to bind in container @@ -684,7 +711,7 @@ // AppendFilesPath adds files to bind in container (eg: --nv) func (e *EngineConfig) AppendFilesPath(files ...string) { - e.JSON.FilesPath = append(e.JSON.FilesPath, files...) + e.JSON.FilesPath = ConcatenateSliceDeduplicate(e.JSON.FilesPath, files) } // GetFilesPath returns files to bind in container (eg: --nv).