Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support pod's namespace is empty in webhook #1413

Merged
merged 12 commits into from
Feb 4, 2022
2 changes: 1 addition & 1 deletion charts/fluid/fluid/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ version: 0.7.0

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application.
appVersion: 0.7.0-73135a0
appVersion: 0.7.0-e27fa8c
home: https://github.com/fluid-cloudnative/fluid
keywords:
- category:data
Expand Down
20 changes: 10 additions & 10 deletions charts/fluid/fluid/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ workdir: /tmp

dataset:
controller:
image: fluidcloudnative/dataset-controller:v0.7.0-73135a0
image: fluidcloudnative/dataset-controller:v0.7.0-e27fa8c

csi:
recoverFusePeriod: -1
Expand All @@ -15,7 +15,7 @@ csi:
registrar:
image: registry.aliyuncs.com/acs/csi-node-driver-registrar:v1.2.0
plugins:
image: fluidcloudnative/fluid-csi:v0.7.0-73135a0
image: fluidcloudnative/fluid-csi:v0.7.0-e27fa8c
kubelet:
rootDir: /var/lib/kubelet

Expand All @@ -28,9 +28,9 @@ runtime:
portRange: 20000-26000
enabled: true
init:
image: fluidcloudnative/init-users:v0.7.0-73135a0
image: fluidcloudnative/init-users:v0.7.0-e27fa8c
controller:
image: fluidcloudnative/alluxioruntime-controller:v0.7.0-73135a0
image: fluidcloudnative/alluxioruntime-controller:v0.7.0-e27fa8c
runtime:
image: registry.aliyuncs.com/alluxio/alluxio:release-2.7.2-SNAPSHOT-3714f2b
fuse:
Expand All @@ -44,32 +44,32 @@ runtime:
fuse:
image: registry.cn-shanghai.aliyuncs.com/jindofs/jindo-fuse:3.8.0
controller:
image: fluidcloudnative/jindoruntime-controller:v0.7.0-73135a0
image: fluidcloudnative/jindoruntime-controller:v0.7.0-e27fa8c
init:
portCheck:
enabled: false
image: fluidcloudnative/init-users:v0.7.0-73135a0
image: fluidcloudnative/init-users:v0.7.0-e27fa8c
goosefs:
runtimeWorkers: 3
portRange: 26000-32000
enabled: false
init:
image: fluidcloudnative/init-users:v0.7.0-73135a0
image: fluidcloudnative/init-users:v0.7.0-e27fa8c
controller:
image: fluidcloudnative/goosefsruntime-controller:v0.7.0-73135a0
image: fluidcloudnative/goosefsruntime-controller:v0.7.0-e27fa8c
runtime:
image: ccr.ccs.tencentyun.com/qcloud/goosefs:v1.1.0-kona_jdk11
fuse:
image: ccr.ccs.tencentyun.com/qcloud/goosefs:v1.1.0-kona_jdk11
juicefs:
enabled: false
controller:
image: fluidcloudnative/juicefsruntime-controller:v0.7.0-73135a0
image: fluidcloudnative/juicefsruntime-controller:v0.7.0-e27fa8c
fuse:
image: juicedata/juicefs-csi-driver:v0.11.0

webhook:
enabled: true
image: fluidcloudnative/fluid-webhook:v0.7.0-73135a0
image: fluidcloudnative/fluid-webhook:v0.7.0-e27fa8c
replicas: 1

21 changes: 13 additions & 8 deletions pkg/webhook/scheduler/mutating/schedule_pod_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ func (a *CreateUpdatePodForSchedulingHandler) Handle(ctx context.Context, req ad
return admission.Errored(http.StatusBadRequest, err)
}

namespace := pod.Namespace
if len(namespace) == 0 {
namespace = req.Namespace
}

