Skip to content

Commit

Permalink
Merge pull request #1135 from akrejcir/update-vm-proxy
Browse files Browse the repository at this point in the history
chore: Update vm-console-proxy to v0.7.0
  • Loading branch information
kubevirt-bot authored Nov 20, 2024
2 parents c62f822 + 64a8480 commit 93d3e75
Show file tree
Hide file tree
Showing 11 changed files with 418 additions and 13 deletions.
10 changes: 4 additions & 6 deletions data/vm-console-proxy-bundle/vm-console-proxy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,7 @@ subjects:
---
apiVersion: v1
data:
tls-profile-v1alpha1.yaml: |
type: Intermediate
intermediate: {}
tls-profile-v1.yaml: '{}'
kind: ConfigMap
metadata:
name: vm-console-proxy
Expand Down Expand Up @@ -156,7 +154,7 @@ spec:
- args: []
command:
- /console
image: quay.io/kubevirt/vm-console-proxy:v0.6.1
image: quay.io/kubevirt/vm-console-proxy:v0.7.0
imagePullPolicy: Always
name: console
ports:
Expand Down Expand Up @@ -194,13 +192,13 @@ kind: APIService
metadata:
annotations:
service.beta.openshift.io/inject-cabundle: "true"
name: v1alpha1.token.kubevirt.io
name: v1.token.kubevirt.io
spec:
group: token.kubevirt.io
groupPriorityMinimum: 2000
service:
name: vm-console-proxy
namespace: kubevirt
port: 443
version: v1alpha1
version: v1
versionPriority: 10
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ require (
kubevirt.io/controller-lifecycle-operator-sdk/api v0.2.4
kubevirt.io/qe-tools v0.1.8
kubevirt.io/ssp-operator/api v0.0.0
kubevirt.io/vm-console-proxy/api v0.7.0
sigs.k8s.io/controller-runtime v0.18.5
sigs.k8s.io/yaml v1.4.0
)
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,8 @@ kubevirt.io/controller-lifecycle-operator-sdk/api v0.2.4 h1:fZYvD3/Vnitfkx6IJxjL
kubevirt.io/controller-lifecycle-operator-sdk/api v0.2.4/go.mod h1:018lASpFYBsYN6XwmA2TIrPCx6e0gviTd/ZNtSitKgc=
kubevirt.io/qe-tools v0.1.8 h1:Ar7qicmzHdd+Ia+6rjHDg3D7GReIyq7QFXoC4F7TjhQ=
kubevirt.io/qe-tools v0.1.8/go.mod h1:+Tr/WZGHIDQa/4pQgzM7+4J6YeVbUWAXESXtL2/zxqc=
kubevirt.io/vm-console-proxy/api v0.7.0 h1:yhzTtywJDqDx3ddIDhuMmN9O19EdGZS0NDqtGwEwk9c=
kubevirt.io/vm-console-proxy/api v0.7.0/go.mod h1:7q967W73c6/Iczl3xJkOjQOASAJ2wXBTEbCbiqD9bXE=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
Expand Down
2 changes: 1 addition & 1 deletion internal/operands/vm-console-proxy/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ package vm_console_proxy
// This file is updated by GitHub action defined in .github/workflows/release-vm-console-proxy.yaml

