Skip to content

Commit

Permalink
Add e2e test for component filtering
Browse files Browse the repository at this point in the history
Signed-off-by: Kate Goldenring <kate.goldenring@fermyon.com>
  • Loading branch information
kate-goldenring committed Oct 31, 2024
1 parent 9668cab commit ffe4e66
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 14 deletions.
6 changes: 5 additions & 1 deletion config/crd/bases/core.spinoperator.dev_spinapps.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,11 @@ spec:
type: object
type: object
components:
description: Components to be executed in this group.
description: |-
Components of the app to execute.
If this is not provided all components are executed.
items:
type: string
minItems: 1
Expand Down
8 changes: 7 additions & 1 deletion config/manager/kustomization.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
resources:
- manager.yaml
- manager.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
images:
- name: ghcr.io/spinkube/spin-operator
newName: ghcr.io/spinkube/spin-operator
newTag: dev
90 changes: 90 additions & 0 deletions e2e/component_filtering_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package e2e

import (
"context"
"testing"
"time"

v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/e2e-framework/klient"
"sigs.k8s.io/e2e-framework/klient/wait"
"sigs.k8s.io/e2e-framework/klient/wait/conditions"
"sigs.k8s.io/e2e-framework/pkg/envconf"
"sigs.k8s.io/e2e-framework/pkg/features"

spinapps_v1alpha1 "github.com/spinkube/spin-operator/api/v1alpha1"
"github.com/spinkube/spin-operator/e2e/helper"
"github.com/stretchr/testify/require"
)

