Skip to content

Commit d6b07bf

Browse files
committed
fix: sync quota values from tenant to resourcequota object
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
1 parent 5e13ac9 commit d6b07bf

File tree

2 files changed

+42
-6
lines changed

2 files changed

+42
-6
lines changed

api/v1beta2/tenant_annotations.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import (
1212
const (
1313
// Annotation name part must be no more than 63 characters.
1414
maxAnnotationLength = 63
15+
16+
HardCapsuleQuotaAnnotation = "quota.capsule.clastix.io/hard-"
17+
UsedCapsuleQuotaAnnotation = "quota.capsule.clastix.io/used-"
1518
)
1619

1720
func createAnnotation(format string, resource fmt.Stringer) (string, error) {
@@ -36,9 +39,9 @@ func createAnnotation(format string, resource fmt.Stringer) (string, error) {
3639
}
3740

3841
func UsedQuotaFor(resource fmt.Stringer) (string, error) {
39-
return createAnnotation("quota.capsule.clastix.io/used-", resource)
42+
return createAnnotation(UsedCapsuleQuotaAnnotation, resource)
4043
}
4144

4245
func HardQuotaFor(resource fmt.Stringer) (string, error) {
43-
return createAnnotation("quota.capsule.clastix.io/hard-", resource)
46+
return createAnnotation(HardCapsuleQuotaAnnotation, resource)
4447
}

controllers/tenant/resourcequotas.go

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"context"
88
"fmt"
99
"strconv"
10+
"strings"
1011

1112
"golang.org/x/sync/errgroup"
1213
corev1 "k8s.io/api/core/v1"
@@ -15,6 +16,7 @@ import (
1516
"k8s.io/apimachinery/pkg/labels"
1617
"k8s.io/apimachinery/pkg/selection"
1718
"k8s.io/apimachinery/pkg/types"
19+
"k8s.io/apimachinery/pkg/util/sets"
1820
"k8s.io/client-go/util/retry"
1921
"sigs.k8s.io/controller-runtime/pkg/client"
2022
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
@@ -52,9 +54,12 @@ func (r *Manager) syncResourceQuotas(ctx context.Context, tenant *capsulev1beta2
5254
group := new(errgroup.Group)
5355

5456
for i, q := range tenant.Spec.ResourceQuota.Items {
55-
index := i
57+
index, resourceQuota := i, q
5658

57-
resourceQuota := q
59+
toKeep := sets.New[corev1.ResourceName]()
60+
for k := range resourceQuota.Hard {
61+
toKeep.Insert(k)
62+
}
5863

5964
group.Go(func() (scopeErr error) {
6065
// Calculating the Resource Budget at Tenant scope just if this is put in place.
@@ -120,9 +125,15 @@ func (r *Manager) syncResourceQuotas(ctx context.Context, tenant *capsulev1beta2
120125
list.Items[item].Spec.Hard = map[corev1.ResourceName]resource.Quantity{}
121126
}
122127
list.Items[item].Spec.Hard[name] = resourceQuota.Hard[name]
128+
129+
for k := range list.Items[item].Spec.Hard {
130+
if !toKeep.Has(k) {
131+
delete(list.Items[item].Spec.Hard, k)
132+
}
133+
}
123134
}
124135
}
125-
if scopeErr = r.resourceQuotasUpdate(ctx, name, quantity, resourceQuota.Hard[name], list.Items...); scopeErr != nil {
136+
if scopeErr = r.resourceQuotasUpdate(ctx, name, quantity, toKeep, resourceQuota.Hard[name], list.Items...); scopeErr != nil {
126137
r.Log.Error(scopeErr, "cannot proceed with outer ResourceQuota")
127138

128139
return
@@ -217,9 +228,21 @@ func (r *Manager) syncResourceQuota(ctx context.Context, tenant *capsulev1beta2.
217228
// Serial ResourceQuota processing is expensive: using Go routines we can speed it up.
218229
// In case of multiple errors these are logged properly, returning a generic error since we have to repush back the
219230
// reconciliation loop.
220-
func (r *Manager) resourceQuotasUpdate(ctx context.Context, resourceName corev1.ResourceName, actual, limit resource.Quantity, list ...corev1.ResourceQuota) (err error) {
231+
func (r *Manager) resourceQuotasUpdate(ctx context.Context, resourceName corev1.ResourceName, actual resource.Quantity, toKeep sets.Set[corev1.ResourceName], limit resource.Quantity, list ...corev1.ResourceQuota) (err error) {
221232
group := new(errgroup.Group)
222233

234+
annotationsToKeep := sets.New[string]()
235+
236+
for _, item := range toKeep.UnsortedList() {
237+
if v, vErr := capsulev1beta2.UsedQuotaFor(item); vErr == nil {
238+
annotationsToKeep.Insert(v)
239+
}
240+
241+
if v, vErr := capsulev1beta2.HardQuotaFor(item); vErr == nil {
242+
annotationsToKeep.Insert(v)
243+
}
244+
}
245+
223246
for _, item := range list {
224247
rq := item
225248

@@ -236,6 +259,16 @@ func (r *Manager) resourceQuotasUpdate(ctx context.Context, resourceName corev1.
236259
if found.Annotations == nil {
237260
found.Annotations = make(map[string]string)
238261
}
262+
// Pruning the Capsule quota annotations:
263+
// if the ResourceQuota is updated by removing some objects,
264+
// we could still have left-overs which could be misleading.
265+
// This will not lead to a reconciliation loop since the whole code is idempotent.
266+
for k := range found.Annotations {
267+
if (strings.HasPrefix(k, capsulev1beta2.HardCapsuleQuotaAnnotation) || strings.HasPrefix(k, capsulev1beta2.UsedCapsuleQuotaAnnotation)) && !annotationsToKeep.Has(k) {
268+
delete(found.Annotations, k)
269+
}
270+
}
271+
239272
found.Labels = rq.Labels
240273
if actualKey, keyErr := capsulev1beta2.UsedQuotaFor(resourceName); keyErr == nil {
241274
found.Annotations[actualKey] = actual.String()

0 commit comments

Comments
 (0)