|
6 | 6 | "testing" |
7 | 7 | "time" |
8 | 8 |
|
| 9 | + "github.com/containerd/platforms" |
9 | 10 | "github.com/stretchr/testify/require" |
10 | 11 | corev1 "k8s.io/api/core/v1" |
11 | 12 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
@@ -39,17 +40,134 @@ func Test_LoadImages(t *testing.T) { |
39 | 40 | provider, err := testcontainers.ProviderDocker.GetProvider() |
40 | 41 | require.NoError(t, err) |
41 | 42 |
|
| 43 | + dockerProvider, _ := provider.(*testcontainers.DockerProvider) |
| 44 | + |
| 45 | + // This function only works for single architecture images |
| 46 | + // Forces the test to use a single-arch version of the image |
| 47 | + arch := platforms.DefaultSpec().Architecture |
| 48 | + if platforms.DefaultSpec().Variant != "" { |
| 49 | + arch += platforms.DefaultSpec().Variant |
| 50 | + } |
| 51 | + nginxImg := arch + "/nginx" |
| 52 | + |
42 | 53 | // ensure nginx image is available locally |
43 | | - err = provider.PullImage(ctx, "nginx") |
| 54 | + err = provider.PullImage(ctx, nginxImg) |
44 | 55 | require.NoError(t, err) |
45 | 56 |
|
46 | 57 | t.Run("Test load image not available", func(t *testing.T) { |
47 | 58 | err := k3sContainer.LoadImages(ctx, "fake.registry/fake:non-existing") |
48 | 59 | require.Error(t, err) |
49 | 60 | }) |
50 | 61 |
|
| 62 | + t.Run("Test load image with wrong architecture", func(t *testing.T) { |
| 63 | + p, _ := platforms.Parse("linux/s390x") |
| 64 | + img := "nginx:mainline" |
| 65 | + err = dockerProvider.PullImageWithOpts(ctx, img, testcontainers.PullDockerImageWithPlatform(p)) |
| 66 | + require.NoError(t, err) |
| 67 | + |
| 68 | + err := k3sContainer.LoadImages(ctx, img) |
| 69 | + require.Error(t, err) |
| 70 | + require.Regexp(t, "content digest .* not found", err) |
| 71 | + }) |
| 72 | + |
| 73 | + t.Run("Test load image in cluster", func(t *testing.T) { |
| 74 | + err := k3sContainer.LoadImages(ctx, nginxImg) |
| 75 | + require.NoError(t, err) |
| 76 | + |
| 77 | + pod := &corev1.Pod{ |
| 78 | + TypeMeta: metav1.TypeMeta{ |
| 79 | + Kind: "Pod", |
| 80 | + APIVersion: "v1", |
| 81 | + }, |
| 82 | + ObjectMeta: metav1.ObjectMeta{ |
| 83 | + Name: "test-pod", |
| 84 | + }, |
| 85 | + Spec: corev1.PodSpec{ |
| 86 | + Containers: []corev1.Container{ |
| 87 | + { |
| 88 | + Name: "nginx", |
| 89 | + Image: nginxImg, |
| 90 | + ImagePullPolicy: corev1.PullNever, // use image only if already present |
| 91 | + }, |
| 92 | + }, |
| 93 | + }, |
| 94 | + } |
| 95 | + |
| 96 | + _, err = k8s.CoreV1().Pods("default").Create(ctx, pod, metav1.CreateOptions{}) |
| 97 | + require.NoError(t, err) |
| 98 | + |
| 99 | + err = kwait.PollUntilContextCancel(ctx, time.Second, true, func(ctx context.Context) (bool, error) { |
| 100 | + state, err := getTestPodState(ctx, k8s) |
| 101 | + if err != nil { |
| 102 | + return false, err |
| 103 | + } |
| 104 | + if state.Terminated != nil { |
| 105 | + return false, fmt.Errorf("pod terminated: %v", state.Terminated) |
| 106 | + } |
| 107 | + return state.Running != nil, nil |
| 108 | + }) |
| 109 | + require.NoError(t, err) |
| 110 | + |
| 111 | + state, err := getTestPodState(ctx, k8s) |
| 112 | + require.NoError(t, err) |
| 113 | + require.NotNil(t, state.Running) |
| 114 | + }) |
| 115 | +} |
| 116 | + |
| 117 | +func Test_LoadImagesWithPlatform(t *testing.T) { |
| 118 | + // Give up to three minutes to run this test |
| 119 | + ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(3*time.Minute)) |
| 120 | + defer cancel() |
| 121 | + |
| 122 | + k3sContainer, err := k3s.Run(ctx, "rancher/k3s:v1.27.1-k3s1") |
| 123 | + testcontainers.CleanupContainer(t, k3sContainer) |
| 124 | + require.NoError(t, err) |
| 125 | + |
| 126 | + kubeConfigYaml, err := k3sContainer.GetKubeConfig(ctx) |
| 127 | + require.NoError(t, err) |
| 128 | + |
| 129 | + restcfg, err := clientcmd.RESTConfigFromKubeConfig(kubeConfigYaml) |
| 130 | + require.NoError(t, err) |
| 131 | + |
| 132 | + k8s, err := kubernetes.NewForConfig(restcfg) |
| 133 | + require.NoError(t, err) |
| 134 | + |
| 135 | + provider, err := testcontainers.ProviderDocker.GetProvider() |
| 136 | + require.NoError(t, err) |
| 137 | + |
| 138 | + dockerProvider, _ := provider.(*testcontainers.DockerProvider) |
| 139 | + |
| 140 | + // ensure nginx image is available locally |
| 141 | + err = provider.PullImage(ctx, "nginx") |
| 142 | + require.NoError(t, err) |
| 143 | + |
| 144 | + t.Run("Test load image not available", func(t *testing.T) { |
| 145 | + p, _ := platforms.Parse("linux/amd64") |
| 146 | + err := k3sContainer.LoadImagesWithPlatform(ctx, []string{"fake.registry/fake:non-existing"}, &p) |
| 147 | + require.Error(t, err) |
| 148 | + }) |
| 149 | + |
| 150 | + t.Run("Test load image with wrong architecture", func(t *testing.T) { |
| 151 | + pullPlatform, _ := platforms.Parse("linux/s390x") |
| 152 | + img := "nginx:mainline" |
| 153 | + err = dockerProvider.PullImageWithOpts(ctx, img, testcontainers.PullDockerImageWithPlatform(pullPlatform)) |
| 154 | + require.NoError(t, err) |
| 155 | + |
| 156 | + loadPlatform, _ := platforms.Parse("linux/amd64") |
| 157 | + err := k3sContainer.LoadImagesWithPlatform(ctx, []string{img}, &loadPlatform) |
| 158 | + require.Error(t, err) |
| 159 | + expected := fmt.Sprintf( |
| 160 | + "image with reference %s was found but does not provide the specified platform (%s)", |
| 161 | + img, |
| 162 | + platforms.Format(loadPlatform), |
| 163 | + ) |
| 164 | + require.Contains(t, err.Error(), expected) |
| 165 | + }) |
| 166 | + |
51 | 167 | t.Run("Test load image in cluster", func(t *testing.T) { |
52 | | - err := k3sContainer.LoadImages(ctx, "nginx") |
| 168 | + p := platforms.DefaultSpec() |
| 169 | + p.OS = "linux" |
| 170 | + err := k3sContainer.LoadImagesWithPlatform(ctx, []string{"nginx"}, &p) |
53 | 171 | require.NoError(t, err) |
54 | 172 |
|
55 | 173 | pod := &corev1.Pod{ |
|
0 commit comments