From 7fbf89084d267d35e1fe761cc853328826fc00f4 Mon Sep 17 00:00:00 2001 From: Pablo Chacin <pablochacin@gmail.com> Date: Sat, 2 Mar 2024 15:42:09 +0100 Subject: [PATCH 1/3] Add WithManifest option to k3s Signed-off-by: Pablo Chacin <pablochacin@gmail.com> --- docs/modules/k3s.md | 14 ++++++++++++++ modules/k3s/k3s.go | 31 +++++++++++++++++++++++++++++++ modules/k3s/k3s_test.go | 21 +++++++++++++++++++++ modules/k3s/nginx-manifest.yaml | 14 ++++++++++++++ 4 files changed, 80 insertions(+) create mode 100644 modules/k3s/nginx-manifest.yaml diff --git a/docs/modules/k3s.md b/docs/modules/k3s.md index 3e448b8e45..c6edd0d255 100644 --- a/docs/modules/k3s.md +++ b/docs/modules/k3s.md @@ -49,6 +49,20 @@ for K3s. E.g. `testcontainers.WithImage("docker.io/rancher/k3s:v1.27.1-k3s1")`. {% include "../features/common_functional_options.md" %} +## WithManifest + +The `WithManifest` option loads a manifest obtained from a local file into the cluster. K3s applies it automatically during the startup process + +```golang +func WithManifest(manifestPath string) testcontainers.CustomizeRequestOption +``` + +Example: + +```golang + WithManifest("nginx-manifest.yaml") +``` + ### Container Methods The K3s container exposes the following methods: diff --git a/modules/k3s/k3s.go b/modules/k3s/k3s.go index 0f7ccb4d16..f851ed92f9 100644 --- a/modules/k3s/k3s.go +++ b/modules/k3s/k3s.go @@ -29,6 +29,37 @@ type K3sContainer struct { testcontainers.Container } +// path to the k3s manifests directory +const k3sManifests = "/var/lib/rancher/k3s/server/manifests/" + +// WithManifest loads the manifest into the cluster. K3s applies it automatically during the startup process +func WithManifest(manifestPath string) testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) { + manifest := filepath.Base(manifestPath) + target := k3sManifests + manifest + + // Add a post start hook to copy the manifest. + // We cannot use the Files option in the GenericRequest because the target + // path is created when the container starts + manifestHook := testcontainers.ContainerLifecycleHooks{ + PostStarts: []testcontainers.ContainerHook{ + func(ctx context.Context, c testcontainers.Container) error { + // if this hook is executed too soon after the container starts, + // the manifests directory may not exists yet, so we try to create it here + _, _, err := c.Exec(ctx, []string{"mkdir","-p", k3sManifests}) + if err != nil { + return err + } + + // copy the manifest + return c.CopyFileToContainer(ctx, manifest, target, 0x644) + }, + }, + } + req.LifecycleHooks = append(req.LifecycleHooks, manifestHook) + } +} + // RunContainer creates an instance of the K3s container type func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*K3sContainer, error) { host, err := getContainerHost(ctx, opts...) diff --git a/modules/k3s/k3s_test.go b/modules/k3s/k3s_test.go index 65510c037c..2a91a335ec 100644 --- a/modules/k3s/k3s_test.go +++ b/modules/k3s/k3s_test.go @@ -12,6 +12,7 @@ import ( "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/k3s" + "github.com/testcontainers/testcontainers-go/wait" ) func Test_LoadImages(t *testing.T) { @@ -161,3 +162,23 @@ func Test_APIServerReady(t *testing.T) { t.Fatalf("failed to create pod %v", err) } } + +func Test_WithManifestOption(t *testing.T) { + ctx := context.Background() + + k3sContainer, err := k3s.RunContainer(ctx, + testcontainers.WithImage("docker.io/rancher/k3s:v1.27.1-k3s1"), + k3s.WithManifest("nginx-manifest.yaml"), + testcontainers.WithWaitStrategy(wait.ForExec([]string{"kubectl", "wait", "pod", "nginx","--for=condition=Ready"})), + ) + if err != nil { + t.Fatal(err) + } + + // Clean up the container + defer func() { + if err := k3sContainer.Terminate(ctx); err != nil { + t.Fatal(err) + } + }() +} diff --git a/modules/k3s/nginx-manifest.yaml b/modules/k3s/nginx-manifest.yaml new file mode 100644 index 0000000000..fd552a1a24 --- /dev/null +++ b/modules/k3s/nginx-manifest.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + labels: + run: pod + name: nginx + namespace: default +spec: + containers: + - name: pod + image: nginx + imagePullPolicy: Always + + \ No newline at end of file From f38071d12e5243ce98114cfe9e957181391dd232 Mon Sep 17 00:00:00 2001 From: pablochacin <pablochacin@gmail.com> Date: Tue, 5 Mar 2024 17:06:34 +0100 Subject: [PATCH 2/3] Use new copy file feature to copy manifest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Manuel de la Peña <social.mdelapenya@gmail.com> --- modules/k3s/k3s.go | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/modules/k3s/k3s.go b/modules/k3s/k3s.go index f851ed92f9..bb0d78021c 100644 --- a/modules/k3s/k3s.go +++ b/modules/k3s/k3s.go @@ -38,26 +38,10 @@ func WithManifest(manifestPath string) testcontainers.CustomizeRequestOption { manifest := filepath.Base(manifestPath) target := k3sManifests + manifest - // Add a post start hook to copy the manifest. - // We cannot use the Files option in the GenericRequest because the target - // path is created when the container starts - manifestHook := testcontainers.ContainerLifecycleHooks{ - PostStarts: []testcontainers.ContainerHook{ - func(ctx context.Context, c testcontainers.Container) error { - // if this hook is executed too soon after the container starts, - // the manifests directory may not exists yet, so we try to create it here - _, _, err := c.Exec(ctx, []string{"mkdir","-p", k3sManifests}) - if err != nil { - return err - } - - // copy the manifest - return c.CopyFileToContainer(ctx, manifest, target, 0x644) - }, - }, - } - req.LifecycleHooks = append(req.LifecycleHooks, manifestHook) - } + req.Files = append(req.Files, testcontainers.ContainerFile{ + HostFilePath: manifestPath, + ContainerFilePath: target, + }) } // RunContainer creates an instance of the K3s container type From eb1d29f170c6e40d5e1396739c206f5d5e8cf111 Mon Sep 17 00:00:00 2001 From: Pablo Chacin <pablochacin@gmail.com> Date: Tue, 5 Mar 2024 17:10:31 +0100 Subject: [PATCH 3/3] Fix missing bracket Signed-off-by: Pablo Chacin <pablochacin@gmail.com> --- modules/k3s/k3s.go | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/k3s/k3s.go b/modules/k3s/k3s.go index bb0d78021c..83fdde4338 100644 --- a/modules/k3s/k3s.go +++ b/modules/k3s/k3s.go @@ -42,6 +42,7 @@ func WithManifest(manifestPath string) testcontainers.CustomizeRequestOption { HostFilePath: manifestPath, ContainerFilePath: target, }) + } } // RunContainer creates an instance of the K3s container type