Skip to content

Commit 03d5e48

Browse files
author
jiuyu
committed
Feature: support to skip the validation of indirectly related resources involved in webhook mutating
Signed-off-by: jiuyu <guotongyu.gty@alibaba-inc.com>
1 parent 4e199c8 commit 03d5e48

File tree

14 files changed

+279
-246
lines changed

14 files changed

+279
-246
lines changed

pkg/application/inject/fuse/injector.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,10 @@ func (s *Injector) inject(in runtime.Object, runtimeInfos map[string]base.Runtim
172172
Log: s.log,
173173
Specs: podSpecs,
174174
Options: common.FuseSidecarInjectOption{
175-
EnableCacheDir: utils.InjectCacheDirEnabled(podSpecs.MetaObj.Labels),
176-
EnableUnprivilegedSidecar: utils.FuseSidecarUnprivileged(podSpecs.MetaObj.Labels),
177-
SkipSidecarPostStartInject: utils.SkipSidecarPostStartInject(podSpecs.MetaObj.Labels),
175+
EnableCacheDir: utils.InjectCacheDirEnabled(podSpecs.MetaObj.Labels),
176+
EnableUnprivilegedSidecar: utils.FuseSidecarUnprivileged(podSpecs.MetaObj.Labels),
177+
SkipSidecarPostStartInject: utils.SkipSidecarPostStartInject(podSpecs.MetaObj.Labels),
178+
SkipIndirectlyRelatedResourceValidation: utils.SkipIndirectlyRelatedResourceValidationEnable(podSpecs.MetaObj.Annotations),
178179
},
179180
ExtraArgs: mutator.FindExtraArgsFromMetadata(podSpecs.MetaObj, platform),
180181
}
@@ -258,5 +259,5 @@ func (s *Injector) shouldInject(pod common.FluidObject) (should bool, err error)
258259
}
259260

260261
func (s *Injector) getServerlessPlatformFromMeta(metaObj metav1.ObjectMeta) string {
261-
return utils.GetServerlessPlatfrom(metaObj.Labels)
262+
return utils.GetServerlessPlatform(metaObj.Labels)
262263
}

