Skip to content

Commit

Permalink
test: migrate vm-operator to v1alpha2
Browse files Browse the repository at this point in the history
  • Loading branch information
chrischdi committed Jun 4, 2024
1 parent c5333e2 commit bda7076
Show file tree
Hide file tree
Showing 10 changed files with 47 additions and 290 deletions.
4 changes: 3 additions & 1 deletion test/e2e/e2e_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ import (

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
vmoprv1 "github.com/vmware-tanzu/vm-operator/api/v1alpha1"
imgregv1 "github.com/vmware-tanzu/image-registry-operator-api/api/v1alpha1"
vmoprv1 "github.com/vmware-tanzu/vm-operator/api/v1alpha2"
topologyv1 "github.com/vmware-tanzu/vm-operator/external/tanzu-topology/api/v1alpha1"
corev1 "k8s.io/api/core/v1"
storagev1 "k8s.io/api/storage/v1"
Expand Down Expand Up @@ -350,6 +351,7 @@ func initScheme() *runtime.Scheme {
_ = topologyv1.AddToScheme(sc)
_ = vmoprv1.AddToScheme(sc)
_ = vmwarev1.AddToScheme(sc)
_ = imgregv1.AddToScheme(sc)
}
return sc
}
Expand Down
257 changes: 29 additions & 228 deletions test/framework/vmoperator/vmoperator.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,11 @@ import (
"fmt"
"net"
"net/url"
"sort"
"strings"
"time"

"github.com/pkg/errors"
vmoprv1 "github.com/vmware-tanzu/vm-operator/api/v1alpha1"
vmoprv1 "github.com/vmware-tanzu/vm-operator/api/v1alpha2"
topologyv1 "github.com/vmware-tanzu/vm-operator/external/tanzu-topology/api/v1alpha1"
"github.com/vmware/govmomi/pbm"
"github.com/vmware/govmomi/vapi/library"
Expand All @@ -36,13 +35,13 @@ import (
corev1 "k8s.io/api/core/v1"
storagev1 "k8s.io/api/storage/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/klog/v2"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"

"sigs.k8s.io/cluster-api-provider-vsphere/pkg/session"
vcsimv1 "sigs.k8s.io/cluster-api-provider-vsphere/test/infrastructure/vcsim/api/v1alpha1"
Expand Down Expand Up @@ -392,36 +391,6 @@ func ReconcileDependencies(ctx context.Context, c client.Client, dependenciesCon
if retryError != nil {
return retryError
}

vmClassBinding := &vmoprv1.VirtualMachineClassBinding{
ObjectMeta: metav1.ObjectMeta{
Name: vmClass.Name,
Namespace: config.Namespace,
},
ClassRef: vmoprv1.ClassReference{
APIVersion: vmoprv1.SchemeGroupVersion.String(),
Kind: "VirtualMachineClass",
Name: vmClass.Name,
},
}
_ = wait.PollUntilContextTimeout(ctx, 250*time.Millisecond, 5*time.Second, true, func(ctx context.Context) (bool, error) {
retryError = nil
if err := c.Get(ctx, client.ObjectKeyFromObject(vmClassBinding), vmClassBinding); err != nil {
if !apierrors.IsNotFound(err) {
retryError = errors.Wrapf(err, "failed to get vm-operator VirtualMachineClassBinding %s", vmClassBinding.Name)
return false, nil
}
if err := c.Create(ctx, vmClassBinding); err != nil {
retryError = errors.Wrapf(err, "failed to create vm-operator VirtualMachineClassBinding %s", vmClassBinding.Name)
return false, nil
}
log.Info("Created vm-operator VirtualMachineClassBinding", "VirtualMachineClassBinding", klog.KObj(vmClassBinding))
}
return true, nil
})
if retryError != nil {
return retryError
}
}

// Create a ContentLibrary in K8s and in vCenter, bind it to the K8s namespace
Expand Down Expand Up @@ -470,97 +439,6 @@ func ReconcileDependencies(ctx context.Context, c client.Client, dependenciesCon
contentLibraryID = id
}

contentSource := &vmoprv1.ContentSource{
ObjectMeta: metav1.ObjectMeta{
Name: contentLibraryID,
},
Spec: vmoprv1.ContentSourceSpec{
ProviderRef: vmoprv1.ContentProviderReference{
Name: contentLibraryID, // NOTE: this should match the ContentLibraryProvider name below
Kind: "ContentLibraryProvider",
},
},
}
_ = wait.PollUntilContextTimeout(ctx, 250*time.Millisecond, 5*time.Second, true, func(ctx context.Context) (bool, error) {
retryError = nil
if err := c.Get(ctx, client.ObjectKeyFromObject(contentSource), contentSource); err != nil {
if !apierrors.IsNotFound(err) {
retryError = errors.Wrapf(err, "failed to get vm-operator ContentSource %s", contentSource.Name)
return false, nil
}
if err := c.Create(ctx, contentSource); err != nil {
retryError = errors.Wrapf(err, "failed to create vm-operator ContentSource %s", contentSource.Name)
return false, nil
}
log.Info("Created vm-operator ContentSource", "ContentSource", klog.KObj(contentSource))
}
return true, nil
})
if retryError != nil {
return retryError
}

contentSourceBinding := &vmoprv1.ContentSourceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: contentLibraryID,
Namespace: config.Namespace,
},
ContentSourceRef: vmoprv1.ContentSourceReference{
APIVersion: vmoprv1.SchemeGroupVersion.String(),
Kind: "ContentSource",
Name: contentSource.Name,
},
}
_ = wait.PollUntilContextTimeout(ctx, 250*time.Millisecond, 5*time.Second, true, func(ctx context.Context) (bool, error) {
retryError = nil
if err := c.Get(ctx, client.ObjectKeyFromObject(contentSourceBinding), contentSourceBinding); err != nil {
if !apierrors.IsNotFound(err) {
retryError = errors.Wrapf(err, "failed to get vm-operator ContentSourceBinding %s", contentSourceBinding.Name)
return false, nil
}
if err := c.Create(ctx, contentSourceBinding); err != nil {
retryError = errors.Wrapf(err, "failed to create vm-operator ContentSourceBinding %s", contentSourceBinding.Name)
return false, nil
}
log.Info("Created vm-operator ContentSourceBinding", "ContentSourceBinding", klog.KObj(contentSourceBinding))
}
return true, nil
})
if retryError != nil {
return retryError
}

