1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
package daemon
import (
"context"
"errors"
"testing"
"github.com/containerd/platforms"
"github.com/docker/docker/container"
"github.com/docker/docker/image"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"gotest.tools/v3/assert"
)
type mockPlatformReader struct{}
func (m mockPlatformReader) ReadPlatformFromImage(ctx context.Context, id image.ID) (ocispec.Platform, error) {
switch id {
case "multiplatform":
// This image has multiple platforms, but GetImage will prefer the first one
// because the ID points to the full image index, not a specific platform.
return platforms.DefaultSpec(), nil
case "linux/arm64/v8":
return ocispec.Platform{
OS: "linux",
Architecture: "arm64",
Variant: "v8",
}, nil
case "linux/amd64":
return ocispec.Platform{
OS: "linux",
Architecture: "amd64",
}, nil
case "windows/amd64":
return ocispec.Platform{
OS: "windows",
Architecture: "amd64",
}, nil
default:
return ocispec.Platform{}, errors.New("image not found")
}
}
func (m mockPlatformReader) ReadPlatformFromConfigByImageManifest(ctx context.Context, desc ocispec.Descriptor) (ocispec.Platform, error) {
return m.ReadPlatformFromImage(ctx, image.ID(desc.Digest))
}
//nolint:staticcheck // ignore SA1019 because we are testing deprecated field migration
func TestContainerMigrateOS(t *testing.T) {
type Container = container.Container
var mock mockPlatformReader
// ImageManifest is nil for containers created with graphdrivers image store
var graphdrivers *ocispec.Descriptor = nil
for _, tc := range []struct {
name string
ctr Container
expected ocispec.Platform
}{
{
name: "gd pre-OS container",
ctr: Container{
ImageManifest: graphdrivers,
OS: "",
},
expected: platforms.DefaultSpec(),
},
{
name: "gd with linux arm64 image",
ctr: Container{
ImageManifest: graphdrivers,
ImageID: "linux/arm64/v8",
OS: "linux",
},
expected: ocispec.Platform{
OS: "linux",
Architecture: "arm64",
Variant: "v8",
},
},
{
name: "gd with windows image",
ctr: Container{
ImageManifest: graphdrivers,
ImageID: "windows/amd64",
OS: "windows",
},
expected: ocispec.Platform{
OS: "windows",
Architecture: "amd64",
},
},
{
name: "gd with an image thats no longer available",
ctr: Container{
ImageManifest: graphdrivers,
ImageID: "notfound",
OS: "linux",
},
expected: platforms.Platform{
OS: "linux",
},
},
{
name: "c8d with linux arm64 image",
ctr: Container{
ImageManifest: &ocispec.Descriptor{
Digest: "linux/arm64/v8",
},
OS: "linux",
ImageID: "linux/arm64/v8",
},
expected: ocispec.Platform{
OS: "linux",
Architecture: "arm64",
Variant: "v8",
},
},
{
name: "c8d with an image thats no longer available",
ctr: Container{
ImageManifest: &ocispec.Descriptor{
Digest: "notfound",
},
OS: "linux",
ImageID: "notfound",
},
expected: platforms.Platform{
OS: "linux",
},
},
{
name: "c8d with ImageManifest that is no longer available",
ctr: Container{
ImageManifest: &ocispec.Descriptor{
Digest: "notfound",
},
OS: "linux",
ImageID: "multiplatform",
},
// Note: This might produce unexpected results, because if the platform-specific manifest
// is not available, and the ImageID points to a multi-platform image, then GetImage will
// return any available platform with host platform being the priority.
// So it will just use whatever platform is returned by GetImage (docker image inspect).
expected: platforms.DefaultSpec(),
},
{
name: "ImageManifest has priority over ImageID migration",
ctr: Container{
ImageManifest: &ocispec.Descriptor{
Digest: "linux/arm64/v8",
},
OS: "linux",
ImageID: "linux/amd64",
},
expected: ocispec.Platform{
OS: "linux",
Architecture: "arm64",
Variant: "v8",
},
},
} {
ctr := tc.ctr
t.Run(tc.name, func(t *testing.T) {
migrateContainerOS(context.Background(), mock, &ctr)
assert.DeepEqual(t, tc.expected, ctr.ImagePlatform)
})
}
}
|