Skip to content

Commit d0a2433

Browse files
authored
Adjust default PVC size to currently installed (#205)
1 parent fb86354 commit d0a2433

File tree

3 files changed

+205
-2
lines changed

3 files changed

+205
-2
lines changed

internal/chart/install.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package chart
22

33
import (
44
"fmt"
5+
"github.com/pkg/errors"
56

67
"github.com/kyma-project/serverless-manager/internal/annotation"
78
"helm.sh/helm/v3/pkg/release"
@@ -20,7 +21,7 @@ func install(config *Config, renderChartFunc func(config *Config) (*release.Rele
2021
return err
2122
}
2223

23-
objs, unusedObjs, err := getObjectsToUpdateAndRemove(cachedManifest, currentManifest)
24+
objs, unusedObjs, err := getObjectsToInstallAndRemove(cachedManifest, currentManifest)
2425
if err != nil {
2526
return err
2627
}
@@ -39,7 +40,7 @@ func install(config *Config, renderChartFunc func(config *Config) (*release.Rele
3940
})
4041
}
4142

42-
func getObjectsToUpdateAndRemove(cachedManifest string, currentManifest string) ([]unstructured.Unstructured, []unstructured.Unstructured, error) {
43+
func getObjectsToInstallAndRemove(cachedManifest string, currentManifest string) ([]unstructured.Unstructured, []unstructured.Unstructured, error) {
4344
objs, err := parseManifest(currentManifest)
4445
if err != nil {
4546
return nil, nil, fmt.Errorf("could not parse chart manifest: %s", err.Error())
@@ -60,6 +61,13 @@ func updateObjects(config *Config, objs []unstructured.Unstructured) error {
6061
config.Log.Debugf("creating %s %s/%s", u.GetKind(), u.GetNamespace(), u.GetName())
6162

6263
u = annotation.AddDoNotEditDisclaimer(u)
64+
if IsPVC(u.GroupVersionKind()) {
65+
modifiedObj, err := AdjustDockerRegToClusterPVCSize(config.Ctx, config.Cluster.Client, u)
66+
if err != nil {
67+
return errors.Wrap(err, "while adjusting pvc size")
68+
}
69+
u = modifiedObj
70+
}
6371

6472
// TODO: what if Path returns error in the middle of manifest?
6573
// maybe we should in this case translate applied objs into manifest and set it into cache?

internal/chart/pvc.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package chart
2+
3+
import (
4+
"context"
5+
"github.com/pkg/errors"
6+
corev1 "k8s.io/api/core/v1"
7+
k8serrors "k8s.io/apimachinery/pkg/api/errors"
8+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
9+
"k8s.io/apimachinery/pkg/runtime"
10+
"k8s.io/apimachinery/pkg/runtime/schema"
11+
"sigs.k8s.io/controller-runtime/pkg/client"
12+
)
13+
14+
const (
15+
dockerRegistryPVCName = "serverless-docker-registry"
16+
pvcKind = "PersistentVolumeClaim"
17+
pvcVersion = "v1"
18+
pvcGroup = ""
19+
)
20+
21+
func AdjustDockerRegToClusterPVCSize(ctx context.Context, c client.Client, obj unstructured.Unstructured) (unstructured.Unstructured, error) {
22+
if obj.GetName() != dockerRegistryPVCName {
23+
return obj, nil
24+
}
25+
clusterPVC := corev1.PersistentVolumeClaim{}
26+
err := c.Get(ctx, client.ObjectKey{
27+
Namespace: obj.GetNamespace(),
28+
Name: obj.GetName(),
29+
}, &clusterPVC)
30+
if err != nil {
31+
if k8serrors.IsNotFound(err) {
32+
return obj, nil
33+
}
34+
return obj, errors.Wrap(err, "while getting pvc from cluster")
35+
}
36+
objPVC := corev1.PersistentVolumeClaim{}
37+
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, &objPVC); err != nil {
38+
return obj, errors.Wrap(err, "while converting unstructured to pvc")
39+
}
40+
storage := clusterPVC.Spec.Resources.Requests.Storage()
41+
if storage.Equal(*objPVC.Spec.Resources.Requests.Storage()) {
42+
return obj, nil
43+
}
44+
objPVCcopy := objPVC.DeepCopy()
45+
objPVCcopy.Spec.Resources.Requests[corev1.ResourceStorage] = *clusterPVC.Spec.Resources.Requests.Storage()
46+
47+
out, err := runtime.DefaultUnstructuredConverter.ToUnstructured(objPVCcopy)
48+
if err != nil {
49+
return obj, errors.Wrap(err, "while converting copied pvc object to unstructured")
50+
}
51+
52+
return unstructured.Unstructured{Object: out}, nil
53+
}
54+
55+
func IsPVC(objKind schema.GroupVersionKind) bool {
56+
expected := schema.GroupVersionKind{
57+
Group: pvcGroup,
58+
Version: pvcVersion,
59+
Kind: pvcKind,
60+
}
61+
62+
return expected.Group == objKind.Group && expected.Kind == objKind.Kind && expected.Version == objKind.Version
63+
}

internal/chart/pvc_test.go

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package chart
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"github.com/stretchr/testify/require"
7+
corev1 "k8s.io/api/core/v1"
8+
"k8s.io/apimachinery/pkg/api/resource"
9+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
11+
"k8s.io/apimachinery/pkg/runtime"
12+
"k8s.io/apimachinery/pkg/runtime/schema"
13+
"sigs.k8s.io/controller-runtime/pkg/client"
14+
"sigs.k8s.io/controller-runtime/pkg/client/fake"
15+
"testing"
16+
)
17+
18+
func TestAdjustToClusterSize(t *testing.T) {
19+
testCases := map[string]struct {
20+
rawPVCToInstall *corev1.PersistentVolumeClaim
21+
clusterPVC []client.Object
22+
expectedPVC *corev1.PersistentVolumeClaim
23+
}{
24+
"pvc not exists in cluster": {
25+
rawPVCToInstall: fixPVC(dockerRegistryPVCName, 20),
26+
expectedPVC: fixPVC(dockerRegistryPVCName, 20),
27+
},
28+
"pvc is not docker registry": {
29+
rawPVCToInstall: fixPVC("random-pvc", 20),
30+
expectedPVC: fixPVC("random-pvc", 20),
31+
},
32+
"pvc exists with the same size": {
33+
rawPVCToInstall: fixPVC(dockerRegistryPVCName, 20),
34+
clusterPVC: []client.Object{fixPVC(dockerRegistryPVCName, 20)},
35+
expectedPVC: fixPVC(dockerRegistryPVCName, 20),
36+
},
37+
"pvc exists with bigger size": {
38+
rawPVCToInstall: fixPVC(dockerRegistryPVCName, 20),
39+
clusterPVC: []client.Object{fixPVC(dockerRegistryPVCName, 30)},
40+
expectedPVC: fixPVC(dockerRegistryPVCName, 30),
41+
},
42+
}
43+
44+
for name, testCase := range testCases {
45+
t.Run(name, func(t *testing.T) {
46+
//GIVEN
47+
out, err := runtime.DefaultUnstructuredConverter.ToUnstructured(testCase.rawPVCToInstall)
48+
require.NoError(t, err)
49+
obj := unstructured.Unstructured{Object: out}
50+
51+
c := fake.NewClientBuilder().WithObjects(testCase.clusterPVC...).Build()
52+
53+
//WHEN
54+
finalObj, err := AdjustDockerRegToClusterPVCSize(context.TODO(), c, obj)
55+
56+
//THEN
57+
require.NoError(t, err)
58+
59+
expected, err := runtime.DefaultUnstructuredConverter.ToUnstructured(testCase.expectedPVC)
60+
61+
require.NoError(t, err)
62+
require.EqualValues(t, expected, finalObj.Object)
63+
})
64+
}
65+
}
66+
67+
func fixPVC(name string, size int) *corev1.PersistentVolumeClaim {
68+
return &corev1.PersistentVolumeClaim{
69+
ObjectMeta: metav1.ObjectMeta{
70+
Name: name,
71+
Namespace: "kyma-system",
72+
},
73+
Spec: corev1.PersistentVolumeClaimSpec{
74+
Resources: corev1.ResourceRequirements{
75+
Requests: corev1.ResourceList{
76+
corev1.ResourceStorage: resource.MustParse(fmt.Sprintf("%dGi", size)),
77+
},
78+
},
79+
},
80+
}
81+
}
82+
83+
func TestIsPVC(t *testing.T) {
84+
testCases := map[string]struct {
85+
input schema.GroupVersionKind
86+
expected bool
87+
}{
88+
"Equal": {
89+
input: schema.GroupVersionKind{
90+
Group: "",
91+
Version: "v1",
92+
Kind: "PersistentVolumeClaim",
93+
},
94+
expected: true,
95+
},
96+
"Different kind": {
97+
input: schema.GroupVersionKind{
98+
Group: "",
99+
Version: "v1",
100+
Kind: "Pod",
101+
},
102+
expected: false,
103+
},
104+
"Different version": {
105+
input: schema.GroupVersionKind{
106+
Group: "",
107+
Version: "v2alpha1",
108+
Kind: "PersistentVolumeClaim",
109+
},
110+
expected: false,
111+
},
112+
"Different group": {
113+
input: schema.GroupVersionKind{
114+
Group: "networking",
115+
Version: "v1",
116+
Kind: "NetworkPolicy",
117+
},
118+
expected: false,
119+
},
120+
}
121+
122+
for name, testCase := range testCases {
123+
t.Run(name, func(t *testing.T) {
124+
//GIVEN
125+
126+
//WHEN
127+
equal := IsPVC(testCase.input)
128+
//THEN
129+
require.Equal(t, testCase.expected, equal)
130+
})
131+
}
132+
}

0 commit comments

Comments
 (0)