From c846f02801d1af4e43b8a7a1aa959af0c7aa1b14 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Tue, 19 Nov 2024 17:57:53 +0100 Subject: [PATCH 1/4] libimage tests: try to avoid docker.io images These images can and will change at any time and thus can break our CI without any external changes which is very bad. The TestPush test is failing because it expects two not one image as it converts from docker to oci on push. However the upstream docker.io/library/alpine was switched to an oci image thus the test started failing as the local storage now has the same id and just stores two different tags for the same image. Switch to our own controlled quay.io images where possible. This is neither complete nor do I fully understand the tests here. I did a quick search and replace and will see what works or not. Signed-off-by: Paul Holzinger (cherry picked from commit 97d26144888e8fba0970fc89660b1c0212fb6a65) --- libimage/image_test.go | 2 +- libimage/pull_test.go | 2 +- libimage/push_test.go | 16 ++++++++-------- libimage/remove_test.go | 2 +- libimage/runtime_test.go | 14 +++++++------- libimage/save_test.go | 4 ++-- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/libimage/image_test.go b/libimage/image_test.go index 0f5333418..bd1f78cae 100644 --- a/libimage/image_test.go +++ b/libimage/image_test.go @@ -391,7 +391,7 @@ func TestUntag(t *testing.T) { func getImageAndRuntime(t *testing.T) (*Runtime, *Image) { // Note: this will resolve pull from the GCR registry (see // testdata/registries.conf). - busyboxLatest := "docker.io/library/busybox:latest" + busyboxLatest := "quay.io/libpod/busybox:latest" runtime := testNewRuntime(t) ctx := context.Background() diff --git a/libimage/pull_test.go b/libimage/pull_test.go index b965358ec..4f9c2813c 100644 --- a/libimage/pull_test.go +++ b/libimage/pull_test.go @@ -223,7 +223,7 @@ func TestPullOCINoReference(t *testing.T) { // Exercise pulling from the OCI transport and make sure that a // specified reference is preserved in the image name. - busybox := "docker.io/library/busybox:latest" + busybox := "quay.io/libpod/busybox:latest" runtime := testNewRuntime(t) ctx := context.Background() pullOptions := &PullOptions{} diff --git a/libimage/push_test.go b/libimage/push_test.go index dd8a24752..1e69cffc8 100644 --- a/libimage/push_test.go +++ b/libimage/push_test.go @@ -22,7 +22,7 @@ func TestPush(t *testing.T) { // Prefetch alpine. pullOptions := &PullOptions{} pullOptions.Writer = os.Stdout - _, err := runtime.Pull(ctx, "docker.io/library/alpine:latest", config.PullPolicyAlways, pullOptions) + _, err := runtime.Pull(ctx, "quay.io/libpod/alpine:latest", config.PullPolicyAlways, pullOptions) require.NoError(t, err) pushOptions := &PushOptions{} @@ -81,7 +81,7 @@ func TestPushOtherPlatform(t *testing.T) { pullOptions := &PullOptions{} pullOptions.Writer = os.Stdout pullOptions.Architecture = "arm64" - pulledImages, err := runtime.Pull(ctx, "docker.io/library/alpine:latest", config.PullPolicyAlways, pullOptions) + pulledImages, err := runtime.Pull(ctx, "quay.io/libpod/alpine:latest", config.PullPolicyAlways, pullOptions) require.NoError(t, err) require.Len(t, pulledImages, 1) @@ -95,7 +95,7 @@ func TestPushOtherPlatform(t *testing.T) { require.NoError(t, err) tmp.Close() defer os.Remove(tmp.Name()) - _, err = runtime.Push(ctx, "docker.io/library/alpine:latest", "docker-archive:"+tmp.Name(), pushOptions) + _, err = runtime.Push(ctx, "quay.io/libpod/alpine:latest", "docker-archive:"+tmp.Name(), pushOptions) require.NoError(t, err) } @@ -107,7 +107,7 @@ func TestPushWithForceCompression(t *testing.T) { pullOptions := &PullOptions{} pullOptions.Writer = os.Stdout pullOptions.Architecture = "arm64" - pulledImages, err := runtime.Pull(ctx, "docker.io/library/alpine:latest", config.PullPolicyAlways, pullOptions) + pulledImages, err := runtime.Pull(ctx, "quay.io/libpod/alpine:latest", config.PullPolicyAlways, pullOptions) require.NoError(t, err) require.Len(t, pulledImages, 1) @@ -121,7 +121,7 @@ func TestPushWithForceCompression(t *testing.T) { pushOptions.SystemContext.DirForceDecompress = true pushOptions.Writer = os.Stdout dirDest := t.TempDir() - _, err = runtime.Push(ctx, "docker.io/library/alpine:latest", "dir:"+dirDest, pushOptions) + _, err = runtime.Push(ctx, "quay.io/libpod/alpine:latest", "dir:"+dirDest, pushOptions) require.NoError(t, err) // Pull uncompressed alpine from `dir:dirDest` as source. @@ -137,7 +137,7 @@ func TestPushWithForceCompression(t *testing.T) { pushOptions.OciAcceptUncompressedLayers = true pushOptions.Writer = os.Stdout ociDest := t.TempDir() - _, err = runtime.Push(ctx, "docker.io/library/alpine:latest", "oci:"+ociDest, pushOptions) + _, err = runtime.Push(ctx, "quay.io/libpod/alpine:latest", "oci:"+ociDest, pushOptions) require.NoError(t, err) // blobs from first push @@ -154,7 +154,7 @@ func TestPushWithForceCompression(t *testing.T) { pushOptions.Writer = os.Stdout pushOptions.CompressionFormat = &compression.Gzip pushOptions.ForceCompressionFormat = false - _, err = runtime.Push(ctx, "docker.io/library/alpine:latest", "oci:"+ociDest, pushOptions) + _, err = runtime.Push(ctx, "quay.io/libpod/alpine:latest", "oci:"+ociDest, pushOptions) require.NoError(t, err) // blobs from second push @@ -175,7 +175,7 @@ func TestPushWithForceCompression(t *testing.T) { pushOptions.Writer = os.Stdout pushOptions.CompressionFormat = &compression.Gzip pushOptions.ForceCompressionFormat = true - _, err = runtime.Push(ctx, "docker.io/library/alpine:latest", "oci:"+ociDest, pushOptions) + _, err = runtime.Push(ctx, "quay.io/libpod/alpine:latest", "oci:"+ociDest, pushOptions) require.NoError(t, err) // collect blobs from third push diff --git a/libimage/remove_test.go b/libimage/remove_test.go index e15b650ab..521444301 100644 --- a/libimage/remove_test.go +++ b/libimage/remove_test.go @@ -14,7 +14,7 @@ import ( func TestRemoveImages(t *testing.T) { // Note: this will resolve pull from the GCR registry (see // testdata/registries.conf). - busyboxLatest := "docker.io/library/busybox:latest" + busyboxLatest := "quay.io/libpod/busybox:latest" runtime := testNewRuntime(t) ctx := context.Background() diff --git a/libimage/runtime_test.go b/libimage/runtime_test.go index 300d43cee..48dd62ce6 100644 --- a/libimage/runtime_test.go +++ b/libimage/runtime_test.go @@ -109,8 +109,8 @@ func TestRuntimeListImagesAllImages(t *testing.T) { ctx := context.Background() // Prefetch alpine, busybox. - testRuntimePullImage(t, runtime, ctx, "docker.io/library/alpine:latest") - testRuntimePullImage(t, runtime, ctx, "docker.io/library/busybox:latest") + testRuntimePullImage(t, runtime, ctx, "quay.io/libpod/alpine:latest") + testRuntimePullImage(t, runtime, ctx, "quay.io/libpod/busybox:latest") images, err := runtime.ListImages(ctx, nil) require.NoError(t, err) @@ -122,7 +122,7 @@ func TestRuntimeListImagesAllImages(t *testing.T) { } assert.ElementsMatch(t, image_names, - []string{"docker.io/library/alpine:latest", "docker.io/library/busybox:latest"}, + []string{"quay.io/libpod/alpine:latest", "quay.io/libpod/busybox:latest"}, ) } @@ -131,15 +131,15 @@ func TestRuntimeListImagesByNames(t *testing.T) { ctx := context.Background() // Prefetch alpine, busybox. - testRuntimePullImage(t, runtime, ctx, "docker.io/library/alpine:latest") - testRuntimePullImage(t, runtime, ctx, "docker.io/library/busybox:latest") + testRuntimePullImage(t, runtime, ctx, "quay.io/libpod/alpine:latest") + testRuntimePullImage(t, runtime, ctx, "quay.io/libpod/busybox:latest") for _, test := range []struct { name string fullName string }{ - {"alpine", "docker.io/library/alpine:latest"}, - {"busybox", "docker.io/library/busybox:latest"}, + {"alpine", "quay.io/libpod/alpine:latest"}, + {"busybox", "quay.io/libpod/busybox:latest"}, } { images, err := runtime.ListImagesByNames([]string{test.name}) require.NoError(t, err) diff --git a/libimage/save_test.go b/libimage/save_test.go index 8bfa2dae5..ea40b8d60 100644 --- a/libimage/save_test.go +++ b/libimage/save_test.go @@ -19,9 +19,9 @@ func TestSave(t *testing.T) { // Prefetch alpine, busybox. pullOptions := &PullOptions{} pullOptions.Writer = os.Stdout - _, err := runtime.Pull(ctx, "docker.io/library/alpine:latest", config.PullPolicyAlways, pullOptions) + _, err := runtime.Pull(ctx, "quay.io/libpod/alpine:latest", config.PullPolicyAlways, pullOptions) require.NoError(t, err) - _, err = runtime.Pull(ctx, "docker.io/library/busybox:latest", config.PullPolicyAlways, pullOptions) + _, err = runtime.Pull(ctx, "quay.io/libpod/busybox:latest", config.PullPolicyAlways, pullOptions) require.NoError(t, err) // Save the two images into a multi-image archive. This way, we can From a76e706b729540123af042d503f69d9b8d9cc57d Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Wed, 27 Nov 2024 14:25:08 +0100 Subject: [PATCH 2/4] libnetwork/pasta: do not ignore ipv4 link local Starting with pasta 2024_11_27.c0fbc7e there is new "local mode"[1] in pasta that defaults to setting up link local addresses in the netns when no suitable interface was found. this is done to fix the podman issue[2] where we fail to start in these cases which was a poor UX. Now the pasta change alone works fine for these users but there is one problem. Podman adds hosts entries for the container ip/name tuple and for the host.containers.internal. These entries are filtered out thus neither ipv4 or ipv6 bool was set and no addresses where added to IPAddresses. Thus podman had no info to add entries and just left them empty, while for most cases this is fine there might be a few users who expect host.containers.internal and the container name to resolve correctly. This commit changes the logic to only skip ipv6 link local addresses but allow ipv4 link local addresses. With that podman will add the proper entry. [1] https://archives.passt.top/passt-dev/20241127042725.3133538-1-sbrivio@redhat.com/ [2] https://github.com/containers/podman/issues/24614 Signed-off-by: Paul Holzinger (cherry picked from commit 0b0b18e404abc35d67407725bc55786d8be0e6c8) --- libnetwork/pasta/pasta_linux.go | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/libnetwork/pasta/pasta_linux.go b/libnetwork/pasta/pasta_linux.go index 2ee6369ef..33fbc35e6 100644 --- a/libnetwork/pasta/pasta_linux.go +++ b/libnetwork/pasta/pasta_linux.go @@ -110,13 +110,26 @@ func Setup(opts *SetupOptions) (*SetupResult, error) { return err } for _, addr := range addrs { - // make sure to skip localhost and other special addresses - if ipnet, ok := addr.(*net.IPNet); ok && ipnet.IP.IsGlobalUnicast() { - result.IPAddresses = append(result.IPAddresses, ipnet.IP) - if !ipv4 && util.IsIPv4(ipnet.IP) { + // make sure to skip loopback and multicast addresses + if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && !ipnet.IP.IsMulticast() { + if util.IsIPv4(ipnet.IP) { + result.IPAddresses = append(result.IPAddresses, ipnet.IP) ipv4 = true - } - if !ipv6 && util.IsIPv6(ipnet.IP) { + } else if !ipnet.IP.IsLinkLocalUnicast() { + // Else must be ipv6. + // We shouldn't resolve hosts.containers.internal to IPv6 + // link-local addresses, for two reasons: + // 1. even if IPv6 is disabled in pasta (--ipv4-only), the + // kernel will configure an IPv6 link-local address in the + // container, but that doesn't mean that IPv6 connectivity + // is actually working + // 2. link-local addresses need to be suffixed by the zone + // (interface) to be of any use, but we can't do it here + // + // Thus, don't include IPv6 link-local addresses in + // IPAddresses: Podman uses them for /etc/hosts entries, and + // those need to be functional. + result.IPAddresses = append(result.IPAddresses, ipnet.IP) ipv6 = true } } From aefab141f3270418ebb49f1159a4d1b3739551bc Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Tue, 26 Nov 2024 14:51:47 +0100 Subject: [PATCH 3/4] pkg/ssh: fix windows path logic Using the path package is not correct on windows as it always defaults to the "/" as path separator. Instead one must use the filepath package. Fixes containers/podman#24616 Signed-off-by: Paul Holzinger (cherry picked from commit 512cfbd46fc0001e8053332960760a77b191d5a2) --- pkg/ssh/connection_golang.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/ssh/connection_golang.go b/pkg/ssh/connection_golang.go index c2b1265c3..0439354c4 100644 --- a/pkg/ssh/connection_golang.go +++ b/pkg/ssh/connection_golang.go @@ -10,7 +10,6 @@ import ( "net/url" "os" "os/user" - "path" "path/filepath" "regexp" "strings" @@ -313,7 +312,7 @@ func ValidateAndConfigure(uri *url.URL, iden string, insecureIsMachineConnection if !errors.Is(err, os.ErrNotExist) { return nil, err } - keyDir := path.Dir(keyFilePath) + keyDir := filepath.Dir(keyFilePath) if err := fileutils.Exists(keyDir); errors.Is(err, os.ErrNotExist) { if err := os.Mkdir(keyDir, 0o700); err != nil { return nil, err From 62b7d1246a046251c4e1d91efaa926b918ad4628 Mon Sep 17 00:00:00 2001 From: Dusty Mabe Date: Thu, 5 Dec 2024 11:56:12 -0500 Subject: [PATCH 4/4] spec: create/own /etc/containers/networks In some cases if /etc/ is mounted read-only the non-existence of the `/etc/containers/networks` directory will cause basic functionality to fail. ``` bash-5.2# mount --bind -o ro /etc/containers/ /etc/containers/ bash-5.2# podman info Error: mkdir /etc/containers/networks: read-only file system ``` Since it's going to get created anyway let's just have the directory exist from the beginning. Signed-off-by: Dusty Mabe (cherry picked from commit 9f2002baed0b72bf931a22ae169aa8f806313a5d) --- rpm/containers-common.spec | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rpm/containers-common.spec b/rpm/containers-common.spec index 125a1b62d..53725f92f 100644 --- a/rpm/containers-common.spec +++ b/rpm/containers-common.spec @@ -141,7 +141,7 @@ done %install # install config and policy files for registries -install -dp %{buildroot}%{_sysconfdir}/containers/{certs.d,oci/hooks.d,systemd} +install -dp %{buildroot}%{_sysconfdir}/containers/{certs.d,oci/hooks.d,networks,systemd} install -dp %{buildroot}%{_sharedstatedir}/containers/sigstore install -dp %{buildroot}%{_datadir}/containers/systemd install -dp %{buildroot}%{_prefix}/lib/containers/storage @@ -187,6 +187,7 @@ ln -s ../../../..%{_sysconfdir}/yum.repos.d/redhat.repo %{buildroot}%{_datadir}/ %files %dir %{_sysconfdir}/containers %dir %{_sysconfdir}/containers/certs.d +%dir %{_sysconfdir}/containers/networks %dir %{_sysconfdir}/containers/oci %dir %{_sysconfdir}/containers/oci/hooks.d %dir %{_sysconfdir}/containers/registries.conf.d