// check whether should inject
if common.CheckExpectValue(pod.Labels, common.EnableFluidInjectionFlag, common.False) {
setupLog.Info("skip mutating the pod because injection is disabled", "Pod", pod.Name, "Namespace", pod.Namespace)
Expand All @@ -69,7 +74,7 @@ func (a *CreateUpdatePodForSchedulingHandler) Handle(ctx context.Context, req ad
}

// inject affinity info into pod
err = a.AddScheduleInfoToPod(pod)
err = a.AddScheduleInfoToPod(pod, namespace)
if err != nil {
return admission.Errored(http.StatusInternalServerError, err)
}
Expand All @@ -90,23 +95,23 @@ func (a *CreateUpdatePodForSchedulingHandler) InjectDecoder(d *admission.Decoder
}

// AddScheduleInfoToPod will call all plugins to get total prefer info
func (a *CreateUpdatePodForSchedulingHandler) AddScheduleInfoToPod(pod *corev1.Pod) (err error) {
func (a *CreateUpdatePodForSchedulingHandler) AddScheduleInfoToPod(pod *corev1.Pod, namespace string) (err error) {
var setupLog = ctrl.Log.WithName("AddScheduleInfoToPod")
setupLog.Info("start to add schedule info", "Pod", pod.Name, "Namespace", pod.Namespace)
setupLog.Info("start to add schedule info", "Pod", pod.Name, "Namespace", namespace)
errPVCs := map[string]error{}
pvcNames := kubeclient.GetPVCNamesFromPod(pod)
var runtimeInfos map[string]base.RuntimeInfoInterface = map[string]base.RuntimeInfoInterface{}
for _, pvcName := range pvcNames {
isDatasetPVC, err := kubeclient.IsDatasetPVC(a.Client, pvcName, pod.Namespace)
isDatasetPVC, err := kubeclient.IsDatasetPVC(a.Client, pvcName, namespace)
if err != nil {
setupLog.Error(err, "unable to check pvc, will ignore it", "pvc", pvcName)
setupLog.Error(err, "unable to check pvc, will ignore it", "pvc", pvcName, "namespace", namespace)
errPVCs[pvcName] = err
continue
}
if isDatasetPVC {
runtimeInfo, err := base.GetRuntimeInfo(a.Client, pvcName, pod.Namespace)
runtimeInfo, err := base.GetRuntimeInfo(a.Client, pvcName, namespace)
if err != nil {
setupLog.Error(err, "unable to get runtimeInfo, get failure", "runtime", pvcName)
setupLog.Error(err, "unable to get runtimeInfo, get failure", "runtime", pvcName, "namespace", namespace)
return err
}
runtimeInfo.SetDeprecatedNodeLabel(false)
Expand All @@ -122,7 +127,7 @@ func (a *CreateUpdatePodForSchedulingHandler) AddScheduleInfoToPod(pod *corev1.P
if len(errPVCs) > 0 && utils.ServerlessEnabled(pod.GetLabels()) {
info := fmt.Sprintf("the pod %s in namespace %s is configured with (%s or %s) but without dataset enabling, and with errors %v",
pod.Name,
pod.Namespace,
namespace,
common.InjectServerless,
common.InjectFuseSidecar,
errPVCs)
Expand Down
92 changes: 91 additions & 1 deletion pkg/webhook/scheduler/mutating/schedule_pod_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@ limitations under the License.
package mutating

import (
"context"
"testing"

"github.com/fluid-cloudnative/fluid/pkg/common"
"github.com/fluid-cloudnative/fluid/pkg/utils/fake"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"

admissionv1 "k8s.io/api/admission/v1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -603,9 +607,95 @@ func TestAddScheduleInfoToPod(t *testing.T) {
Client: fakeClient,
}

err := handler.AddScheduleInfoToPod(testcase.in)
err := handler.AddScheduleInfoToPod(testcase.in, testcase.in.Namespace)
if !((err != nil) == testcase.wantErr) {
t.Errorf("testcase %s is failed due to error %v", testcase.name, err)
}
}
}

func TestHandle(t *testing.T) {
decoder, err := admission.NewDecoder(scheme.Scheme)
if err != nil {
t.Errorf("test failed due to err %v", err)
}

type testCase struct {
name string
req admission.Request
want bool
}

tests := []testCase{
{
name: "namespace_in_pod",
req: admission.Request{
AdmissionRequest: admissionv1.AdmissionRequest{
Namespace: "default",
Object: runtime.RawExtension{
Raw: []byte(
`{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "foo"
},
"spec": {
"containers": [
{
"image": "bar:v2",
"name": "bar"
}
]
}
}`),
},
},
},
want: true,
}, {
name: "namespace_not_in_pod",
req: admission.Request{
AdmissionRequest: admissionv1.AdmissionRequest{
Namespace: "default",
Object: runtime.RawExtension{
Raw: []byte(
`{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "foo"
},
"spec": {
"containers": [
{
"image": "bar:v2",
"name": "bar"
}
]
}
}`),
},
},
},
want: true,
},
}

objs := []runtime.Object{}
s := runtime.NewScheme()
fakeClient := fake.NewFakeClientWithScheme(s, objs...)

for _, test := range tests {
handler := &CreateUpdatePodForSchedulingHandler{
decoder: decoder,
}
handler.Setup(fakeClient)

resp := handler.Handle(context.TODO(), test.req)

if resp.AdmissionResponse.Allowed != test.want {
t.Errorf("test %s failed to get resp %v, want %v", test.name, resp, test.want)
}
}
}