diff --git a/go.mod b/go.mod index fcce71265..4eed2cc25 100644 --- a/go.mod +++ b/go.mod @@ -31,6 +31,10 @@ require ( sigs.k8s.io/controller-runtime v0.13.0 ) +replace github.com/codeready-toolchain/api => github.com/xcoulon/api v0.0.0-20240725145329-0fc7541fe19e + +replace github.com/codeready-toolchain/toolchain-common => github.com/xcoulon/toolchain-common v0.0.0-20240725145759-056fcf98e945 + require github.com/google/uuid v1.6.0 require ( diff --git a/go.sum b/go.sum index 8ffa62b72..a78ce43ed 100644 --- a/go.sum +++ b/go.sum @@ -123,10 +123,6 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/codeready-toolchain/api v0.0.0-20240717145630-bb67a632867a h1:La7GOCysmkU+4vnN8lDzXFJwJiA1LWZ9YkX/yQXYnpw= -github.com/codeready-toolchain/api v0.0.0-20240717145630-bb67a632867a/go.mod h1:ie9p4LenCCS0LsnbWp6/xwpFDdCWYE0KWzUO6Sk1g0E= -github.com/codeready-toolchain/toolchain-common v0.0.0-20240716065433-8604fe46b96a h1:HcaJtZCLfYkWZCxIa3iTvq3zgn711JGqPLkunBTfGSc= -github.com/codeready-toolchain/toolchain-common v0.0.0-20240716065433-8604fe46b96a/go.mod h1:8M9k7w2VSyRKSK6P08Jo2ddW3uyGgxCcSitnYa3HK9o= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -660,6 +656,10 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1 github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/xcoulon/api v0.0.0-20240725145329-0fc7541fe19e h1:6rYzVUcLeuVHmFjd7BU/Oe1SMsPrwdQgak2EYMz+oxM= +github.com/xcoulon/api v0.0.0-20240725145329-0fc7541fe19e/go.mod h1:ie9p4LenCCS0LsnbWp6/xwpFDdCWYE0KWzUO6Sk1g0E= +github.com/xcoulon/toolchain-common v0.0.0-20240725145759-056fcf98e945 h1:s7dhWL8+zBI8+bIFzk0EATb6ASGlkA59PHSRvhhxeBc= +github.com/xcoulon/toolchain-common v0.0.0-20240725145759-056fcf98e945/go.mod h1:7o3ZyfqhV16N2Hc3P6j9lx0x6sLhQ0gaVl2cpGAz3ZE= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= diff --git a/make/test.mk b/make/test.mk index 7203d3449..ec3783fe0 100644 --- a/make/test.mk +++ b/make/test.mk @@ -386,7 +386,7 @@ create-host-resources: create-spaceprovisionerconfigs-for-members echo "TOOLCHAIN_CLUSTER_NAME $${TOOLCHAIN_CLUSTER_NAME}"; \ echo "ENVIRONMENT ${ENVIRONMENT}"; \ PATCH_FILE=/tmp/patch-toolchainconfig_${DATE_SUFFIX}.json; \ - echo "{\"spec\":{\"members\":{\"specificPerMemberCluster\":{\"$${TOOLCHAIN_CLUSTER_NAME}\":{\"webhook\":{\"deploy\":false},\"webConsolePlugin\":{\"deploy\":true},\"environment\":\"${ENVIRONMENT}\"}}}}}" > $$PATCH_FILE; \ + echo "{\"spec\":{\"members\":{\"specificPerMemberCluster\":{\"$${TOOLCHAIN_CLUSTER_NAME}\":{\"webhook\":{\"deploy\":false},\"environment\":\"${ENVIRONMENT}\"}}}}}" > $$PATCH_FILE; \ oc patch toolchainconfig config -n ${HOST_NS} --type=merge --patch "$$(cat $$PATCH_FILE)"; \ fi; echo "Restart host operator pods so that configuration referenced in main.go can get the updated ToolchainConfig CRs at startup" diff --git a/test/e2e/parallel/e2e_test.go b/test/e2e/parallel/e2e_test.go index 054ec996d..cf58c2d79 100644 --- a/test/e2e/parallel/e2e_test.go +++ b/test/e2e/parallel/e2e_test.go @@ -56,7 +56,7 @@ func TestE2EFlow(t *testing.T) { VerifyMemberOperatorConfig(t, hostAwait, memberAwait, wait.UntilMemberConfigMatches(expectedMemberConfiguration)) }) t.Run("verify MemberOperatorConfig was synced to member 2", func(t *testing.T) { - member2ExpectedConfig := testconfig.NewMemberOperatorConfigObj(testconfig.Webhook().Deploy(false), testconfig.WebConsolePlugin().Deploy(true), testconfig.MemberEnvironment("e2e-tests")) + member2ExpectedConfig := testconfig.NewMemberOperatorConfigObj(testconfig.Webhook().Deploy(false), testconfig.MemberEnvironment("e2e-tests")) VerifyMemberOperatorConfig(t, hostAwait, memberAwait2, wait.UntilMemberConfigMatches(member2ExpectedConfig.Spec)) }) }) diff --git a/test/e2e/parallel/space_test.go b/test/e2e/parallel/space_test.go index 957e92a59..bd6d3d361 100644 --- a/test/e2e/parallel/space_test.go +++ b/test/e2e/parallel/space_test.go @@ -7,7 +7,6 @@ import ( toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1" testspace "github.com/codeready-toolchain/toolchain-common/pkg/test/space" - "github.com/codeready-toolchain/toolchain-e2e/testsupport" . "github.com/codeready-toolchain/toolchain-e2e/testsupport" . "github.com/codeready-toolchain/toolchain-e2e/testsupport/space" testsupportsb "github.com/codeready-toolchain/toolchain-e2e/testsupport/spacebinding" @@ -250,7 +249,7 @@ func TestPromoteSpace(t *testing.T) { hostAwait := awaitilities.Host() memberAwait := awaitilities.Member1() - user := testsupport.NewSignupRequest(awaitilities). + user := NewSignupRequest(awaitilities). ManuallyApprove(). TargetCluster(memberAwait). RequireConditions(ConditionSet(Default(), ApprovedByAdmin())...). diff --git a/test/e2e/parallel/web_console_plugin_test.go b/test/e2e/parallel/web_console_plugin_test.go deleted file mode 100644 index 2d60e5333..000000000 --- a/test/e2e/parallel/web_console_plugin_test.go +++ /dev/null @@ -1,235 +0,0 @@ -package parallel - -import ( - "crypto/tls" - "fmt" - "io" - "net/http" - "strings" - "testing" - - . "github.com/codeready-toolchain/toolchain-e2e/testsupport" - "github.com/codeready-toolchain/toolchain-e2e/testsupport/wait" - v1 "github.com/openshift/api/route/v1" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" -) - -func TestWebConsoleDeployedSuccessfully(t *testing.T) { - // given - t.Parallel() - await := WaitForDeployments(t) - - for i, memberAwait := range await.AllMembers() { - image := memberAwait.GetContainerEnv(t, "MEMBER_OPERATOR_WEBCONSOLEPLUGIN_IMAGE") - require.NotEmpty(t, image, "The value of the env var MEMBER_OPERATOR_WEBCONSOLEPLUGIN_IMAGE wasn't found in the deployment of the member operator.") - - _, err := memberAwait.WaitForServiceAccount(t, memberAwait.Namespace, "member-operator-console-plugin") - require.NoError(t, err) - waitForWebConsolePluginRole(t, memberAwait) - waitForWebConsolePluginRoleBinding(t, memberAwait) - waitForWebConsolePluginDeployment(t, memberAwait, image) - waitForWebConsolePluginService(t, memberAwait) - - user := NewSignupRequest(await). - Username(fmt.Sprintf("consoletest%d", i)). - Email("consoletest@redhat.com"). - TargetCluster(memberAwait). - ManuallyApprove(). - EnsureMUR(). - RequireConditions(wait.ConditionSet(wait.Default(), wait.ApprovedByAdmin())...). - Execute(t) - token := user.Token - - // Since we can't easily access the web console API resources directly (due to complex security requirements) we - // will instead create a route in the member cluster with which to access the console plugin - - // Before we can create the route however, we need the certificate and private key values from the - // member-operator-console-plugin secret - secret, err := memberAwait.WaitForSecret(t, "member-operator-console-plugin") - require.NoError(t, err) - - // Now we can create the route resource - route := &v1.Route{ - TypeMeta: metav1.TypeMeta{}, - ObjectMeta: metav1.ObjectMeta{ - Name: "consolepluginroute", - Namespace: memberAwait.Namespace, - Annotations: map[string]string{ - "openshift.io/host.generated": "true", - }, - }, - Spec: v1.RouteSpec{ - To: v1.RouteTargetReference{ - Kind: "Service", - Name: "member-operator-console-plugin", - }, - Port: &v1.RoutePort{ - TargetPort: intstr.FromInt(9443), - }, - TLS: &v1.TLSConfig{ - Termination: "reencrypt", - Certificate: string(secret.Data["tls.crt"]), - Key: string(secret.Data["tls.key"]), - }, - WildcardPolicy: "None", - }, - } - - err = memberAwait.CreateWithCleanup(t, route) - require.NoError(t, err) - - reloaded, err := memberAwait.WaitForRouteToBeAvailable(t, route.Namespace, route.Name, "/status") - require.NoError(t, err, "route not available", route) - - // Construct the routeURL from the route host - routeURL := reloaded.Spec.Host + "/" - - manifestURL := fmt.Sprintf("%s%s%s", "https://", routeURL, "plugin-manifest.json") - healthCheckURL := fmt.Sprintf("%s%s%s", "https://", routeURL, "status") - - var tr *http.Transport - { // #nosec G402 - tr = &http.Transport{ - TLSClientConfig: &tls.Config{ - InsecureSkipVerify: true, //nolint:gosec - }, - } - } - - httpClient := &http.Client{Transport: tr} - - var healthCheckResponse *http.Response - - // at this point, since the test is not executed as the first one in the whole e2e test suite, - // we expect that the service should be already healthy, thus we don't need to pool because waiting - // another minute shouldn't have any impact on the outcome. At the same time the presence - // of all Web console plugins related resources are verified at the beginning of thi test including - // the availability of the deployment. In other words, if it fails, then there is definitely - // some problem with the service. - req, err := http.NewRequest("GET", healthCheckURL, nil) - require.NoError(t, err) - req.Header.Set("Authorization", token) - - healthCheckResponse, err = httpClient.Do(req) //nolint - require.NoError(t, err) - defer healthCheckResponse.Body.Close() - require.Equal(t, http.StatusOK, healthCheckResponse.StatusCode, "error calling health check endpoint", route) - - req, err = http.NewRequest("GET", manifestURL, nil) - require.NoError(t, err) - req.Header.Set("Authorization", token) - - manifestResponse, err := httpClient.Do(req) - require.NoError(t, err) - defer manifestResponse.Body.Close() - require.Equal(t, http.StatusOK, healthCheckResponse.StatusCode, "error calling console plugin manifests", route) - - body, err := io.ReadAll(manifestResponse.Body) - require.NoError(t, err) - - require.True(t, strings.HasPrefix(string(body), "{\n \"name\": \"toolchain-member-web-console-plugin\",")) - } -} - -func waitForWebConsolePluginRole(t *testing.T, await *wait.MemberAwaitility) { - ns := &corev1.Namespace{} - ns.Name = await.Namespace - role, err := await.WaitForRole(t, ns, "member-operator-console-plugin") - require.NoError(t, err) - assert.Len(t, role.Rules, 2) - expected := &rbacv1.Role{ - Rules: []rbacv1.PolicyRule{ - { - APIGroups: []string{"toolchain.dev.openshift.com"}, - Resources: []string{"memberoperatorconfigs"}, - Verbs: []string{"get", "list", "watch"}, - }, - { - APIGroups: []string{""}, - Resources: []string{"secrets"}, - Verbs: []string{"get", "list", "watch"}, - }, - }, - } - - assert.Equal(t, expected.Rules, role.Rules) - assert.Equal(t, "codeready-toolchain", role.ObjectMeta.Labels["toolchain.dev.openshift.com/provider"]) -} - -func waitForWebConsolePluginRoleBinding(t *testing.T, await *wait.MemberAwaitility) { - ns := &corev1.Namespace{} - ns.Name = await.Namespace - rb, err := await.WaitForRoleBinding(t, ns, "member-operator-console-plugin") - require.NoError(t, err) - assert.Len(t, rb.Subjects, 1) - assert.Equal(t, "ServiceAccount", rb.Subjects[0].Kind) - assert.Equal(t, "member-operator-console-plugin", rb.Subjects[0].Name) - assert.Equal(t, "member-operator-console-plugin", rb.RoleRef.Name) - assert.Equal(t, "Role", rb.RoleRef.Kind) - assert.Equal(t, "rbac.authorization.k8s.io", rb.RoleRef.APIGroup) - assert.Equal(t, "codeready-toolchain", rb.ObjectMeta.Labels["toolchain.dev.openshift.com/provider"]) -} - -func waitForWebConsolePluginDeployment(t *testing.T, await *wait.MemberAwaitility, image string) { - t.Logf("checking Deployment '%s' in namespace '%s' and with image '%s'", "member-operator-console-plugin", await.Namespace, image) - actualDeployment := await.WaitForDeploymentToGetReady(t, "member-operator-console-plugin", 3, - wait.DeploymentHasContainerWithImage("member-operator-console-plugin", image)) - - assert.Equal(t, "codeready-toolchain", actualDeployment.ObjectMeta.Labels["toolchain.dev.openshift.com/provider"]) - assert.Equal(t, int32(3), *actualDeployment.Spec.Replicas) - assert.Equal(t, map[string]string{ - "name": "member-operator-console-plugin", - }, actualDeployment.Spec.Selector.MatchLabels) - - template := actualDeployment.Spec.Template - assert.Equal(t, map[string]string{ - "name": "member-operator-console-plugin", - "run": "member-operator-console-plugin", - }, template.ObjectMeta.Labels) - assert.Equal(t, "member-operator-console-plugin", template.Spec.ServiceAccountName) - require.Len(t, template.Spec.Volumes, 1) - assert.Equal(t, "consoleplugin-certs", template.Spec.Volumes[0].Name) - assert.Equal(t, "member-operator-console-plugin", template.Spec.Volumes[0].Secret.SecretName) - require.Len(t, template.Spec.Containers, 1) - - container := template.Spec.Containers[0] - assert.Equal(t, "member-operator-console-plugin", container.Name) - assert.NotEmpty(t, container.Image) - assert.Equal(t, []string{"member-operator-console-plugin"}, container.Command) - assert.Equal(t, corev1.PullIfNotPresent, container.ImagePullPolicy) - assert.NotEmpty(t, container.LivenessProbe) - assert.NotEmpty(t, container.ReadinessProbe) - assert.NotEmpty(t, container.StartupProbe) - assert.Len(t, container.Env, 1) - assert.Equal(t, "WATCH_NAMESPACE", container.Env[0].Name) - assert.Equal(t, await.Namespace, container.Env[0].Value) - - assert.Len(t, container.VolumeMounts, 1) - assert.Equal(t, "consoleplugin-certs", container.VolumeMounts[0].Name) - assert.Equal(t, "/etc/consoleplugin/certs", container.VolumeMounts[0].MountPath) - assert.True(t, container.VolumeMounts[0].ReadOnly) -} - -func waitForWebConsolePluginService(t *testing.T, await *wait.MemberAwaitility) { - t.Logf("waiting for Service '%s' in namespace '%s'", "member-operator-console-plugin", await.Namespace) - service, err := await.WaitForService(t, "member-operator-console-plugin") - require.NoError(t, err) - assert.Equal(t, map[string]string{ - "run": "member-operator-console-plugin", - "toolchain.dev.openshift.com/provider": "codeready-toolchain", - }, service.Labels) - require.Len(t, service.Spec.Ports, 1) - assert.Equal(t, int32(9443), service.Spec.Ports[0].Port) - assert.Equal(t, "9443", service.Spec.Ports[0].Name) - assert.Equal(t, intstr.IntOrString{ - IntVal: 9443, - }, service.Spec.Ports[0].TargetPort) - assert.Equal(t, map[string]string{ - "run": "member-operator-console-plugin", - }, service.Spec.Selector) -}