Skip to content

Commit

Permalink
instancetype: Label ControllerRevisions with stored object metadata
Browse files Browse the repository at this point in the history
ControllerRevisions are used to store point in time copies of instance
type and preference objects for each VirtualMachine making use of the
feature, see the following user-guide docs for more on this:

Instance types and preferences - Versioning
https://kubevirt.io/user-guide/virtual_machines/instancetypes/#versioning

This change adds labels to these ControllerRevision, exposing metadata
of the stored objects. With this in place it becomes easier to track the
objects stored within these ControllerRevisions and in the future
orchestrate the migration of these objects to newer versions of the API
and CRDs as these are introduced.

Signed-off-by: Lee Yarwood <lyarwood@redhat.com>
  • Loading branch information
lyarwood committed Jul 7, 2023
1 parent 252e886 commit e0ee835
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 7 deletions.
7 changes: 7 additions & 0 deletions pkg/instancetype/instancetype.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ func CreateControllerRevision(vm *virtv1.VirtualMachine, object runtime.Object)
Name: revisionName,
Namespace: vm.Namespace,
OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(vm, virtv1.VirtualMachineGroupVersionKind)},
Labels: map[string]string{
apiinstancetype.ControllerRevisionObjectGenerationLabel: fmt.Sprintf("%d", metaObj.GetGeneration()),
apiinstancetype.ControllerRevisionObjectKindLabel: obj.GetObjectKind().GroupVersionKind().Kind,
apiinstancetype.ControllerRevisionObjectNameLabel: metaObj.GetName(),
apiinstancetype.ControllerRevisionObjectUIDLabel: string(metaObj.GetUID()),
apiinstancetype.ControllerRevisionObjectVersionLabel: obj.GetObjectKind().GroupVersionKind().Version,
},
},
Data: runtime.RawExtension{
Object: obj,
Expand Down
23 changes: 19 additions & 4 deletions pkg/instancetype/instancetype_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,20 @@ var _ = Describe("Instancetype and Preferences", func() {
controllerrevisionInformerStore cache.Store
)

expectControllerRevisionCreation := func(instancetypeSpecRevision *appsv1.ControllerRevision) {
expectControllerRevisionCreation := func(expectedControllerRevision *appsv1.ControllerRevision) {
k8sClient.Fake.PrependReactor("create", "controllerrevisions", func(action testing.Action) (handled bool, obj runtime.Object, err error) {
created, ok := action.(testing.CreateAction)
Expect(ok).To(BeTrue())

createObj := created.GetObject().(*appsv1.ControllerRevision)
Expect(createObj).To(Equal(instancetypeSpecRevision))

// This is already covered by the below assertion but be explicit here to ensure coverage
Expect(createObj.Labels).To(HaveKey(apiinstancetype.ControllerRevisionObjectGenerationLabel))
Expect(createObj.Labels).To(HaveKey(apiinstancetype.ControllerRevisionObjectKindLabel))
Expect(createObj.Labels).To(HaveKey(apiinstancetype.ControllerRevisionObjectNameLabel))
Expect(createObj.Labels).To(HaveKey(apiinstancetype.ControllerRevisionObjectUIDLabel))
Expect(createObj.Labels).To(HaveKey(apiinstancetype.ControllerRevisionObjectVersionLabel))
Expect(createObj).To(Equal(expectedControllerRevision))

return true, created.GetObject(), nil
})
Expand Down Expand Up @@ -112,7 +119,7 @@ var _ = Describe("Instancetype and Preferences", func() {
vm.Namespace = k8sv1.NamespaceDefault
})

Context("Find and store Instancetype Spec", func() {
Context("Find and store instancetype", func() {

It("find returns nil when no instancetype is specified", func() {
vm.Spec.Instancetype = nil
Expand Down Expand Up @@ -564,7 +571,7 @@ var _ = Describe("Instancetype and Preferences", func() {
})
})

Context("Find and store VirtualMachinePreferenceSpec", func() {
Context("Find and store preference", func() {

It("find returns nil when no preference is specified", func() {
vm.Spec.Preference = nil
Expand Down Expand Up @@ -606,6 +613,10 @@ var _ = Describe("Instancetype and Preferences", func() {

preferredCPUTopology := instancetypev1beta1.PreferCores
clusterPreference = &instancetypev1beta1.VirtualMachineClusterPreference{
TypeMeta: metav1.TypeMeta{
Kind: "VirtualMachineClusterPreference",
APIVersion: instancetypev1beta1.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: "test-cluster-preference",
UID: resourceUID,
Expand Down Expand Up @@ -735,6 +746,10 @@ var _ = Describe("Instancetype and Preferences", func() {

preferredCPUTopology := instancetypev1beta1.PreferCores
preference = &instancetypev1beta1.VirtualMachinePreference{
TypeMeta: metav1.TypeMeta{
Kind: "VirtualMachinePreference",
APIVersion: instancetypev1beta1.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: "test-preference",
Namespace: vm.Namespace,
Expand Down
1 change: 1 addition & 0 deletions pkg/storage/snapshot/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,7 @@ func (t *vmRestoreTarget) restoreInstancetypeControllerRevision(vmSnapshotRevisi
restoredCRName := strings.Replace(vmSnapshotRevisionName, vmSnapshotName, vm.Name, 1)
restoredCR := snapshotCR.DeepCopy()
restoredCR.ObjectMeta.Reset()
restoredCR.ObjectMeta.SetLabels(snapshotCR.Labels)
restoredCR.Name = restoredCRName

// If the target VirtualMachine already exists it's likely that the original ControllerRevision is already present.
Expand Down
16 changes: 13 additions & 3 deletions pkg/storage/snapshot/snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2502,6 +2502,16 @@ func createInstancetypeVirtualMachineSnapshotCR(vm *v1.VirtualMachine, vmSnapsho
return cr
}

func expectControllerRevisionToEqualExpected(controllerRevision, expectedControllerRevision *appsv1.ControllerRevision) {
// This is already covered by the below assertion but be explicit here to ensure coverage
Expect(controllerRevision.Labels).To(HaveKey(instancetypeapi.ControllerRevisionObjectGenerationLabel))
Expect(controllerRevision.Labels).To(HaveKey(instancetypeapi.ControllerRevisionObjectKindLabel))
Expect(controllerRevision.Labels).To(HaveKey(instancetypeapi.ControllerRevisionObjectNameLabel))
Expect(controllerRevision.Labels).To(HaveKey(instancetypeapi.ControllerRevisionObjectUIDLabel))
Expect(controllerRevision.Labels).To(HaveKey(instancetypeapi.ControllerRevisionObjectVersionLabel))
Expect(*controllerRevision).To(Equal(*expectedControllerRevision))
}

func expectControllerRevisionCreate(client *k8sfake.Clientset, expectedCR *appsv1.ControllerRevision) {
client.Fake.PrependReactor("create", "controllerrevisions", func(action testing.Action) (handled bool, obj runtime.Object, err error) {
create, ok := action.(testing.CreateAction)
Expand All @@ -2512,7 +2522,7 @@ func expectControllerRevisionCreate(client *k8sfake.Clientset, expectedCR *appsv
expectedCR.ResourceVersion = ""

createObj := create.GetObject().(*appsv1.ControllerRevision)
Expect(*createObj).To(Equal(*expectedCR))
expectControllerRevisionToEqualExpected(createObj, expectedCR)

return true, createObj, nil
})
Expand All @@ -2528,7 +2538,7 @@ func expectCreateControllerRevisionAlreadyExists(client *k8sfake.Clientset, expe
expectedCR.ResourceVersion = ""

createObj := create.GetObject().(*appsv1.ControllerRevision)
Expect(*createObj).To(Equal(*expectedCR))
expectControllerRevisionToEqualExpected(createObj, expectedCR)

return true, create.GetObject(), errors.NewAlreadyExists(schema.GroupResource{}, expectedCR.Name)
})
Expand All @@ -2540,7 +2550,7 @@ func expectControllerRevisionUpdate(client *k8sfake.Clientset, expectedCR *appsv
Expect(ok).To(BeTrue())

updateObj := update.GetObject().(*appsv1.ControllerRevision)
Expect(*updateObj).To(Equal(*expectedCR))
expectControllerRevisionToEqualExpected(updateObj, expectedCR)

return true, update.GetObject(), nil
})
Expand Down
1 change: 1 addition & 0 deletions pkg/storage/snapshot/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ func (s *vmSnapshotSource) captureInstancetypeControllerRevision(namespace, revi

snapshotCR := existingCR.DeepCopy()
snapshotCR.ObjectMeta.Reset()
snapshotCR.ObjectMeta.SetLabels(existingCR.Labels)

// We strip out the source VM name from the CR name and replace it with the snapshot name
snapshotCR.Name = strings.Replace(existingCR.Name, s.snapshot.Spec.Source.Name, s.snapshot.Name, 1)
Expand Down
8 changes: 8 additions & 0 deletions staging/src/kubevirt.io/api/instancetype/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,11 @@ const (
DefaultPreferenceLabel = "instancetype.kubevirt.io/default-preference"
DefaultPreferenceKindLabel = "instancetype.kubevirt.io/default-preference-kind"
)

const (
ControllerRevisionObjectGenerationLabel = "instancetype.kubevirt.io/object-generation"
ControllerRevisionObjectKindLabel = "instancetype.kubevirt.io/object-kind"
ControllerRevisionObjectNameLabel = "instancetype.kubevirt.io/object-name"
ControllerRevisionObjectUIDLabel = "instancetype.kubevirt.io/object-uid"
ControllerRevisionObjectVersionLabel = "instancetype.kubevirt.io/object-version"
)

0 comments on commit e0ee835

Please sign in to comment.