diff --git a/pkg/webhook/validating_gss.go b/pkg/webhook/validating_gss.go index b74fa127..b96a8e76 100644 --- a/pkg/webhook/validating_gss.go +++ b/pkg/webhook/validating_gss.go @@ -20,6 +20,7 @@ import ( "context" "fmt" gamekruiseiov1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1" + "github.com/openkruise/kruise-game/cloudprovider/manager" "github.com/openkruise/kruise-game/pkg/util" admissionv1 "k8s.io/api/admission/v1" "net/http" @@ -28,8 +29,9 @@ import ( ) type GssValidaatingHandler struct { - Client client.Client - decoder *admission.Decoder + Client client.Client + decoder *admission.Decoder + CloudProviderManager *manager.ProviderManager } func (gvh *GssValidaatingHandler) Handle(ctx context.Context, req admission.Request) admission.Response { @@ -52,6 +54,9 @@ func (gvh *GssValidaatingHandler) Handle(ctx context.Context, req admission.Requ return admission.Errored(http.StatusBadRequest, err) } return validatingUpdate(newGss, oldGss) + case admissionv1.Create: + newGss := gss.DeepCopy() + return validatingCreate(newGss, gvh.CloudProviderManager) } return admission.ValidationResponse(true, "pass validating") @@ -78,3 +83,26 @@ func validatingUpdate(newGss, oldGss *gamekruiseiov1alpha1.GameServerSet) admiss } return admission.ValidationResponse(true, "validatingUpdate success") } + +func validatingCreate(gss *gamekruiseiov1alpha1.GameServerSet, cpm *manager.ProviderManager) admission.Response { + if gss.Spec.Network != nil { + if gss.Spec.Network.NetworkType == "" { + return admission.ValidationResponse(false, "network type is required") + } + if pn := listPluginNames(cpm); !util.IsStringInList(gss.Spec.Network.NetworkType, pn) { + return admission.ValidationResponse(false, fmt.Sprintf("network type must be one of %v", pn)) + } + } + return admission.ValidationResponse(true, "validatingCreate success") +} + +func listPluginNames(cpm *manager.ProviderManager) []string { + var pluginNames []string + for _, cp := range cpm.CloudProviders { + plugins, _ := cp.ListPlugins() + for _, p := range plugins { + pluginNames = append(pluginNames, p.Name()) + } + } + return pluginNames +} diff --git a/pkg/webhook/validating_gss_test.go b/pkg/webhook/validating_gss_test.go new file mode 100644 index 00000000..7ffd4b7b --- /dev/null +++ b/pkg/webhook/validating_gss_test.go @@ -0,0 +1,61 @@ +package webhook + +import ( + gamekruiseiov1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1" + "github.com/openkruise/kruise-game/cloudprovider" + "github.com/openkruise/kruise-game/cloudprovider/alibabacloud" + "github.com/openkruise/kruise-game/cloudprovider/manager" + "testing" +) + +func TestValidatingCreate(t *testing.T) { + tests := []struct { + gss *gamekruiseiov1alpha1.GameServerSet + cpm *manager.ProviderManager + allowed bool + }{ + { + gss: &gamekruiseiov1alpha1.GameServerSet{ + Spec: gamekruiseiov1alpha1.GameServerSetSpec{ + Network: &gamekruiseiov1alpha1.Network{ + NetworkConf: []gamekruiseiov1alpha1.NetworkConfParams{ + { + Name: "xx", + Value: "xx", + }, + }, + }, + }, + }, + cpm: &manager.ProviderManager{ + CloudProviders: map[string]cloudprovider.CloudProvider{}, + }, + allowed: false, + }, + { + gss: &gamekruiseiov1alpha1.GameServerSet{ + Spec: gamekruiseiov1alpha1.GameServerSetSpec{ + Network: &gamekruiseiov1alpha1.Network{ + NetworkType: "AlibabaCloud-LB", + }, + }, + }, + cpm: &manager.ProviderManager{ + CloudProviders: map[string]cloudprovider.CloudProvider{ + "AlibabaCloud": func() cloudprovider.CloudProvider { + acp, _ := alibabacloud.NewAlibabaCloudProvider() + return acp + }(), + }, + }, + allowed: false, + }, + } + + for i, test := range tests { + actual := validatingCreate(test.gss, test.cpm) + if actual.Allowed != test.allowed { + t.Errorf("%d: expect %v, got %v", i, test.allowed, actual.Allowed) + } + } +} diff --git a/pkg/webhook/webhook.go b/pkg/webhook/webhook.go index eeaf86d4..a29c2755 100644 --- a/pkg/webhook/webhook.go +++ b/pkg/webhook/webhook.go @@ -104,7 +104,7 @@ func (ws *Webhook) SetupWithManager(mgr manager.Manager) *Webhook { } recorder := mgr.GetEventRecorderFor("kruise-game-webhook") server.Register(mutatePodPath, &webhook.Admission{Handler: NewPodMutatingHandler(mgr.GetClient(), decoder, ws.cpm, recorder)}) - server.Register(validateGssPath, &webhook.Admission{Handler: &GssValidaatingHandler{Client: mgr.GetClient(), decoder: decoder}}) + server.Register(validateGssPath, &webhook.Admission{Handler: &GssValidaatingHandler{Client: mgr.GetClient(), decoder: decoder, CloudProviderManager: ws.cpm}}) return ws }