diff --git a/Makefile b/Makefile index d2d2d00da..df0607eb0 100644 --- a/Makefile +++ b/Makefile @@ -277,9 +277,8 @@ test-e2e: WORK_DIR ?= . test-e2e: WHAT ?= ./test/e2e... test-e2e: $(KCP) $(DEX) build ## Run e2e tests mkdir .kcp - $(MAKE) run-dex 2>&1 & DEX_PID=$$!; \ $(MAKE) run-kcp &>.kcp/kcp.log & KCP_PID=$$!; \ - trap 'kill -TERM $$DEX_PID $$KCP_PID; rm -rf .kcp' TERM INT EXIT && \ + trap 'kill -TERM $$KCP_PID; rm -rf .kcp' TERM INT EXIT && \ echo "Waiting for kcp to be ready (check .kcp/kcp.log)." && while ! KUBECONFIG=.kcp/admin.kubeconfig kubectl get --raw /readyz &>/dev/null; do sleep 1; echo -n "."; done && echo && \ KUBECONFIG=$$PWD/.kcp/admin.kubeconfig GOOS=$(OS) GOARCH=$(ARCH) $(GO_TEST) -race -count $(COUNT) -p $(E2E_PARALLELISM) -parallel $(E2E_PARALLELISM) $(WHAT) $(TEST_ARGS) diff --git a/test/e2e/bind/happy-case_test.go b/test/e2e/bind/happy-case_test.go index 97e03b76e..39a442415 100644 --- a/test/e2e/bind/happy-case_test.go +++ b/test/e2e/bind/happy-case_test.go @@ -59,6 +59,8 @@ func testHappyCase(t *testing.T, resourceScope apiextensionsv1.ResourceScope, in ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) + framework.StartDex(t) + t.Logf("Creating provider workspace") providerConfig, providerKubeconfig := framework.NewWorkspace(t, framework.ClientConfig(t), framework.WithGenerateName("test-happy-case-provider")) diff --git a/test/e2e/framework/backend.go b/test/e2e/framework/backend.go index 135bf84e7..baa19d230 100644 --- a/test/e2e/framework/backend.go +++ b/test/e2e/framework/backend.go @@ -19,17 +19,12 @@ package framework import ( "context" "encoding/base64" - "fmt" "net" "testing" - "time" - dexapi "github.com/dexidp/dex/api/v2" "github.com/gorilla/securecookie" "github.com/spf13/pflag" "github.com/stretchr/testify/require" - "google.golang.org/grpc" - grpcinsecure "google.golang.org/grpc/credentials/insecure" apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/rest" @@ -85,7 +80,7 @@ func StartBackendWithoutDefaultArgs(t *testing.T, clientConfig *rest.Config, arg require.NoError(t, err) opts.OIDC.IssuerClientID = "kube-bind-" + port - createDexClient(t, addr) + CreateDexClient(t, addr) opts.ExtraOptions.TestingSkipNameValidation = true opts.ExtraOptions.SchemaSource = options.CustomResourceDefinitionSource.String() @@ -105,35 +100,3 @@ func StartBackendWithoutDefaultArgs(t *testing.T, clientConfig *rest.Config, arg return addr, server } - -func createDexClient(t *testing.T, addr net.Addr) { - ctx, cancel := context.WithCancel(context.Background()) - t.Cleanup(cancel) - - _, port, err := net.SplitHostPort(addr.String()) - require.NoError(t, err) - conn, err := grpc.NewClient("127.0.0.1:5557", grpc.WithTransportCredentials(grpcinsecure.NewCredentials())) - require.NoError(t, err) - defer conn.Close() - client := dexapi.NewDexClient(conn) - - _, err = client.CreateClient(ctx, &dexapi.CreateClientReq{ - Client: &dexapi.Client{ - Id: "kube-bind-" + port, - Secret: "ZXhhbXBsZS1hcHAtc2VjcmV0", - RedirectUris: []string{fmt.Sprintf("http://%s/callback", addr)}, - Public: true, - Name: "kube-bind on port " + port, - }, - }) - require.NoError(t, err) - - t.Cleanup(func() { - ctx, cancel := context.WithDeadline(context.Background(), metav1.Now().Add(10*time.Second)) - defer cancel() - conn, err := grpc.NewClient("127.0.0.1:5557", grpc.WithTransportCredentials(grpcinsecure.NewCredentials())) - require.NoError(t, err) - _, err = dexapi.NewDexClient(conn).DeleteClient(ctx, &dexapi.DeleteClientReq{Id: "kube-bind-" + port}) - require.NoError(t, err) - }) -} diff --git a/test/e2e/framework/dex.go b/test/e2e/framework/dex.go new file mode 100644 index 000000000..3ea90b4c3 --- /dev/null +++ b/test/e2e/framework/dex.go @@ -0,0 +1,112 @@ +/* +Copyright 2025 The Kube Bind Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package framework + +import ( + "context" + "fmt" + "net" + "net/http" + "os" + "os/exec" + "path/filepath" + "sync" + "syscall" + "testing" + "time" + + dexapi "github.com/dexidp/dex/api/v2" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" + grpcinsecure "google.golang.org/grpc/credentials/insecure" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" +) + +var dexOnce sync.Once + +func StartDex(t testing.TB) { + t.Helper() + + dexOnce.Do(func() { + dexConfig := os.Getenv("DEX_CONFIG") + if dexConfig == "" { + dexConfig = filepath.Clean(filepath.Join(WorkDir, "..", "hack", "dex-config-dev.yaml")) + } + + t.Logf("Starting dex with config %q", dexConfig) + + dexCmd := exec.Command( + "dex", + "serve", + dexConfig, + ) + + // Ensures that dex is killed when the process ends. + dexCmd.SysProcAttr = &syscall.SysProcAttr{ + Pdeathsig: syscall.SIGKILL, + Setpgid: true, + Pgid: 0, + } + + require.NoError(t, dexCmd.Start()) + }) + + t.Log("Wait for Dex to be ready") + req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "http://127.0.0.1:5556/dex/.well-known/openid-configuration", nil) + require.NoError(t, err) + require.Eventually(t, func() bool { + resp, err := http.DefaultClient.Do(req) + if err != nil { + return false + } + defer resp.Body.Close() + return resp.StatusCode == http.StatusOK + }, wait.ForeverTestTimeout, time.Millisecond*100) + t.Log("Dex is ready") +} + +func CreateDexClient(t testing.TB, addr net.Addr) { + t.Helper() + + _, port, err := net.SplitHostPort(addr.String()) + require.NoError(t, err) + conn, err := grpc.NewClient("127.0.0.1:5557", grpc.WithTransportCredentials(grpcinsecure.NewCredentials())) + require.NoError(t, err) + defer conn.Close() + client := dexapi.NewDexClient(conn) + + _, err = client.CreateClient(t.Context(), &dexapi.CreateClientReq{ + Client: &dexapi.Client{ + Id: "kube-bind-" + port, + Secret: "ZXhhbXBsZS1hcHAtc2VjcmV0", + RedirectUris: []string{fmt.Sprintf("http://%s/callback", addr)}, + Public: true, + Name: "kube-bind on port " + port, + }, + }) + require.NoError(t, err) + + t.Cleanup(func() { + ctx, cancel := context.WithDeadline(context.Background(), metav1.Now().Add(10*time.Second)) + defer cancel() + conn, err := grpc.NewClient("127.0.0.1:5557", grpc.WithTransportCredentials(grpcinsecure.NewCredentials())) + require.NoError(t, err) + _, err = dexapi.NewDexClient(conn).DeleteClient(ctx, &dexapi.DeleteClientReq{Id: "kube-bind-" + port}) + require.NoError(t, err) + }) +}