diff --git a/api/v1beta2/ssp_types.go b/api/v1beta2/ssp_types.go index 2f1307d54..63ca358dc 100644 --- a/api/v1beta2/ssp_types.go +++ b/api/v1beta2/ssp_types.go @@ -107,6 +107,8 @@ type TektonTasks struct { // FeatureGates defines feature gate for tto operator type FeatureGates struct { DeployTektonTaskResources bool `json:"deployTektonTaskResources,omitempty"` + + DeployVmConsoleProxy bool `json:"deployVmConsoleProxy,omitempty"` } // DataImportCronTemplate defines the template type for DataImportCrons. diff --git a/config/crd/bases/ssp.kubevirt.io_ssps.yaml b/config/crd/bases/ssp.kubevirt.io_ssps.yaml index 4ef68ab2a..123287d14 100644 --- a/config/crd/bases/ssp.kubevirt.io_ssps.yaml +++ b/config/crd/bases/ssp.kubevirt.io_ssps.yaml @@ -3915,6 +3915,8 @@ spec: properties: deployTektonTaskResources: type: boolean + deployVmConsoleProxy: + type: boolean type: object tektonPipelines: description: TektonPipelines is the configuration of the tekton-pipelines diff --git a/config/samples/ssp_v1beta2_ssp.yaml b/config/samples/ssp_v1beta2_ssp.yaml index c6c9a96f9..d1e2a594a 100644 --- a/config/samples/ssp_v1beta2_ssp.yaml +++ b/config/samples/ssp_v1beta2_ssp.yaml @@ -2,7 +2,6 @@ apiVersion: ssp.kubevirt.io/v1beta2 kind: SSP metadata: annotations: - ssp.kubevirt.io/vm-console-proxy-enabled: "true" ssp.kubevirt.io/vm-console-proxy-namespace: "kubevirt" name: ssp-sample namespace: kubevirt @@ -13,6 +12,7 @@ spec: replicas: 2 featureGates: deployTektonTaskResources: true + deployVmConsoleProxy: true tektonPipelines: namespace: kubevirt tektonTasks: diff --git a/data/crd/ssp.kubevirt.io_ssps.yaml b/data/crd/ssp.kubevirt.io_ssps.yaml index 4cc1111de..5a6daf207 100644 --- a/data/crd/ssp.kubevirt.io_ssps.yaml +++ b/data/crd/ssp.kubevirt.io_ssps.yaml @@ -3916,6 +3916,8 @@ spec: properties: deployTektonTaskResources: type: boolean + deployVmConsoleProxy: + type: boolean type: object tektonPipelines: description: TektonPipelines is the configuration of the tekton-pipelines diff --git a/data/olm-catalog/ssp-operator.clusterserviceversion.yaml b/data/olm-catalog/ssp-operator.clusterserviceversion.yaml index 7bd64ff8f..72b0f2495 100644 --- a/data/olm-catalog/ssp-operator.clusterserviceversion.yaml +++ b/data/olm-catalog/ssp-operator.clusterserviceversion.yaml @@ -10,7 +10,6 @@ metadata: "kind": "SSP", "metadata": { "annotations": { - "ssp.kubevirt.io/vm-console-proxy-enabled": "true", "ssp.kubevirt.io/vm-console-proxy-namespace": "kubevirt" }, "name": "ssp-sample", @@ -21,7 +20,8 @@ metadata: "namespace": "kubevirt" }, "featureGates": { - "deployTektonTaskResources": true + "deployTektonTaskResources": true, + "deployVmConsoleProxy": true }, "tektonPipelines": { "namespace": "kubevirt" diff --git a/docs/configuration.md b/docs/configuration.md index 87e4e7e4e..603e731d8 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -22,7 +22,6 @@ apiVersion: ssp.kubevirt.io/v1beta2 kind: SSP metadata: annotations: - ssp.kubevirt.io/vm-console-proxy-enabled: "true" ssp.kubevirt.io/vm-console-proxy-namespace: "kubevirt" name: ssp-sample namespace: kubevirt @@ -33,6 +32,7 @@ spec: replicas: 2 featureGates: deployTektonTaskResources: true + deployVmConsoleProxy: true tektonPipelines: namespace: kubevirt tektonTasks: @@ -43,14 +43,13 @@ spec: ### VM Console Proxy -These annotations are used by VM console proxy operand. +This annotation is used by VM console proxy operand. ``` apiVersion: ssp.kubevirt.io/v1beta1 kind: SSP metadata: annotations: - ssp.kubevirt.io/vm-console-proxy-enabled: "true" # If not set, then by default is false ssp.kubevirt.io/vm-console-proxy-namespace: "kubevirt" # If not set, then default namespace is "kubevirt" name: ssp-sample namespace: kubevirt @@ -162,3 +161,22 @@ spec: featureGates: deployTektonTaskResources: true ``` + +### `deployVmConsoleProxy` + +Set the `deployVmConsoleProxy` feature gate to true to allow the operator +to deploy VM console proxy resources. + +Resources will be deployed that provide access to the VNC console of a KubeVirt VM, +enabling users to access VMs without requiring access to the cluster's API. + +``` +apiVersion: ssp.kubevirt.io/v1beta2 +kind: SSP +metadata: + name: ssp-sample + namespace: kubevirt +spec: + featureGates: + deployVmConsoleProxy: true +``` diff --git a/internal/operands/vm-console-proxy/reconcile.go b/internal/operands/vm-console-proxy/reconcile.go index 8339749f8..75e88c0e6 100644 --- a/internal/operands/vm-console-proxy/reconcile.go +++ b/internal/operands/vm-console-proxy/reconcile.go @@ -3,7 +3,6 @@ package vm_console_proxy import ( "context" "fmt" - "strconv" routev1 "github.com/openshift/api/route/v1" apps "k8s.io/api/apps/v1" @@ -19,7 +18,6 @@ import ( ) const ( - EnableAnnotation = "ssp.kubevirt.io/vm-console-proxy-enabled" VmConsoleProxyNamespaceAnnotation = "ssp.kubevirt.io/vm-console-proxy-namespace" operandName = "vm-console-proxy" @@ -91,7 +89,7 @@ func (v *vmConsoleProxy) WatchClusterTypes() []operands.WatchType { } func (v *vmConsoleProxy) Reconcile(request *common.Request) ([]common.ReconcileResult, error) { - if !isEnabled(request) { + if request.Instance.Spec.FeatureGates == nil || !request.Instance.Spec.FeatureGates.DeployVmConsoleProxy { cleanupResults, err := v.Cleanup(request) if err != nil { return nil, err @@ -251,18 +249,6 @@ func reconcileRoute(serviceName string) common.ReconcileFunc { } } -func isEnabled(request *common.Request) bool { - if request.Instance.GetAnnotations() == nil { - return false - } - if enable, isFound := request.Instance.GetAnnotations()[EnableAnnotation]; isFound { - if isEnabled, err := strconv.ParseBool(enable); err == nil { - return isEnabled - } - } - return false -} - func getVmConsoleProxyNamespace(request *common.Request) string { const defaultNamespace = "kubevirt" if request.Instance.GetAnnotations() == nil { diff --git a/internal/operands/vm-console-proxy/reconcile_test.go b/internal/operands/vm-console-proxy/reconcile_test.go index 5e88f5e5e..e451aab05 100644 --- a/internal/operands/vm-console-proxy/reconcile_test.go +++ b/internal/operands/vm-console-proxy/reconcile_test.go @@ -187,7 +187,7 @@ var _ = Describe("VM Console Proxy Operand", func() { ExpectResourceExists(bundle.Deployment, request) ExpectResourceExists(newRoute(namespace, serviceName), request) - delete(request.Instance.Annotations, EnableAnnotation) + request.Instance.Spec.FeatureGates.DeployVmConsoleProxy = false _, err = operand.Reconcile(&request) Expect(err).ToNot(HaveOccurred()) @@ -279,7 +279,8 @@ var _ = Describe("VM Console Proxy Operand", func() { ExpectResourceExists(deployment, request) ExpectResourceExists(route, request) - delete(request.Instance.Annotations, EnableAnnotation) + request.Instance.Spec.FeatureGates.DeployVmConsoleProxy = false + delete(request.Instance.Annotations, VmConsoleProxyNamespaceAnnotation) _, err = operand.Reconcile(&request) @@ -323,10 +324,14 @@ func getMockedRequest() common.Request { Name: name, Namespace: namespace, Annotations: map[string]string{ - EnableAnnotation: "true", VmConsoleProxyNamespaceAnnotation: namespace, }, }, + Spec: ssp.SSPSpec{ + FeatureGates: &ssp.FeatureGates{ + DeployVmConsoleProxy: true, + }, + }, }, Logger: log, VersionCache: common.VersionCache{}, diff --git a/tests/tests_suite_test.go b/tests/tests_suite_test.go index 84b385a7f..467216e81 100644 --- a/tests/tests_suite_test.go +++ b/tests/tests_suite_test.go @@ -116,7 +116,6 @@ func (s *newSspStrategy) Init() { common.AppKubernetesComponentLabel: common.AppComponentSchedule.String(), }, Annotations: map[string]string{ - vm_console_proxy.EnableAnnotation: "true", vm_console_proxy.VmConsoleProxyNamespaceAnnotation: s.GetVmConsoleProxyNamespace(), }, }, @@ -135,6 +134,7 @@ func (s *newSspStrategy) Init() { }, FeatureGates: &sspv1beta2.FeatureGates{ DeployTektonTaskResources: false, + DeployVmConsoleProxy: true, }, }, } diff --git a/tests/vm_console_proxy_test.go b/tests/vm_console_proxy_test.go index a846fcfb6..374ae7dd9 100644 --- a/tests/vm_console_proxy_test.go +++ b/tests/vm_console_proxy_test.go @@ -2,12 +2,10 @@ package tests import ( "crypto/tls" - "fmt" "io" "net/http" "net/url" "reflect" - "strconv" "time" . "github.com/onsi/ginkgo/v2" @@ -17,7 +15,6 @@ import ( apps "k8s.io/api/apps/v1" core "k8s.io/api/core/v1" rbac "k8s.io/api/rbac/v1" - "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/utils/pointer" @@ -39,15 +36,16 @@ var _ = Describe("VM Console Proxy Operand", func() { BeforeEach(OncePerOrdered, func() { strategy.SkipSspUpdateTestsIfNeeded() + namespace := strategy.GetVmConsoleProxyNamespace() updateSsp(func(foundSsp *ssp.SSP) { + if foundSsp.Spec.FeatureGates == nil { + foundSsp.Spec.FeatureGates = &ssp.FeatureGates{} + } if foundSsp.GetAnnotations() == nil { foundSsp.Annotations = make(map[string]string) } - - namespace := strategy.GetVmConsoleProxyNamespace() - - foundSsp.Annotations[vm_console_proxy.EnableAnnotation] = "true" + foundSsp.Spec.FeatureGates.DeployVmConsoleProxy = true foundSsp.Annotations[vm_console_proxy.VmConsoleProxyNamespaceAnnotation] = namespace }) @@ -133,40 +131,11 @@ var _ = Describe("VM Console Proxy Operand", func() { }, } - // Waiting until the proxy deployment is created. - // This is a workaround, because the above updateSsp() function updates only annotations, - // which don't update the .metadata.generation field. So the waitUntilDeployed() call - // below succeeds immediately, and does not wait until proxy resources are created. - Eventually(func() error { - return apiClient.Get(ctx, deploymentResource.GetKey(), &apps.Deployment{}) - }, env.ShortTimeout(), time.Second).Should(Succeed()) - waitUntilDeployed() }) AfterEach(OncePerOrdered, func() { strategy.RevertToOriginalSspCr() - - // Similar workaround as in BeforeEach(). - originalSspProxyAnnotation := getSsp().Annotations[vm_console_proxy.EnableAnnotation] - if isEnabled, _ := strconv.ParseBool(originalSspProxyAnnotation); !isEnabled { - Eventually(func() error { - deployment := &apps.Deployment{} - err := apiClient.Get(ctx, deploymentResource.GetKey(), deployment) - if errors.IsNotFound(err) { - return nil - } - if err != nil { - return err - } - if !deployment.DeletionTimestamp.IsZero() { - return nil - } - return fmt.Errorf("the console proxy deployment is not being deleted") - }, env.ShortTimeout(), time.Second).Should(Succeed()) - } - - waitUntilDeployed() }) Context("Resource creation", Ordered, func() { diff --git a/vendor/kubevirt.io/ssp-operator/api/v1beta2/ssp_types.go b/vendor/kubevirt.io/ssp-operator/api/v1beta2/ssp_types.go index 2f1307d54..63ca358dc 100644 --- a/vendor/kubevirt.io/ssp-operator/api/v1beta2/ssp_types.go +++ b/vendor/kubevirt.io/ssp-operator/api/v1beta2/ssp_types.go @@ -107,6 +107,8 @@ type TektonTasks struct { // FeatureGates defines feature gate for tto operator type FeatureGates struct { DeployTektonTaskResources bool `json:"deployTektonTaskResources,omitempty"` + + DeployVmConsoleProxy bool `json:"deployVmConsoleProxy,omitempty"` } // DataImportCronTemplate defines the template type for DataImportCrons.