const (
defaultVmConsoleProxyImageTag = "v0.6.1"
defaultVmConsoleProxyImageTag = "v0.7.0"
defaultVmConsoleProxyImage = "quay.io/kubevirt/vm-console-proxy:" + defaultVmConsoleProxyImageTag
)
92 changes: 90 additions & 2 deletions internal/operands/vm-console-proxy/reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ import (
"context"
"fmt"

ocpv1 "github.com/openshift/api/config/v1"
routev1 "github.com/openshift/api/route/v1"
"github.com/openshift/library-go/pkg/crypto"
apps "k8s.io/api/apps/v1"
core "k8s.io/api/core/v1"
rbac "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
apiregv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
proxyv1 "kubevirt.io/vm-console-proxy/api/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"

"kubevirt.io/ssp-operator/internal/common"
"kubevirt.io/ssp-operator/internal/env"
Expand Down Expand Up @@ -141,12 +146,21 @@ func (v *vmConsoleProxy) Reconcile(request *common.Request) ([]common.ReconcileR
return nil, err
}

var cleanupResults []common.CleanupResult
oldApiServiceCleanup, err := deleteOldApiService(request)
if err != nil {
return nil, err
}
cleanupResults = append(cleanupResults, oldApiServiceCleanup)

// Route is no longer needed.
routeCleanupResults, err := v.deleteRoute(request)
if err != nil {
return nil, err
}
for _, cleanupResult := range routeCleanupResults {
cleanupResults = append(cleanupResults, routeCleanupResults...)

for _, cleanupResult := range cleanupResults {
if !cleanupResult.Deleted {
reconcileResults = append(reconcileResults, common.ResourceDeletedResult(cleanupResult.Resource, common.OperationResultDeleted))
}
Expand All @@ -159,10 +173,19 @@ func (v *vmConsoleProxy) Cleanup(request *common.Request) ([]common.CleanupResul
// We need to use labels to find resources that were deployed by this operand,
// because namespace annotation may not be present.

var allResults []common.CleanupResult

routeCleanupResults, err := v.deleteRoute(request)
if err != nil {
return nil, err
}
allResults = append(allResults, routeCleanupResults...)

oldApiServiceCleanup, err := deleteOldApiService(request)
if err != nil {
return nil, err
}
allResults = append(allResults, oldApiServiceCleanup)

var objectsToDelete []client.Object

Expand Down Expand Up @@ -224,7 +247,9 @@ func (v *vmConsoleProxy) Cleanup(request *common.Request) ([]common.CleanupResul
return nil, err
}

return append(cleanupResults, routeCleanupResults...), nil
allResults = append(allResults, cleanupResults...)

return allResults, nil
}

func (v *vmConsoleProxy) deleteRoute(request *common.Request) ([]common.CleanupResult, error) {
Expand All @@ -241,6 +266,15 @@ func (v *vmConsoleProxy) deleteRoute(request *common.Request) ([]common.CleanupR
return common.DeleteAll(request, routes...)
}

func deleteOldApiService(request *common.Request) (common.CleanupResult, error) {
return common.Cleanup(request, &apiregv1.APIService{
TypeMeta: metav1.TypeMeta{},
ObjectMeta: metav1.ObjectMeta{
Name: "v1alpha1.token.kubevirt.io",
},
})
}

func reconcileServiceAccount(serviceAccount core.ServiceAccount) common.ReconcileFunc {
return func(request *common.Request) (common.ReconcileResult, error) {
serviceAccount.Namespace = request.Instance.Namespace
Expand Down Expand Up @@ -283,6 +317,15 @@ func reconcileRoleBinding(roleBinding *rbac.RoleBinding) common.ReconcileFunc {
func reconcileConfigMap(configMap core.ConfigMap) common.ReconcileFunc {
return func(request *common.Request) (common.ReconcileResult, error) {
configMap.Namespace = request.Instance.Namespace

tlsConfigYaml, err := createTlsConfigFile(request.Instance.Spec.TLSSecurityProfile)
if err != nil {
return common.ReconcileResult{}, err
}

const tlsConfigFilename = "tls-profile-v1.yaml"
configMap.Data[tlsConfigFilename] = tlsConfigYaml

return common.CreateOrUpdate(request).
NamespacedResource(&configMap).
WithAppLabels(operandName, operandComponent).
Expand Down Expand Up @@ -335,6 +378,51 @@ func getVmConsoleProxyImage() string {
return env.EnvOrDefault(env.VmConsoleProxyImageKey, defaultVmConsoleProxyImage)
}

func createTlsConfigFile(tlsProfile *ocpv1.TLSSecurityProfile) (string, error) {
if tlsProfile == nil {
// Returning empty config yaml. Default configuration will be used.
return "{}", nil
}

var profileSpec *ocpv1.TLSProfileSpec
if tlsProfile.Type == ocpv1.TLSProfileCustomType {
if tlsProfile.Custom == nil {
return "", fmt.Errorf("tlsProfile is invalid: custom filed is empty")
}
profileSpec = tlsProfile.Custom.TLSProfileSpec.DeepCopy()
} else {
predefinedProfile, found := ocpv1.TLSProfiles[tlsProfile.Type]
if !found {
return "", fmt.Errorf("tlsProfile type is invalid: %s", tlsProfile.Type)
}
profileSpec = predefinedProfile.DeepCopy()
}

result := proxyv1.TlsProfile{}

switch profileSpec.MinTLSVersion {
case ocpv1.VersionTLS10:
result.MinTLSVersion = proxyv1.VersionTLS10
case ocpv1.VersionTLS11:
result.MinTLSVersion = proxyv1.VersionTLS11
case ocpv1.VersionTLS12:
result.MinTLSVersion = proxyv1.VersionTLS12
case ocpv1.VersionTLS13:
result.MinTLSVersion = proxyv1.VersionTLS13
default:
return "", fmt.Errorf("unsupported TLS version: %s", profileSpec.MinTLSVersion)
}

result.Ciphers = crypto.OpenSSLToIANACipherSuites(profileSpec.Ciphers)

yamlBytes, err := yaml.Marshal(result)
if err != nil {
return "", fmt.Errorf("failed to marshal TLS profile cofing to yaml: %w", err)
}

return string(yamlBytes), nil
}

func findResourcesUsingLabels[PtrL interface {
*L
client.ObjectList
Expand Down
78 changes: 76 additions & 2 deletions internal/operands/vm-console-proxy/reconcile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import (

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"k8s.io/apimachinery/pkg/api/errors"

ocpv1 "github.com/openshift/api/config/v1"
routev1 "github.com/openshift/api/route/v1"
libhandler "github.com/operator-framework/operator-lib/handler"
apps "k8s.io/api/apps/v1"
Expand All @@ -21,10 +23,12 @@ import (
apiregv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
"k8s.io/utils/ptr"
kubevirt "kubevirt.io/api/core"
proxyv1 "kubevirt.io/vm-console-proxy/api/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"sigs.k8s.io/yaml"

ssp "kubevirt.io/ssp-operator/api/v1beta2"
"kubevirt.io/ssp-operator/internal/common"
Expand Down Expand Up @@ -116,6 +120,53 @@ var _ = Describe("VM Console Proxy Operand", func() {
Expect(apiService.Spec.Service.Namespace).To(Equal(namespace))
})

It("should remove old APIService on reconcile", func() {
oldApiService := &apiregv1.APIService{
ObjectMeta: metav1.ObjectMeta{
Name: "v1alpha1.token.kubevirt.io",
Labels: map[string]string{
common.AppKubernetesNameLabel: operandName,
common.AppKubernetesComponentLabel: operandComponent,
common.AppKubernetesManagedByLabel: common.AppKubernetesManagedByValue,
},
},
}
Expect(libhandler.SetOwnerAnnotations(request.Instance, oldApiService)).To(Succeed())

Expect(request.Client.Create(request.Context, oldApiService)).To(Succeed())

_, err := operand.Reconcile(&request)
Expect(err).ToNot(HaveOccurred())

key := client.ObjectKeyFromObject(oldApiService)
Expect(request.Client.Get(request.Context, key, &apiregv1.APIService{})).
To(MatchError(errors.IsNotFound, "errors.IsNotFound"))
})

It("should write TLS configuration to ConfigMap", func() {
request.Instance.Spec.TLSSecurityProfile = &ocpv1.TLSSecurityProfile{
Type: ocpv1.TLSProfileIntermediateType,
Intermediate: &ocpv1.IntermediateTLSProfile{},
}

_, err := operand.Reconcile(&request)
Expect(err).ToNot(HaveOccurred())

configMapKey := client.ObjectKeyFromObject(bundle.ConfigMap)

configMap := &core.ConfigMap{}
Expect(request.Client.Get(request.Context, configMapKey, configMap)).To(Succeed())

const tlsConfigFilename = "tls-profile-v1.yaml"
tlsConfig, exists := configMap.Data[tlsConfigFilename]
Expect(exists).To(BeTrue(), "ConfigMap should have TLS configuration file: "+tlsConfigFilename)

proxyProfile := &proxyv1.TlsProfile{}
Expect(yaml.Unmarshal([]byte(tlsConfig), proxyProfile)).To(Succeed())

Expect(proxyProfile.MinTLSVersion).To(Equal(proxyv1.VersionTLS12))
})

It("should remove cluster resources on cleanup", func() {
_, err := operand.Reconcile(&request)
Expect(err).ToNot(HaveOccurred())
Expand Down Expand Up @@ -146,6 +197,29 @@ var _ = Describe("VM Console Proxy Operand", func() {
ExpectResourceNotExists(bundle.ApiService, request)
})

It("should remove old APIService on cleanup", func() {
oldApiService := &apiregv1.APIService{
ObjectMeta: metav1.ObjectMeta{
Name: "v1alpha1.token.kubevirt.io",
Labels: map[string]string{
common.AppKubernetesNameLabel: operandName,
common.AppKubernetesComponentLabel: operandComponent,
common.AppKubernetesManagedByLabel: common.AppKubernetesManagedByValue,
},
},
}
Expect(libhandler.SetOwnerAnnotations(request.Instance, oldApiService)).To(Succeed())

Expect(request.Client.Create(request.Context, oldApiService)).To(Succeed())

_, err := operand.Cleanup(&request)
Expect(err).ToNot(HaveOccurred())

key := client.ObjectKeyFromObject(oldApiService)
Expect(request.Client.Get(request.Context, key, &apiregv1.APIService{})).
To(MatchError(errors.IsNotFound, "errors.IsNotFound"))
})

DescribeTable("should delete Route leftover from previous version", func(op func() error) {
route := &routev1.Route{
ObjectMeta: metav1.ObjectMeta{
Expand Down Expand Up @@ -536,12 +610,12 @@ func getMockedTestBundle() *vm_console_proxy_bundle.Bundle {
},
ApiService: &apiregv1.APIService{
ObjectMeta: metav1.ObjectMeta{
Name: "v1alpha1.token.kubevirt.io",
Name: "v1.token.kubevirt.io",
},
Spec: apiregv1.APIServiceSpec{
Group: "token.kubevirt.io",
GroupPriorityMinimum: 2000,
Version: "v1alpha1",
Version: "v1",
VersionPriority: 10,
Service: &apiregv1.ServiceReference{
Name: serviceName,
Expand Down
4 changes: 2 additions & 2 deletions tests/vm_console_proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ var _ = Describe("VM Console Proxy Operand", func() {
},
}
apiServiceResource = testResource{
Name: "v1alpha1.token.kubevirt.io",
Name: "v1.token.kubevirt.io",
Resource: &apiregv1.APIService{},
ExpectedLabels: expectedLabels,
UpdateFunc: func(apiService *apiregv1.APIService) {
Expand Down Expand Up @@ -319,7 +319,7 @@ var _ = Describe("VM Console Proxy Operand", func() {
vmNamespace := strategy.GetNamespace()
vmName := "non-existing-vm"

url := apiServerHostname + "/apis/token.kubevirt.io/v1alpha1/namespaces/" + vmNamespace + "/virtualmachines/" + vmName + "/vnc"
url := apiServerHostname + "/apis/token.kubevirt.io/v1/namespaces/" + vmNamespace + "/virtualmachines/" + vmName + "/vnc"

// It may take a moment for the service to be reachable
Eventually(func(g Gomega) {
Expand Down
Loading

0 comments on commit 93d3e75

Please sign in to comment.