contentLibraryProvider := &vmoprv1.ContentLibraryProvider{
ObjectMeta: metav1.ObjectMeta{
Name: contentLibraryID,
},
Spec: vmoprv1.ContentLibraryProviderSpec{
UUID: contentLibraryID,
},
}

if err := controllerutil.SetOwnerReference(contentSource, contentLibraryProvider, c.Scheme()); err != nil {
return errors.Wrap(err, "failed to set ContentLibraryProvider owner")
}
_ = wait.PollUntilContextTimeout(ctx, 250*time.Millisecond, 5*time.Second, true, func(ctx context.Context) (bool, error) {
retryError = nil
if err := c.Get(ctx, client.ObjectKeyFromObject(contentSource), contentLibraryProvider); err != nil {
if !apierrors.IsNotFound(err) {
retryError = errors.Wrapf(err, "failed to get vm-operator ContentLibraryProvider %s", contentLibraryProvider.Name)
return false, nil
}
if err := c.Create(ctx, contentLibraryProvider); err != nil {
retryError = errors.Wrapf(err, "failed to create vm-operator ContentLibraryProvider %s", contentLibraryProvider.Name)
return false, nil
}
log.Info("Created vm-operator ContentLibraryProvider", "ContentSource", klog.KObj(contentSource), "ContentLibraryProvider", klog.KObj(contentLibraryProvider))
}
return true, nil
})
if retryError != nil {
return retryError
}

