Skip to content

Commit

Permalink
feat: adds auto scale padding
Browse files Browse the repository at this point in the history
  • Loading branch information
AntiTyping committed Sep 26, 2023
1 parent f240661 commit d5edc80
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 23 deletions.
24 changes: 22 additions & 2 deletions internal/fullnode/pvc_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}
)
Expand Down Expand Up @@ -79,9 +85,23 @@ 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
// This is the implementation using Int64 but it does not support fractions
//requestSize, unableToConvert := autoScale.RequestedSize.AsInt64()
//if unableToConvert == true {
// fmt.Errorf("Unable to convert auto scale request")
//} else {
// sizeWithPadding := resource.NewQuantity(int64(float64(requestSize)*SnapshotScalingFactor), resource.DecimalSI)
// if sizeWithPadding.Cmp(size) > 0 {
// reqs.Requests[corev1.ResourceStorage] = *sizeWithPadding
// }
//}
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
Expand Down
106 changes: 85 additions & 21 deletions internal/fullnode/pvc_builder_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fullnode

import (
"encoding/json"
"fmt"
"strings"
"testing"
Expand All @@ -15,6 +16,14 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
)

func PrettyStruct(data interface{}) (string, error) {
val, err := json.MarshalIndent(data, "", " ")
if err != nil {
return "", err
}
return string(val), nil
}

func TestBuildPVCs(t *testing.T) {
t.Parallel()

Expand All @@ -28,11 +37,15 @@ func TestBuildPVCs(t *testing.T) {
Requests: corev1.ResourceList{corev1.ResourceStorage: resource.MustParse("100G")},
},
}

//println(PrettyStruct(crd.Spec.VolumeClaimTemplate))

crd.Spec.InstanceOverrides = map[string]cosmosv1.InstanceOverridesSpec{
"juno-0": {},
}

for i, r := range BuildPVCs(&crd) {
//println(PrettyStruct(r.Object()))
require.Equal(t, int64(i), r.Ordinal())
require.NotEmpty(t, r.Revision())
}
Expand Down Expand Up @@ -148,30 +161,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 {
Expand Down

0 comments on commit d5edc80

Please sign in to comment.