// TestComponentFiltering checks that the operator and shim have support for running a subset of a Spin app's components
func TestComponentFiltering(t *testing.T) {
var client klient.Client

// TODO: Use an image from a sample app in this repository
appImage := "ghcr.io/kate-goldenring/spin-operator/examples/spin-salutations:20241022-144454"
testSpinAppName := "test-component-filtering"

defaultTest := features.New("default and most minimal setup").
Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {

client = cfg.Client()

if err := spinapps_v1alpha1.AddToScheme(client.Resources(testNamespace).GetScheme()); err != nil {
t.Fatalf("failed to register the spinapps_v1alpha1 types with Kubernetes scheme: %s", err)
}

return ctx
}).
Assess("spin app custom resource is created", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
testSpinApp := newSpinAppCR(testSpinAppName, appImage, "containerd-shim-spin", []string{"hello"})

if err := client.Resources().Create(ctx, testSpinApp); err != nil {
t.Fatalf("Failed to create spinapp: %s", err)
}
return ctx
}).
Assess("spin app deployment and service are available", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
// wait for deployment to be ready
if err := wait.For(
conditions.New(client.Resources()).DeploymentAvailable(testSpinAppName, testNamespace),
wait.WithTimeout(3*time.Minute),
wait.WithInterval(time.Second),
); err != nil {
t.Fatal(err)
}

svc := &v1.ServiceList{
Items: []v1.Service{
{ObjectMeta: metav1.ObjectMeta{Name: testSpinAppName, Namespace: testNamespace}},
},
}

if err := wait.For(
conditions.New(client.Resources()).ResourcesFound(svc),
wait.WithTimeout(3*time.Minute),
wait.WithInterval(500*time.Millisecond),
); err != nil {
t.Fatal(err)
}
return ctx
}).
Assess("spin app is only serving hello component", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
helper.EnsureDebugContainer(t, ctx, cfg, testNamespace)

_, status, err := helper.CurlSpinApp(t, ctx, cfg, testNamespace, testSpinAppName, "/hi", "")

require.NoError(t, err)
require.Equal(t, 200, status)

_, status, err = helper.CurlSpinApp(t, ctx, cfg, testNamespace, testSpinAppName, "/bye", "")

require.NoError(t, err)
require.Equal(t, 404, status)

return ctx
}).
Feature()
testEnv.Test(t, defaultTest)
}
10 changes: 7 additions & 3 deletions e2e/default_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func TestDefaultSetup(t *testing.T) {
Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
client = cfg.Client()

testSpinApp := newSpinAppCR(testSpinAppName, helloWorldImage, "containerd-shim-spin")
testSpinApp := newSpinAppCR(testSpinAppName, helloWorldImage, "containerd-shim-spin", nil)
if err := client.Resources().Create(ctx, testSpinApp); err != nil {
t.Fatalf("Failed to create spinapp: %s", err)
}
Expand Down Expand Up @@ -69,8 +69,8 @@ func TestDefaultSetup(t *testing.T) {
testEnv.Test(t, defaultTest)
}

func newSpinAppCR(name, image, executor string) *spinapps_v1alpha1.SpinApp {
return &spinapps_v1alpha1.SpinApp{
func newSpinAppCR(name, image, executor string, components []string) *spinapps_v1alpha1.SpinApp {
app := spinapps_v1alpha1.SpinApp{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: testNamespace,
Expand All @@ -81,4 +81,8 @@ func newSpinAppCR(name, image, executor string) *spinapps_v1alpha1.SpinApp {
Executor: executor,
},
}
if components != nil {
app.Spec.Components = components
}
return &app
}
12 changes: 7 additions & 5 deletions e2e/helper/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,9 @@ func EnsureDebugContainer(t *testing.T, ctx context.Context, cfg *envconf.Config
}
}

// PostToSpinApp is a crude function for using the debug pod to post to a spin app
// within the cluster. It allows customization of the route, but all requests
// are currently `POST`.
func PostToSpinApp(t *testing.T, ctx context.Context, cfg *envconf.Config, namespace, spinAppName, route, body string) (string, int, error) {
// CurlSpinApp is a crude function for using the debug pod to send a HTTP request to a spin app
// within the cluster. It allows customization of the route, and all requests are GET requests unless a non-empty body is provided.
func CurlSpinApp(t *testing.T, ctx context.Context, cfg *envconf.Config, namespace, spinAppName, route, body string) (string, int, error) {
t.Helper()

client, err := cfg.NewClient()
Expand All @@ -71,7 +70,10 @@ func PostToSpinApp(t *testing.T, ctx context.Context, cfg *envconf.Config, names

podName := debugPod.Name

command := []string{"curl", "-s", "-m", "5", "-w", "\n%{http_code}\n", "http://" + spinAppName + "." + namespace + route, "--data", body, "-o", "-"}
command := []string{"curl", "--silent", "--max-time", "5", "--write-out", "\n%{http_code}\n", "http://" + spinAppName + "." + namespace + route, "--output", "-"}
if body != "" {
command = append(command, "--data", body)
}

var stdout, stderr bytes.Buffer
if err := client.Resources().ExecInPod(ctx, namespace, podName, debugDeploymentName, command, &stdout, &stderr); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion e2e/k3d_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"sigs.k8s.io/e2e-framework/support/utils"
)

const k3dImage = "ghcr.io/spinkube/containerd-shim-spin/k3d:v0.13.1"
const k3dImage = "ghcr.io/spinkube/containerd-shim-spin/k3d:20241015-215845-g71c8351"

var k3dBin = "k3d"

Expand Down
4 changes: 2 additions & 2 deletions e2e/redis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func TestShimRedis(t *testing.T) {
Assess("spin app is using redis", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
helper.EnsureDebugContainer(t, ctx, cfg, testNamespace)

_, status, err := helper.PostToSpinApp(t, ctx, cfg, testNamespace, testSpinAppName, "/api", "{\"key\": \"foo\", \"value\": \"bar\"}")
_, status, err := helper.CurlSpinApp(t, ctx, cfg, testNamespace, testSpinAppName, "/api", "{\"key\": \"foo\", \"value\": \"bar\"}")

require.NoError(t, err)
require.Equal(t, 200, status)
Expand Down Expand Up @@ -194,7 +194,7 @@ func TestSpintainerRedis(t *testing.T) {
Assess("spin app is using redis", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
helper.EnsureDebugContainer(t, ctx, cfg, testNamespace)

_, status, err := helper.PostToSpinApp(t, ctx, cfg, testNamespace, testSpinAppName, "/api", "{\"key\": \"foo\", \"value\": \"bar\"}")
_, status, err := helper.CurlSpinApp(t, ctx, cfg, testNamespace, testSpinAppName, "/api", "{\"key\": \"foo\", \"value\": \"bar\"}")

require.NoError(t, err)
require.Equal(t, 200, status)
Expand Down
2 changes: 1 addition & 1 deletion e2e/spintainer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func TestSpintainer(t *testing.T) {
return ctx
}).
Assess("spin app custom resource is created", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
testSpinApp := newSpinAppCR(testSpinAppName, helloWorldImage, "spintainer")
testSpinApp := newSpinAppCR(testSpinAppName, helloWorldImage, "spintainer", nil)

if err := client.Resources().Create(ctx, newSpintainerExecutor(testNamespace)); controllerruntimeclient.IgnoreAlreadyExists(err) != nil {
t.Fatalf("Failed to create spinappexecutor: %s", err)
Expand Down

0 comments on commit ffe4e66

Please sign in to comment.