for _, item := range config.Spec.VCenter.ContentLibrary.Items {
libraryItem := library.Item{
Name: item.Name,
Expand Down Expand Up @@ -595,29 +473,20 @@ func ReconcileDependencies(ctx context.Context, c client.Client, dependenciesCon
Name: libraryItem.Name,
Namespace: config.Namespace,
},
Spec: vmoprv1.VirtualMachineImageSpec{
ImageID: libraryItemID,
ImageSourceType: "Content Library",
Type: "ovf",
ProviderRef: vmoprv1.ContentProviderReference{
APIVersion: vmoprv1.SchemeGroupVersion.String(),
Kind: "ContentLibraryItem",
// Not 100% sure about following values now that Kind is required to be ContentLibraryItem, but this doesn't seem to be an issue
Name: contentLibraryProvider.Name,
Namespace: contentLibraryProvider.Namespace,
},
ProductInfo: vmoprv1.VirtualMachineImageProductInfo{
FullVersion: item.ProductInfo,
},
OSInfo: vmoprv1.VirtualMachineImageOSInfo{
Type: item.OSInfo,
},
},
// // TODO(chrischdi): check if we can life without it
// Status: vmoprv1.VirtualMachineImageStatus{
// ImageSourceType: "Content Library",
// Type: "ovf",
// ProviderRef: vmoprv1.ContentProviderReference{
// APIVersion: vmoprv1.SchemeGroupVersion.String(),
// Kind: "ContentLibraryItem",
// // Not 100% sure about following values now that Kind is required to be ContentLibraryItem, but this doesn't seem to be an issue
// Name: contentLibraryProvider.Name,
// Namespace: contentLibraryProvider.Namespace,
// },
// },
}

if err := controllerutil.SetOwnerReference(contentLibraryProvider, virtualMachineImage, c.Scheme()); err != nil {
return errors.Wrap(err, "failed to set VirtualMachineImage owner")
}
_ = wait.PollUntilContextTimeout(ctx, 250*time.Millisecond, 5*time.Second, true, func(ctx context.Context) (bool, error) {
retryError = nil
if err := c.Get(ctx, client.ObjectKeyFromObject(virtualMachineImage), virtualMachineImage); err != nil {
Expand All @@ -629,7 +498,7 @@ func ReconcileDependencies(ctx context.Context, c client.Client, dependenciesCon
retryError = errors.Wrapf(err, "failed to create vm-operator VirtualMachineImage %s", virtualMachineImage.Name)
return false, nil
}
log.Info("Created vm-operator VirtualMachineImage", "ContentSource", klog.KObj(contentSource), "ContentLibraryProvider", klog.KObj(contentLibraryProvider), "VirtualMachineImage", klog.KObj(virtualMachineImage))
log.Info("Created vm-operator VirtualMachineImage", "VirtualMachineImage", klog.KObj(virtualMachineImage))
}
return true, nil
})
Expand All @@ -639,14 +508,25 @@ func ReconcileDependencies(ctx context.Context, c client.Client, dependenciesCon

// Fakes reconciliation of virtualMachineImage by setting required status field for the image to be considered ready.
virtualMachineImageReconciled := virtualMachineImage.DeepCopy()
virtualMachineImageReconciled.Status.ImageName = virtualMachineImage.Name
Set(virtualMachineImageReconciled, TrueCondition(ReadyConditionType))
virtualMachineImageReconciled.Status.Name = virtualMachineImage.Name
virtualMachineImageReconciled.Status.ProviderItemID = libraryItemID
virtualMachineImageReconciled.Status.ProductInfo = vmoprv1.VirtualMachineImageProductInfo{
FullVersion: item.ProductInfo,
}
virtualMachineImageReconciled.Status.OSInfo = vmoprv1.VirtualMachineImageOSInfo{
Type: item.OSInfo,
}
meta.SetStatusCondition(&virtualMachineImageReconciled.Status.Conditions, metav1.Condition{
Type: "Ready",
Status: metav1.ConditionTrue,
Reason: string(metav1.ConditionTrue),
})
_ = wait.PollUntilContextTimeout(ctx, 250*time.Millisecond, 5*time.Second, true, func(ctx context.Context) (bool, error) {
retryError = nil
if err := c.Status().Patch(ctx, virtualMachineImageReconciled, client.MergeFrom(virtualMachineImage)); err != nil {
retryError = errors.Wrapf(err, "failed to patch vm-operator VirtualMachineImage %s", virtualMachineImage.Name)
}
log.Info("Patched vm-operator VirtualMachineImage", "ContentSource", klog.KObj(contentSource), "ContentLibraryProvider", klog.KObj(contentLibraryProvider), "VirtualMachineImage", klog.KObj(virtualMachineImage))
log.Info("Patched vm-operator VirtualMachineImage", "VirtualMachineImage", klog.KObj(virtualMachineImage))
return true, nil
})
if retryError != nil {
Expand Down Expand Up @@ -784,82 +664,3 @@ func GetDistributedPortGroup(ctx context.Context, c client.Client) (string, erro

return distributedPortGroup, nil
}

// NOTE: code below is a fork of vm-operator's pkg/conditions (so we can avoid to import the entire project).

const (
ReadyConditionType = "Ready"
)

type Getter interface {
client.Object

// GetConditions returns the list of conditions for a cluster API object.
GetConditions() vmoprv1.Conditions
}

type Setter interface {
Getter
SetConditions(vmoprv1.Conditions)
}

func Set(to Setter, condition *vmoprv1.Condition) {
if to == nil || condition == nil {
return
}

// Check if the new conditions already exists, and change it only if there is a status
// transition (otherwise we should preserve the current last transition time)-
conditions := to.GetConditions()
exists := false
for i := range conditions {
existingCondition := conditions[i]
if existingCondition.Type == condition.Type {
exists = true
if !hasSameState(&existingCondition, condition) {
condition.LastTransitionTime = metav1.NewTime(time.Now().UTC().Truncate(time.Second))
conditions[i] = *condition
break
}
condition.LastTransitionTime = existingCondition.LastTransitionTime
break
}
}

// If the condition does not exist, add it, setting the transition time only if not already set
if !exists {
if condition.LastTransitionTime.IsZero() {
condition.LastTransitionTime = metav1.NewTime(time.Now().UTC().Truncate(time.Second))
}
conditions = append(conditions, *condition)
}

// Sorts conditions for convenience of the consumer, i.e. kubectl.
sort.Slice(conditions, func(i, j int) bool {
return lexicographicLess(&conditions[i], &conditions[j])
})

to.SetConditions(conditions)
}

func lexicographicLess(i, j *vmoprv1.Condition) bool {
return (i.Type == ReadyConditionType || i.Type < j.Type) && j.Type != ReadyConditionType
}

func hasSameState(i, j *vmoprv1.Condition) bool {
return i.Type == j.Type &&
i.Status == j.Status &&
i.Reason == j.Reason &&
i.Message == j.Message
}

func TrueCondition(t vmoprv1.ConditionType) *vmoprv1.Condition {
return &vmoprv1.Condition{
Type: t,
Status: corev1.ConditionTrue,
// This is a non-empty field in metav1.Conditions, when it was not in our v1a1 Conditions. This
// really doesn't work with how we've defined our conditions so do something to make things
// work for now.
Reason: string(corev1.ConditionTrue),
}
}
1 change: 1 addition & 0 deletions test/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ require (
github.com/onsi/gomega v1.33.1
github.com/pkg/errors v0.9.1
github.com/spf13/pflag v1.0.5
github.com/vmware-tanzu/image-registry-operator-api v0.0.0-20240509202721-f6552612433a
github.com/vmware-tanzu/net-operator-api v0.0.0-20240326163340-1f32d6bf7f9d
github.com/vmware-tanzu/vm-operator/api v1.8.6
github.com/vmware-tanzu/vm-operator/external/tanzu-topology v0.0.0-20240404200847-de75746a9505
Expand Down
4 changes: 2 additions & 2 deletions test/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,8 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/vmware-tanzu/image-registry-operator-api v0.0.0-20240509202721-f6552612433a h1:DWa7KUbaOs89ggmKDjiwBBuuR1ewUbN/U071O79W6v4=
github.com/vmware-tanzu/image-registry-operator-api v0.0.0-20240509202721-f6552612433a/go.mod h1:zn/ponkeFUViyBDhYp9OKFPqEGWYrsR71Pn9/aTCvSI=
github.com/vmware-tanzu/net-operator-api v0.0.0-20240326163340-1f32d6bf7f9d h1:cgx9UH/r53bKU/Gbv8IPsUZ34bj5+ItijA2JCUS3kVk=
github.com/vmware-tanzu/net-operator-api v0.0.0-20240326163340-1f32d6bf7f9d/go.mod h1:JbFOh22iDsT5BowJe0GgpMI5e2/S7cWaJlv9LdURVQM=
github.com/vmware-tanzu/nsx-operator/pkg/apis v0.1.0 h1:HdnQb/X9vJ8a5WQ03g/0nDr9igIIK1fF6wO5wOtkJT4=
Expand All @@ -637,8 +639,6 @@ github.com/vmware-tanzu/vm-operator/external/ncp v0.0.0-20240404200847-de75746a9
github.com/vmware-tanzu/vm-operator/external/ncp v0.0.0-20240404200847-de75746a9505/go.mod h1:5rqRJ9zGR+KnKbkGx373WgN8xJpvAj99kHnfoDYRO5I=
github.com/vmware-tanzu/vm-operator/external/tanzu-topology v0.0.0-20240404200847-de75746a9505 h1:/6vFL20UMHOeTf/mb+dKf5sFG0FBbyrCBY/71QKAIE0=
github.com/vmware-tanzu/vm-operator/external/tanzu-topology v0.0.0-20240404200847-de75746a9505/go.mod h1:dfYrWS8DMRN+XZfhu8M4LVHmeGvYB29Ipd7j4uIq+mU=
github.com/vmware-tanzu/vm-operator/pkg/constants/testlabels v0.0.0-20240404200847-de75746a9505 h1:LRMZ+zzb944d6r+uYsE+CuJ3zVBE6Hc8vjH7IJX2QY4=
github.com/vmware-tanzu/vm-operator/pkg/constants/testlabels v0.0.0-20240404200847-de75746a9505/go.mod h1:M+6bZCS8vSjCN9OOppnAyYxeBxY1U0wG6+j3CvIrOHY=
github.com/vmware/govmomi v0.37.2 h1:5ANLoaTxWv600ZnoosJ2zXbM3A+EaxqGheEZbRN8YVE=
github.com/vmware/govmomi v0.37.2/go.mod h1:mtGWtM+YhTADHlCgJBiskSRPOZRsN9MSjPzaZLte/oQ=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
Expand Down
Loading

0 comments on commit bda7076

Please sign in to comment.