-
Notifications
You must be signed in to change notification settings - Fork 434
/
vip.go
93 lines (80 loc) · 2.71 KB
/
vip.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package webhook
import (
"context"
"fmt"
ovnv1 "github.com/kubeovn/kube-ovn/pkg/apis/kubeovn/v1"
"github.com/kubeovn/kube-ovn/pkg/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"net"
"net/http"
"reflect"
ctrlwebhook "sigs.k8s.io/controller-runtime/pkg/webhook"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)
var vipGVK = metav1.GroupVersionKind{Group: ovnv1.SchemeGroupVersion.Group, Version: ovnv1.SchemeGroupVersion.Version, Kind: "Vip"}
func (v *ValidatingHook) VipCreateHook(ctx context.Context, req admission.Request) admission.Response {
vip := ovnv1.Vip{}
if err := v.decoder.DecodeRaw(req.Object, &vip); err != nil {
return ctrlwebhook.Errored(http.StatusBadRequest, err)
}
if err := v.ValidateVip(ctx, &vip); err != nil {
return ctrlwebhook.Errored(http.StatusBadRequest, err)
}
return ctrlwebhook.Allowed("by pass")
}
func (v *ValidatingHook) VipUpdateHook(ctx context.Context, req admission.Request) admission.Response {
vipOld := ovnv1.Vip{}
if err := v.decoder.DecodeRaw(req.OldObject, &vipOld); err != nil {
return ctrlwebhook.Errored(http.StatusBadRequest, err)
}
vipNew := ovnv1.Vip{}
if err := v.decoder.DecodeRaw(req.Object, &vipNew); err != nil {
return ctrlwebhook.Errored(http.StatusBadRequest, err)
}
if !reflect.DeepEqual(vipNew.Spec, vipOld.Spec) {
if vipOld.Status.Mac == "" {
if err := v.ValidateVip(ctx, &vipNew); err != nil {
return ctrlwebhook.Errored(http.StatusBadRequest, err)
}
} else {
err := fmt.Errorf("vip has been assigned,not support change")
return ctrlwebhook.Errored(http.StatusBadRequest, err)
}
}
return ctrlwebhook.Allowed("by pass")
}
func (v *ValidatingHook) ValidateVip(ctx context.Context, vip *ovnv1.Vip) error {
if vip.Spec.Subnet == "" {
err := fmt.Errorf("subnet parameter cannot be empty")
return err
}
subnet := &ovnv1.Subnet{}
key := types.NamespacedName{Name: vip.Spec.Subnet}
if err := v.cache.Get(ctx, key, subnet); err != nil {
return err
}
if vip.Spec.V4ip != "" {
if net.ParseIP(vip.Spec.V4ip) == nil {
err := fmt.Errorf("%s is not a valid ip", vip.Spec.V4ip)
return err
}
if !util.CIDRContainIP(subnet.Spec.CIDRBlock, vip.Spec.V4ip) {
err := fmt.Errorf("the V4ip %s is not in the range of subnet %s, cidr %v",
vip.Spec.V4ip, subnet.Name, subnet.Spec.CIDRBlock)
return err
}
}
if vip.Spec.V6ip != "" {
if net.ParseIP(vip.Spec.V6ip) == nil {
err := fmt.Errorf("%s is not a valid ip", vip.Spec.V6ip)
return err
}
if !util.CIDRContainIP(subnet.Spec.CIDRBlock, vip.Spec.V6ip) {
err := fmt.Errorf("the vip %s is not in the range of subnet %s, cidr %v",
vip.Spec.V6ip, subnet.Name, subnet.Spec.CIDRBlock)
return err
}
}
return nil
}