From 23d43aba91fc1ad4e699cbcdbffd7f1cd6231e0a Mon Sep 17 00:00:00 2001 From: Andy Pliszka Date: Mon, 16 Oct 2023 10:34:33 -0400 Subject: [PATCH] feat: adds auto scale padding (#362) * feat: adds auto scale padding * fix: makes constant hidden --- internal/fullnode/pvc_builder.go | 14 +++- internal/fullnode/pvc_builder_test.go | 94 +++++++++++++++++++++------ 2 files changed, 85 insertions(+), 23 deletions(-) diff --git a/internal/fullnode/pvc_builder.go b/internal/fullnode/pvc_builder.go index 5720265a..12f113c0 100644 --- a/internal/fullnode/pvc_builder.go +++ b/internal/fullnode/pvc_builder.go @@ -6,10 +6,16 @@ import ( cosmosv1 "github.com/strangelove-ventures/cosmos-operator/api/v1" "github.com/strangelove-ventures/cosmos-operator/internal/diff" "github.com/strangelove-ventures/cosmos-operator/internal/kube" + "gopkg.in/inf.v0" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +const ( + snapshotGrowthFactor = 102 +) + var ( defaultAccessModes = []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce} ) @@ -79,9 +85,13 @@ func pvcResources(crd *cosmosv1.CosmosFullNode) corev1.ResourceRequirements { reqs = crd.Spec.VolumeClaimTemplate.Resources size = reqs.Requests[corev1.ResourceStorage] ) + if autoScale := crd.Status.SelfHealing.PVCAutoScale; autoScale != nil { - if autoScale.RequestedSize.Cmp(size) > 0 { - reqs.Requests[corev1.ResourceStorage] = autoScale.RequestedSize + requestedSize := autoScale.RequestedSize.DeepCopy() + newSize := requestedSize.AsDec() + sizeWithPadding := resource.NewDecimalQuantity(*newSize.Mul(newSize, inf.NewDec(snapshotGrowthFactor, 2)), resource.DecimalSI) + if sizeWithPadding.Cmp(size) > 0 { + reqs.Requests[corev1.ResourceStorage] = *sizeWithPadding } } return reqs diff --git a/internal/fullnode/pvc_builder_test.go b/internal/fullnode/pvc_builder_test.go index 8cd9acf6..26cdb51e 100644 --- a/internal/fullnode/pvc_builder_test.go +++ b/internal/fullnode/pvc_builder_test.go @@ -28,6 +28,7 @@ func TestBuildPVCs(t *testing.T) { Requests: corev1.ResourceList{corev1.ResourceStorage: resource.MustParse("100G")}, }, } + crd.Spec.InstanceOverrides = map[string]cosmosv1.InstanceOverridesSpec{ "juno-0": {}, } @@ -148,30 +149,81 @@ func TestBuildPVCs(t *testing.T) { } }) - t.Run("pvc auto scale", func(t *testing.T) { - for _, tt := range []struct { - SpecQuant, AutoScaleQuant, WantQuant string - }{ - {"100G", "99G", "100G"}, - {"100G", "101G", "101G"}, - } { - crd := defaultCRD() - crd.Spec.Replicas = 1 - crd.Spec.VolumeClaimTemplate = cosmosv1.PersistentVolumeClaimSpec{ - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{corev1.ResourceStorage: resource.MustParse(tt.SpecQuant)}, - }, - } - crd.Status.SelfHealing.PVCAutoScale = &cosmosv1.PVCAutoScaleStatus{ - RequestedSize: resource.MustParse(tt.AutoScaleQuant), + t.Run("pvc auto scale with padding", func(t *testing.T) { + t.Run("given auto scale size less then current size", func(t *testing.T) { + for _, tt := range []struct { + SpecQuant, AutoScaleQuant, WantQuant string + }{ + {"100G", "97G", "100G"}, + } { + crd := defaultCRD() + crd.Spec.Replicas = 1 + crd.Spec.VolumeClaimTemplate = cosmosv1.PersistentVolumeClaimSpec{ + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{corev1.ResourceStorage: resource.MustParse(tt.SpecQuant)}, + }, + } + crd.Status.SelfHealing.PVCAutoScale = &cosmosv1.PVCAutoScaleStatus{ + RequestedSize: resource.MustParse(tt.AutoScaleQuant), + } + + pvcs := BuildPVCs(&crd) + require.Len(t, pvcs, 1, tt) + + want := corev1.ResourceList{corev1.ResourceStorage: resource.MustParse(tt.WantQuant)} + require.Equal(t, want.Storage().Value(), pvcs[0].Object().Spec.Resources.Requests.Storage().Value(), tt) } + }) - pvcs := BuildPVCs(&crd) - require.Len(t, pvcs, 1, tt) + t.Run("given auto scale size equal to current size", func(t *testing.T) { + for _, tt := range []struct { + SpecQuant, AutoScaleQuant, WantQuant string + }{ + {"102G", "100G", "102G"}, + } { + crd := defaultCRD() + crd.Spec.Replicas = 1 + crd.Spec.VolumeClaimTemplate = cosmosv1.PersistentVolumeClaimSpec{ + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{corev1.ResourceStorage: resource.MustParse(tt.SpecQuant)}, + }, + } + crd.Status.SelfHealing.PVCAutoScale = &cosmosv1.PVCAutoScaleStatus{ + RequestedSize: resource.MustParse(tt.AutoScaleQuant), + } + + pvcs := BuildPVCs(&crd) + require.Len(t, pvcs, 1, tt) + + want := corev1.ResourceList{corev1.ResourceStorage: resource.MustParse(tt.WantQuant)} + require.Equal(t, want, pvcs[0].Object().Spec.Resources.Requests, tt) + } + }) - want := corev1.ResourceList{corev1.ResourceStorage: resource.MustParse(tt.WantQuant)} - require.Equal(t, want, pvcs[0].Object().Spec.Resources.Requests, tt) - } + t.Run("given auto scale size greater then current size", func(t *testing.T) { + for _, tt := range []struct { + SpecQuant, AutoScaleQuant, WantQuant string + }{ + {"100G", "100G", "102G"}, + } { + crd := defaultCRD() + crd.Spec.Replicas = 1 + crd.Spec.VolumeClaimTemplate = cosmosv1.PersistentVolumeClaimSpec{ + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{corev1.ResourceStorage: resource.MustParse(tt.SpecQuant)}, + }, + } + crd.Status.SelfHealing.PVCAutoScale = &cosmosv1.PVCAutoScaleStatus{ + RequestedSize: resource.MustParse(tt.AutoScaleQuant), + } + + pvcs := BuildPVCs(&crd) + require.Len(t, pvcs, 1, tt) + + want := corev1.ResourceList{corev1.ResourceStorage: resource.MustParse(tt.WantQuant)} + require.Equal(t, want.Storage().Value(), pvcs[0].Object().Spec.Resources.Requests.Storage().Value(), tt) + } + }) }) test.HasTypeLabel(t, func(crd cosmosv1.CosmosFullNode) []map[string]string {