Skip to content

Commit e048e8f

Browse files
idle datavolumes.cdi.kubevirt.io by deleting it (#719)
1 parent b749e61 commit e048e8f

5 files changed

Lines changed: 62 additions & 6 deletions

File tree

controllers/idler/idler_controller.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
"github.com/codeready-toolchain/toolchain-common/pkg/condition"
1414
notify "github.com/codeready-toolchain/toolchain-common/pkg/notification"
1515
"k8s.io/apimachinery/pkg/runtime"
16-
"k8s.io/apimachinery/pkg/runtime/schema"
1716
"k8s.io/client-go/dynamic"
1817
"k8s.io/client-go/rest"
1918
"k8s.io/client-go/scale"
@@ -42,8 +41,6 @@ const (
4241
vmSubresourceURLFmt = "/apis/subresources.kubevirt.io/%s"
4342
)
4443

45-
var vmGVR = schema.GroupVersionResource{Group: "kubevirt.io", Version: "v1", Resource: "virtualmachines"}
46-
4744
// SetupWithManager sets up the controller with the Manager.
4845
func (r *Reconciler) SetupWithManager(mgr manager.Manager, allNamespaceCluster runtimeCluster.Cluster) error {
4946
return ctrl.NewControllerManagedBy(mgr).
@@ -70,11 +67,12 @@ type Reconciler struct {
7067
//+kubebuilder:rbac:groups=toolchain.dev.openshift.com,resources=idlers/status,verbs=get;update;patch
7168
//+kubebuilder:rbac:groups=toolchain.dev.openshift.com,resources=idlers/finalizers,verbs=update
7269

73-
//+kubebuilder:rbac:groups="",resources=pods;replicationcontrollers,verbs=get;list;watch;create;update;patch;delete
70+
//+kubebuilder:rbac:groups="",resources=pods;replicationcontrollers;persistentvolumeclaims,verbs=get;list;watch;create;update;patch;delete
7471
//+kubebuilder:rbac:groups=apps,resources=deployments;daemonsets;replicasets;statefulsets,verbs=get;list;watch;create;update;patch;delete
7572
//+kubebuilder:rbac:groups=apps.openshift.io,resources=deploymentconfigs,verbs=get;list;watch;create;update;patch;delete
7673
//+kubebuilder:rbac:groups=batch,resources=jobs,verbs=get;list;watch;create;update;patch;delete
7774
//+kubebuilder:rbac:groups=kubevirt.io,resources=virtualmachines;virtualmachineinstances,verbs=get;list;watch;create;update;patch;delete
75+
//+kubebuilder:rbac:groups=cdi.kubevirt.io,resources=datavolumes,verbs=get;list;watch;create;update;patch;delete
7876
//+kubebuilder:rbac:groups=serving.kserve.io,resources=inferenceservices;servingruntimes,verbs=get;list;watch;create;update;patch;delete
7977

8078
// needed to stop the VMs - we need to make a PUT request for the "stop" subresource. Kubernetes internally classifies these as either create or update

controllers/idler/idler_controller_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ func TestEnsureIdling(t *testing.T) {
198198
JobDoesNotExist(podsRunningForTooLong.job).
199199
JobExists(podsTooEarlyToKill.job).
200200
JobExists(noise.job).
201+
DataVolumeDoesNotExist(podsRunningForTooLong.dataVolume).
202+
DataVolumeExists(podsTooEarlyToKill.dataVolume).
203+
DataVolumeExists(noise.dataVolume).
201204
DeploymentScaledDown(podsRunningForTooLong.deployment).
202205
ScaleSubresourceScaledDown(podsRunningForTooLong.integration).
203206
ScaleSubresourceScaledDown(podsRunningForTooLong.kameletBinding).
@@ -321,6 +324,7 @@ func TestEnsureIdling(t *testing.T) {
321324
PodsDoNotExist(toKill.standalonePods).
322325
DaemonSetDoesNotExist(toKill.daemonSet).
323326
JobDoesNotExist(toKill.job).
327+
DataVolumeDoesNotExist(toKill.dataVolume).
324328
DeploymentScaledDown(toKill.deployment).
325329
ScaleSubresourceScaledDown(toKill.integration).
326330
ScaleSubresourceScaledDown(toKill.kameletBinding).
@@ -536,6 +540,7 @@ func TestEnsureIdlingFailed(t *testing.T) {
536540
PodsDoNotExist(toKill.standalonePods).
537541
DaemonSetDoesNotExist(toKill.daemonSet).
538542
JobDoesNotExist(toKill.job).
543+
DataVolumeDoesNotExist(toKill.dataVolume).
539544
ReplicaSetScaledDown(toKill.replicaSet).
540545
DeploymentScaledDown(toKill.deployment).
541546
ScaleSubresourceScaledDown(toKill.integration).
@@ -871,6 +876,7 @@ type payloads struct {
871876
deploymentConfig *openshiftappsv1.DeploymentConfig
872877
replicationController *corev1.ReplicationController
873878
job *batchv1.Job
879+
dataVolume *unstructured.Unstructured
874880
virtualmachine *unstructured.Unstructured
875881
vmStopCallCounter *int
876882
virtualmachineinstance *unstructured.Unstructured
@@ -982,6 +988,21 @@ func preparePayloads(t *testing.T, clients *memberoperatortest.FakeClientSet, na
982988
createObjectWithDynamicClient(t, clients.DynamicClient, job)
983989
controlledPods = createPods(t, clients.AllNamespacesClient, job, sTime, controlledPods, noRestart())
984990

991+
// DataVolume
992+
dv := &unstructured.Unstructured{}
993+
dv.SetAPIVersion("cdi.kubevirt.io/v1beta1")
994+
dv.SetKind("DataVolume")
995+
dv.SetName(fmt.Sprintf("%s%s-datavolume", namePrefix, namespace))
996+
dv.SetNamespace(namespace)
997+
createObjectWithDynamicClient(t, clients.DynamicClient, dv)
998+
// PersistentVolumeClaim owned by DataVolume
999+
dvPvc := &corev1.PersistentVolumeClaim{
1000+
ObjectMeta: metav1.ObjectMeta{Name: fmt.Sprintf("%s-pvc", dv.GetName()), Namespace: namespace},
1001+
}
1002+
require.NoError(t, controllerutil.SetControllerReference(dv, dvPvc, scheme.Scheme))
1003+
createObjectWithDynamicClient(t, clients.DynamicClient, dvPvc)
1004+
controlledPods = createPods(t, clients.AllNamespacesClient, dvPvc, sTime, controlledPods, noRestart())
1005+
9851006
// StatefulSet
9861007
sts := &appsv1.StatefulSet{
9871008
ObjectMeta: metav1.ObjectMeta{Name: fmt.Sprintf("%s%s-statefulset", namePrefix, namespace), Namespace: namespace},
@@ -1107,6 +1128,7 @@ func preparePayloads(t *testing.T, clients *memberoperatortest.FakeClientSet, na
11071128
deploymentConfig: dc,
11081129
replicationController: standaloneRC,
11091130
job: job,
1131+
dataVolume: dv,
11101132
virtualmachine: vm,
11111133
vmStopCallCounter: stopCallCounter,
11121134
virtualmachineinstance: vmi,

controllers/idler/owners.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func (i *ownerIdler) scaleOwnerToZero(ctx context.Context, pod *corev1.Pod) (str
6060
switch ownerKind {
6161
case "Deployment", "ReplicaSet", "Integration", "KameletBinding", "StatefulSet", "ReplicationController":
6262
err = i.scaleToZero(ctx, ownerWithGVR)
63-
case "DaemonSet", "Job":
63+
case "DaemonSet", "Job", "DataVolume":
6464
err = i.deleteResource(ctx, ownerWithGVR) // Nothing to scale down. Delete instead.
6565
case "DeploymentConfig":
6666
err = i.scaleDeploymentConfigToZero(ctx, ownerWithGVR)

controllers/idler/owners_test.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,20 @@ var testConfigs = map[string]createTestConfigFunc{
157157
},
158158
}
159159
},
160+
"DataVolume": func(plds payloads) payloadTestConfig {
161+
return payloadTestConfig{
162+
// We are testing the case with nested controllers (DataVolume -> PersistentVolumeClaim -> Pod) here,
163+
// so the pod's owner is PersistentVolumeClaim but the expected scaled app is the parent DataVolume.
164+
podOwnerName: fmt.Sprintf("%s-pvc", plds.dataVolume.GetName()),
165+
expectedAppName: plds.dataVolume.GetName(),
166+
ownerScaledUp: func(assertion *test.IdleablePayloadAssertion) {
167+
assertion.DataVolumeExists(plds.dataVolume)
168+
},
169+
ownerScaledDown: func(assertion *test.IdleablePayloadAssertion) {
170+
assertion.DataVolumeDoesNotExist(plds.dataVolume)
171+
},
172+
}
173+
},
160174
"VirtualMachine": func(plds payloads) payloadTestConfig {
161175
return payloadTestConfig{
162176
podOwnerName: plds.virtualmachineinstance.GetName(),
@@ -428,12 +442,18 @@ func noAAPResourceList(t *testing.T) []*metav1.APIResourceList {
428442
require.NoError(t, apis.AddToScheme(scheme.Scheme))
429443
noAAPResources := []*metav1.APIResourceList{
430444
{
431-
GroupVersion: vmGVR.GroupVersion().String(),
445+
GroupVersion: "kubevirt.io/v1",
432446
APIResources: []metav1.APIResource{
433447
{Name: "virtualmachineinstances", Namespaced: true, Kind: "VirtualMachineInstance"},
434448
{Name: "virtualmachines", Namespaced: true, Kind: "VirtualMachine"},
435449
},
436450
},
451+
{
452+
GroupVersion: "cdi.kubevirt.io/v1beta1",
453+
APIResources: []metav1.APIResource{
454+
{Name: "datavolumes", Namespaced: true, Kind: "DataVolume"},
455+
},
456+
},
437457
}
438458
for gvk := range scheme.Scheme.AllKnownTypes() {
439459
resource, _ := meta.UnsafeGuessKindToResource(gvk)

test/idler_assertion.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,22 @@ func (a *IdleablePayloadAssertion) JobDoesNotExist(job *batchv1.Job) *IdleablePa
298298
return a
299299
}
300300

301+
var dataVolumeGVR = schema.GroupVersionResource{Group: "cdi.kubevirt.io", Version: "v1beta1", Resource: "datavolumes"}
302+
303+
func (a *IdleablePayloadAssertion) DataVolumeExists(dataVolume *unstructured.Unstructured) *IdleablePayloadAssertion {
304+
_, err := a.dynamicClient.
305+
Resource(dataVolumeGVR).
306+
Namespace(dataVolume.GetNamespace()).
307+
Get(context.TODO(), dataVolume.GetName(), metav1.GetOptions{})
308+
require.NoError(a.t, err)
309+
return a
310+
}
311+
312+
func (a *IdleablePayloadAssertion) DataVolumeDoesNotExist(dataVolume *unstructured.Unstructured) *IdleablePayloadAssertion {
313+
a.assertResourceDeleted(dataVolumeGVR, dataVolume.GetNamespace(), dataVolume.GetName())
314+
return a
315+
}
316+
301317
func (a *IdleablePayloadAssertion) StatefulSetScaledDown(statefulSet *appsv1.StatefulSet) *IdleablePayloadAssertion {
302318
s := &appsv1.StatefulSet{}
303319
gvr := appsv1.SchemeGroupVersion.WithResource("statefulsets")

0 commit comments

Comments
 (0)