pkg/application/inject/fuse/mutator/mutator_default.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ func NewDefaultMutator(args MutatorBuildArgs) Mutator {
6868
var _ Mutator = &DefaultMutator{}
6969

7070
func (mutator *DefaultMutator) MutateWithRuntimeInfo(pvcName string, runtimeInfo base.RuntimeInfoInterface, nameSuffix string) error {
71-
template, err := runtimeInfo.GetFuseContainerTemplate()
71+
template, err := runtimeInfo.GetFuseContainerTemplate(mutator.options.SkipIndirectlyRelatedResourceValidation)
7272
if err != nil {
7373
return errors.Wrapf(err, "failed to get fuse container template for runtime \"%s/%s\"", runtimeInfo.GetNamespace(), runtimeInfo.GetName())
7474
}

pkg/application/inject/fuse/mutator/mutator_unprivileged.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func NewUnprivilegedMutator(opts MutatorBuildArgs) Mutator {
4848
}
4949

5050
func (mutator *UnprivilegedMutator) MutateWithRuntimeInfo(pvcName string, runtimeInfo base.RuntimeInfoInterface, nameSuffix string) error {
51-
template, err := runtimeInfo.GetFuseContainerTemplate()
51+
template, err := runtimeInfo.GetFuseContainerTemplate(mutator.options.SkipIndirectlyRelatedResourceValidation)
5252
if err != nil {
5353
return errors.Wrapf(err, "failed to get fuse container template for runtime \"%s/%s\"", runtimeInfo.GetNamespace(), runtimeInfo.GetName())
5454
}

pkg/common/constants.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,7 @@ const (
212212
K8sZoneLabelKey = "topology.kubernetes.io/zone"
213213
K8sRegionLabelKey = "topology.kubernetes.io/region"
214214
)
215+
216+
const (
217+
SkipResourceValidationAnnotationKey = "sidecar.fluid.io/skip-resource-validation"
218+
)

pkg/common/types.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,10 @@ type FuseMountInfo struct {
168168

169169
// FuseSidecarInjectOption are options for webhook to inject fuse sidecar containers
170170
type FuseSidecarInjectOption struct {
171-
EnableCacheDir bool
172-
EnableUnprivilegedSidecar bool
173-
SkipSidecarPostStartInject bool
171+
EnableCacheDir bool
172+
EnableUnprivilegedSidecar bool
173+
SkipSidecarPostStartInject bool
174+
SkipIndirectlyRelatedResourceValidation bool
174175
}
175176

176177
func (f FuseSidecarInjectOption) String() string {

pkg/ddc/base/runtime.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ type RuntimeInfoInterface interface {
8989

9090
IsDeprecatedPVName() bool
9191

92-
GetFuseContainerTemplate() (template *common.FuseInjectionTemplate, err error)
92+
GetFuseContainerTemplate(skipRelatedResourceCheck bool) (template *common.FuseInjectionTemplate, err error)
9393

9494
SetClient(client client.Client)
9595

pkg/ddc/base/runtime_helper.go

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,18 @@ import (
2020
"fmt"
2121
"time"
2222

23-
"github.com/fluid-cloudnative/fluid/pkg/utils"
24-
"github.com/fluid-cloudnative/fluid/pkg/utils/kubeclient"
2523
"github.com/pkg/errors"
2624
appsv1 "k8s.io/api/apps/v1"
25+
corev1 "k8s.io/api/core/v1"
2726

2827
"github.com/fluid-cloudnative/fluid/pkg/common"
28+
"github.com/fluid-cloudnative/fluid/pkg/utils"
29+
"github.com/fluid-cloudnative/fluid/pkg/utils/kubeclient"
2930
)
3031

3132
// GetFuseContainerTemplate collects the fuse container spec from the runtime's fuse daemonSet spec. The function summarizes fuse related information into
3233
// the template and returns it. The template then can be freely modified according to need of the serverless platform.
33-
func (info *RuntimeInfo) GetFuseContainerTemplate() (template *common.FuseInjectionTemplate, err error) {
34+
func (info *RuntimeInfo) GetFuseContainerTemplate(skipIndirectlyRelatedResourceValidation bool) (template *common.FuseInjectionTemplate, err error) {
3435
if utils.IsTimeTrackerDebugEnabled() {
3536
defer utils.TimeTrack(time.Now(), "RuntimeInfo.GetFuseContainerTemplate",
3637
"runtime.name", info.name, "runtime.namespace", info.namespace)
@@ -52,7 +53,11 @@ func (info *RuntimeInfo) GetFuseContainerTemplate() (template *common.FuseInject
5253

5354
template.FuseContainer.Name = common.FuseContainerName
5455

55-
hostMountPath, mountType, subPath, err := kubeclient.GetMountInfoFromVolumeClaim(info.client, info.name, info.namespace)
56+
hostMountPath, mountType, subPath, err := info.getMountInfo(skipIndirectlyRelatedResourceValidation)
57+
if err != nil {
58+
return template, errors.Wrapf(err, "failed to get mount info")
59+
}
60+
5661
if err != nil {
5762
return template, errors.Wrapf(err, "failed get mount info from PVC \"%s/%s\"", info.namespace, info.name)
5863
}
@@ -87,3 +92,35 @@ func (info *RuntimeInfo) getFuseDaemonset() (ds *appsv1.DaemonSet, err error) {
8792
}
8893
return kubeclient.GetDaemonset(info.client, fuseName, info.GetNamespace())
8994
}
95+
96+
func (info *RuntimeInfo) getMountInfo(skipUnnecessaryResourceValidation bool) (path, mountType, subpath string, err error) {
97+
var pv *corev1.PersistentVolume
98+
99+
pvName := info.GetPersistentVolumeName()
100+
101+
if !skipUnnecessaryResourceValidation {
102+
var pvc *corev1.PersistentVolumeClaim
103+
pvc, err = kubeclient.GetPersistentVolumeClaim(info.client, info.name, info.namespace)
104+
if err != nil {
105+
err = errors.Wrapf(err, "failed to get persistent volume claim %s/%s", info.namespace, info.name)
106+
return
107+
}
108+
pvName = pvc.Spec.VolumeName
109+
}
110+
111+
pv, err = kubeclient.GetPersistentVolume(info.client, pvName)
112+
if err != nil {
113+
err = errors.Wrapf(err, "cannot find pvc \"%s/%s\"'s bounded PV", info.namespace, info.name)
114+
return
115+
}
116+
117+
if pv.Spec.CSI != nil && len(pv.Spec.CSI.VolumeAttributes) > 0 {
118+
path = pv.Spec.CSI.VolumeAttributes[common.VolumeAttrFluidPath]
119+
mountType = pv.Spec.CSI.VolumeAttributes[common.VolumeAttrMountType]
120+
subpath = pv.Spec.CSI.VolumeAttributes[common.VolumeAttrFluidSubPath]
121+
} else {
122+
err = fmt.Errorf("the pv %s is not created by fluid", pv.Name)
123+
}
124+
125+
return
126+
}

pkg/ddc/base/runtime_helper_test.go

Lines changed: 192 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,27 @@ import (
2222
datav1alpha1 "github.com/fluid-cloudnative/fluid/api/v1alpha1"
2323
"github.com/fluid-cloudnative/fluid/pkg/common"
2424
"github.com/fluid-cloudnative/fluid/pkg/utils/fake"
25-
"sigs.k8s.io/controller-runtime/pkg/client"
26-
2725
appsv1 "k8s.io/api/apps/v1"
26+
batchv1 "k8s.io/api/batch/v1"
2827
corev1 "k8s.io/api/core/v1"
28+
rbacv1 "k8s.io/api/rbac/v1"
2929
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
30-
3130
"k8s.io/apimachinery/pkg/runtime"
31+
"sigs.k8s.io/controller-runtime/pkg/client"
32+
)
33+
34+
var (
35+
testScheme *runtime.Scheme
3236
)
3337

38+
func init() {
39+
testScheme = runtime.NewScheme()
40+
_ = corev1.AddToScheme(testScheme)
41+
_ = rbacv1.AddToScheme(testScheme)
42+
_ = appsv1.AddToScheme(testScheme)
43+
_ = batchv1.AddToScheme(testScheme)
44+
}
45+
3446
// func TestGetTemplateToInjectForFuse(t *testing.T) {
3547
// type runtimeInfo struct {
3648
// name string
@@ -1169,3 +1181,180 @@ func TestGetFuseDaemonset(t *testing.T) {
11691181
}
11701182
}
11711183
}
1184+
1185+
func TestGetMountInfoFromVolumeClaim(t *testing.T) {
1186+
namespace := "default"
1187+
testPVCInputs := []*corev1.PersistentVolumeClaim{{
1188+
ObjectMeta: metav1.ObjectMeta{Name: "fluidpvc",
1189+
Namespace: namespace},
1190+
Spec: corev1.PersistentVolumeClaimSpec{
1191+
VolumeName: "fluidpv",
1192+
},
1193+
}, {
1194+
ObjectMeta: metav1.ObjectMeta{Name: "nonfluidpvc",
1195+
Annotations: common.ExpectedFluidAnnotations,
1196+
Namespace: namespace},
1197+
Spec: corev1.PersistentVolumeClaimSpec{
1198+
VolumeName: "nonfluidpv",
1199+
},
1200+
}, {
1201+
ObjectMeta: metav1.ObjectMeta{Name: "nopv",
1202+
Annotations: common.ExpectedFluidAnnotations,
1203+
Namespace: namespace},
1204+
Spec: corev1.PersistentVolumeClaimSpec{
1205+
VolumeName: "nopv",
1206+
},
1207+
}, {
1208+
ObjectMeta: metav1.ObjectMeta{Name: "subpvc",
1209+
Annotations: common.ExpectedFluidAnnotations,
1210+
Namespace: namespace},
1211+
Spec: corev1.PersistentVolumeClaimSpec{
1212+
VolumeName: "subpv",
1213+
},
1214+
}}
1215+
1216+
objs := []runtime.Object{}
1217+
1218+
for _, pvc := range testPVCInputs {
1219+
objs = append(objs, pvc.DeepCopy())
1220+
}
1221+
1222+
testPVInputs := []*corev1.PersistentVolume{{
1223+
ObjectMeta: metav1.ObjectMeta{Name: "fluidpv"},
1224+
Spec: corev1.PersistentVolumeSpec{
1225+
PersistentVolumeSource: corev1.PersistentVolumeSource{
1226+
CSI: &corev1.CSIPersistentVolumeSource{
1227+
Driver: "fuse.csi.fluid.io",
1228+
VolumeAttributes: map[string]string{
1229+
common.VolumeAttrFluidPath: "/runtime-mnt/jindo/big-data/nofounddataset/jindofs-fuse",
1230+
common.VolumeAttrMountType: common.JindoRuntime,
1231+
},
1232+
},
1233+
},
1234+
},
1235+
}, {
1236+
ObjectMeta: metav1.ObjectMeta{Name: "nonfluidpv", Annotations: common.ExpectedFluidAnnotations},
1237+
Spec: corev1.PersistentVolumeSpec{},
1238+
}, {
1239+
ObjectMeta: metav1.ObjectMeta{Name: "subpv"},
1240+
Spec: corev1.PersistentVolumeSpec{
1241+
PersistentVolumeSource: corev1.PersistentVolumeSource{
1242+
CSI: &corev1.CSIPersistentVolumeSource{
1243+
Driver: "fuse.csi.fluid.io",
1244+
VolumeAttributes: map[string]string{
1245+
common.VolumeAttrFluidPath: "/runtime-mnt/jindo/big-data/nofounddataset/jindofs-fuse",
1246+
common.VolumeAttrMountType: common.JindoRuntime,
1247+
common.VolumeAttrFluidSubPath: "subtest",
1248+
},
1249+
},
1250+
},
1251+
},
1252+
}}
1253+
1254+
for _, pv := range testPVInputs {
1255+
objs = append(objs, pv.DeepCopy())
1256+
}
1257+
1258+
client := fake.NewFakeClientWithScheme(testScheme, objs...)
1259+
1260+
type args struct {
1261+
name string
1262+
namespace string
1263+
}
1264+
tests := []struct {
1265+
name string
1266+
args args
1267+
wantError bool
1268+
wantPath string
1269+
wantType string
1270+
wantSubPath string
1271+
}{{
1272+
name: "volumeClaim doesn't exist",
1273+
args: args{
1274+
name: "notExist",
1275+
namespace: namespace,
1276+
},
1277+
wantError: true,
1278+
}, {
1279+
name: "non fluid pv",
1280+
args: args{
1281+
name: "nonfluidpvc",
1282+
namespace: namespace,
1283+
},
1284+
wantError: true,
1285+
}, {
1286+
name: " fluid pv",
1287+
args: args{
1288+
name: "fluidpvc",
1289+
namespace: namespace,
1290+
},
1291+
wantError: false,
1292+
wantPath: "/runtime-mnt/jindo/big-data/nofounddataset/jindofs-fuse",
1293+
wantType: common.JindoRuntime,
1294+
}, {
1295+
name: "no pv",
1296+
args: args{
1297+
name: "nopv",
1298+
namespace: namespace,
1299+
},
1300+
wantError: true,
1301+
}, {
1302+
name: "sub pv",
1303+
args: args{
1304+
name: "subpvc",
1305+
namespace: namespace,
1306+
},
1307+
wantError: false,
1308+
wantPath: "/runtime-mnt/jindo/big-data/nofounddataset/jindofs-fuse",
1309+
wantType: common.JindoRuntime,
1310+
wantSubPath: "subtest",
1311+
}}
1312+
1313+
for _, tt := range tests {
1314+
t.Run(tt.name, func(t *testing.T) {
1315+
runtimeInfo := RuntimeInfo{
1316+
name: tt.args.name,
1317+
namespace: tt.args.namespace,
1318+
runtimeType: common.JindoRuntime,
1319+
client: client,
1320+
}
1321+
1322+
path, mountType, subpath, err := runtimeInfo.getMountInfo(false)
1323+
got := err != nil
1324+
1325+
if got != tt.wantError {
1326+
t.Errorf("testcase %v GetMountInfoFromVolumeClaim() for %v in %v = %v, err = %v", tt.name,
1327+
tt.args.name,
1328+
tt.args.namespace,
1329+
got,
1330+
err)
1331+
}
1332+
1333+
if path != tt.wantPath {
1334+
t.Errorf("testcase %v GetMountInfoFromVolumeClaim() for %v in %v got path %v, want path = %v", tt.name,
1335+
tt.args.name,
1336+
tt.args.namespace,
1337+
path,
1338+
tt.wantPath)
1339+
}
1340+
1341+
if mountType != tt.wantType {
1342+
t.Errorf("testcase %v GetMountInfoFromVolumeClaim() for %v in %v got mountType %v, want mountType = %v", tt.name,
1343+
tt.args.name,
1344+
tt.args.namespace,
1345+
mountType,
1346+
tt.wantType)
1347+
}
1348+
1349+
if subpath != tt.wantSubPath {
1350+
t.Errorf("testcase %v GetMountInfoFromVolumeClaim() for %v in %v got subpath %v, want subpath = %v", tt.name,
1351+
tt.args.name,
1352+
tt.args.namespace,
1353+
subpath,
1354+
tt.wantSubPath)
1355+
}
1356+
1357+
})
1358+
}
1359+
1360+
}

pkg/utils/annotations.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ const (
7575
PlatformUnprivileged = "Unprivileged"
7676
)
7777

78-
func GetServerlessPlatfrom(infos map[string]string) (platform string) {
78+
func GetServerlessPlatform(infos map[string]string) (platform string) {
7979
if matchedKey(infos, ServerlessPlatformKey) {
8080
return infos[ServerlessPlatformKey]
8181
}
@@ -129,6 +129,10 @@ func serverlessPlatformMatched(infos map[string]string) (match bool) {
129129
return matchedKey(infos, ServerlessPlatformKey)
130130
}
131131

132+
func SkipIndirectlyRelatedResourceValidationEnable(infos map[string]string) (match bool) {
133+
return enabled(infos, common.SkipResourceValidationAnnotationKey)
134+
}
135+
132136
// enabled checks if the given name has a value of "true"
133137
func enabled(infos map[string]string, name string) (match bool) {
134138
return matchedValue(infos, name, common.True)

0 commit comments

Comments
 (0)