forked from testcontainers/testcontainers-go
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: support for loading images in the K3s module (testcontainers#1622)
* Add image helpers Signed-off-by: Pablo Chacin <[email protected]> * Add LoadImages function Signed-off-by: Pablo Chacin <[email protected]> * Document k3s LoadImages method Signed-off-by: Pablo Chacin <[email protected]> * Apply suggestions from code review Co-authored-by: Manuel de la Peña <[email protected]> * Fix filepath import Signed-off-by: Pablo Chacin <[email protected]> * Fix runnable example package Signed-off-by: Pablo Chacin <[email protected]> * Apply suggestions from code review Co-authored-by: Manuel de la Peña <[email protected]> * Fix linter isues Signed-off-by: Pablo Chacin <[email protected]> * Fix k3s import Signed-off-by: Pablo Chacin <[email protected]> * Simplify LoadImage API Signed-off-by: Pablo Chacin <[email protected]> * Fix panin in test Signed-off-by: Pablo Chacin <[email protected]> * Re-introduce LoadImages documentation Signed-off-by: Pablo Chacin <[email protected]> --------- Signed-off-by: Pablo Chacin <[email protected]> Co-authored-by: Manuel de la Peña <[email protected]>
- Loading branch information
1 parent
a285e86
commit 7daf178
Showing
7 changed files
with
318 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package testcontainers | ||
|
||
import ( | ||
"context" | ||
) | ||
|
||
// ImageInfo represents a summary information of an image | ||
type ImageInfo struct { | ||
ID string | ||
Name string | ||
} | ||
|
||
// ImageProvider allows manipulating images | ||
type ImageProvider interface { | ||
ListImages(context.Context) ([]ImageInfo, error) | ||
SaveImages(context.Context, string, ...string) error | ||
PullImage(context.Context, string) error | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package testcontainers | ||
|
||
import ( | ||
"context" | ||
"os" | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/testcontainers/testcontainers-go/internal/testcontainersdocker" | ||
) | ||
|
||
func TestImageList(t *testing.T) { | ||
t.Setenv("DOCKER_HOST", testcontainersdocker.ExtractDockerHost(context.Background())) | ||
|
||
provider, err := ProviderDocker.GetProvider() | ||
if err != nil { | ||
t.Fatalf("failed to get provider %v", err) | ||
} | ||
|
||
defer func() { | ||
_ = provider.Close() | ||
}() | ||
|
||
req := ContainerRequest{ | ||
Image: "redis:latest", | ||
} | ||
|
||
container, err := provider.CreateContainer(context.Background(), req) | ||
if err != nil { | ||
t.Fatalf("creating test container %v", err) | ||
} | ||
|
||
defer func() { | ||
_ = container.Terminate(context.Background()) | ||
}() | ||
|
||
images, err := provider.ListImages(context.Background()) | ||
if err != nil { | ||
t.Fatalf("listing images %v", err) | ||
} | ||
|
||
if len(images) == 0 { | ||
t.Fatal("no images retrieved") | ||
} | ||
|
||
// look if the list contains the container image | ||
for _, img := range images { | ||
if img.Name == req.Image { | ||
return | ||
} | ||
} | ||
|
||
t.Fatalf("expected image not found: %s", req.Image) | ||
} | ||
|
||
func TestSaveImages(t *testing.T) { | ||
t.Setenv("DOCKER_HOST", testcontainersdocker.ExtractDockerHost(context.Background())) | ||
|
||
provider, err := ProviderDocker.GetProvider() | ||
if err != nil { | ||
t.Fatalf("failed to get provider %v", err) | ||
} | ||
|
||
defer func() { | ||
_ = provider.Close() | ||
}() | ||
|
||
req := ContainerRequest{ | ||
Image: "redis:latest", | ||
} | ||
|
||
container, err := provider.CreateContainer(context.Background(), req) | ||
if err != nil { | ||
t.Fatalf("creating test container %v", err) | ||
} | ||
|
||
defer func() { | ||
_ = container.Terminate(context.Background()) | ||
}() | ||
|
||
output := filepath.Join(t.TempDir(), "images.tar") | ||
err = provider.SaveImages(context.Background(), output, req.Image) | ||
if err != nil { | ||
t.Fatalf("saving image %q: %v", req.Image, err) | ||
} | ||
|
||
info, err := os.Stat(output) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if info.Size() == 0 { | ||
t.Fatalf("output file is empty") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package k3s_test | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
"time" | ||
|
||
corev1 "k8s.io/api/core/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/client-go/kubernetes" | ||
"k8s.io/client-go/tools/clientcmd" | ||
|
||
"github.com/testcontainers/testcontainers-go" | ||
"github.com/testcontainers/testcontainers-go/modules/k3s" | ||
"github.com/testcontainers/testcontainers-go/wait" | ||
) | ||
|
||
func Test_LoadImages(t *testing.T) { | ||
ctx := context.Background() | ||
|
||
k3sContainer, err := k3s.RunContainer(ctx, | ||
testcontainers.WithImage("docker.io/rancher/k3s:v1.27.1-k3s1"), | ||
testcontainers.WithWaitStrategy(wait.ForLog(".*Node controller sync successful.*").AsRegexp()), | ||
) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
// Clean up the container | ||
defer func() { | ||
if err := k3sContainer.Terminate(ctx); err != nil { | ||
t.Fatal(err) | ||
} | ||
}() | ||
|
||
kubeConfigYaml, err := k3sContainer.GetKubeConfig(ctx) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
restcfg, err := clientcmd.RESTConfigFromKubeConfig(kubeConfigYaml) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
k8s, err := kubernetes.NewForConfig(restcfg) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
provider, err := testcontainers.ProviderDocker.GetProvider() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
// ensure nginx image is available locally | ||
err = provider.PullImage(context.Background(), "nginx") | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
t.Run("Test load image not available", func(t *testing.T) { | ||
err := k3sContainer.LoadImages(context.Background(), "fake.registry/fake:non-existing") | ||
if err == nil { | ||
t.Fatal("should had failed") | ||
} | ||
}) | ||
|
||
t.Run("Test load image in cluster", func(t *testing.T) { | ||
err := k3sContainer.LoadImages(context.Background(), "nginx") | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
pod := &corev1.Pod{ | ||
TypeMeta: metav1.TypeMeta{ | ||
Kind: "Pod", | ||
APIVersion: "v1", | ||
}, | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "test-pod", | ||
}, | ||
Spec: corev1.PodSpec{ | ||
Containers: []corev1.Container{ | ||
{ | ||
Name: "nginx", | ||
Image: "nginx", | ||
ImagePullPolicy: corev1.PullNever, // use image only if already present | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
_, err = k8s.CoreV1().Pods("default").Create(context.Background(), pod, metav1.CreateOptions{}) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
time.Sleep(1 * time.Second) | ||
pod, err = k8s.CoreV1().Pods("default").Get(context.Background(), "test-pod", metav1.GetOptions{}) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
waiting := pod.Status.ContainerStatuses[0].State.Waiting | ||
if waiting != nil && waiting.Reason == "ErrImageNeverPull" { | ||
t.Fatal("Image was not loaded") | ||
} | ||
}) | ||
} |