Skip to content

Commit

Permalink
add webhook validation for pool
Browse files Browse the repository at this point in the history
Signed-off-by: Sebastian Sch <[email protected]>
  • Loading branch information
SchSeba committed Dec 8, 2023
1 parent 386b64e commit 8788997
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 3 deletions.
4 changes: 4 additions & 0 deletions bindata/manifests/operator-webhook/003-webhook.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,7 @@ webhooks:
apiGroups: [ "sriovnetwork.openshift.io" ]
apiVersions: [ "v1" ]
resources: [ "sriovoperatorconfigs" ]
- operations: [ "CREATE", "UPDATE", "DELETE" ]
apiGroups: [ "sriovnetwork.openshift.io" ]
apiVersions: [ "v1" ]
resources: [ "sriovnetworkpoolconfigs" ]
29 changes: 26 additions & 3 deletions pkg/webhook/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,34 @@ func validateSriovOperatorConfigDisableDrain(cr *sriovnetworkv1.SriovOperatorCon
return nil
}

// validateSriovNetworkPoolConfig checks if the use tries to remove the default pool config and block it
func validateSriovNetworkPoolConfig(cr *sriovnetworkv1.SriovNetworkPoolConfig, operation v1.Operation) (bool, []string, error) {
log.Log.V(2).Info("validateSriovNetworkPoolConfig", "object", cr)
var warnings []string

if cr.GetName() == consts.DefaultConfigName && operation == v1.Delete {
return false, warnings, fmt.Errorf("default SriovOperatorConfig shouldn't be deleted")
}

if cr.Spec.MaxUnavailable != nil && cr.Spec.OvsHardwareOffloadConfig.Name != "" {
return false, warnings, fmt.Errorf("SriovOperatorConfig can't have both parallel configuration and OvsHardwareOffloadConfig")
}

if cr.Spec.MaxUnavailable != nil {
_, err := cr.MaxUnavailable(1)
if err != nil {
return false, warnings, fmt.Errorf("SriovOperatorConfig invalid maxUnavailable: %v", err)
}
}

return true, warnings, nil
}

func validateSriovNetworkNodePolicy(cr *sriovnetworkv1.SriovNetworkNodePolicy, operation v1.Operation) (bool, []string, error) {
log.Log.V(2).Info("validateSriovNetworkNodePolicy", "object", cr)
var warnings []string

if cr.GetName() == consts.DefaultPolicyName && cr.GetNamespace() == os.Getenv("NAMESPACE") {
if cr.GetName() == consts.DefaultPolicyName && cr.GetNamespace() == vars.Namespace {
if operation == v1.Delete {
// reject deletion of default policy
return false, warnings, fmt.Errorf("default SriovNetworkNodePolicy shouldn't be deleted")
Expand All @@ -105,9 +128,9 @@ func validateSriovNetworkNodePolicy(cr *sriovnetworkv1.SriovNetworkNodePolicy, o
}
}

if cr.GetNamespace() != os.Getenv("NAMESPACE") {
if cr.GetNamespace() != vars.Namespace {
warnings = append(warnings, cr.GetName()+
fmt.Sprintf(" is created or updated but not used. Only policy in %s namespace is respected.", os.Getenv("NAMESPACE")))
fmt.Sprintf(" is created or updated but not used. Only policy in %s namespace is respected.", vars.Namespace))
}

// DELETE should always succeed unless it's for the default object
Expand Down
49 changes: 49 additions & 0 deletions pkg/webhook/validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

. "github.com/onsi/gomega"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/client-go/kubernetes"
"sigs.k8s.io/controller-runtime/pkg/envtest"

Expand Down Expand Up @@ -150,6 +151,19 @@ func newDefaultOperatorConfig() *SriovOperatorConfig {
}
}

func newDefaultNetworkPoolConfig() *SriovNetworkPoolConfig {
maxUn := intstr.FromInt32(1)
return &SriovNetworkPoolConfig{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
},
Spec: SriovNetworkPoolConfigSpec{
MaxUnavailable: &maxUn,
NodeSelector: &metav1.LabelSelector{MatchLabels: map[string]string{}},
},
}
}

func TestValidateSriovOperatorConfigWithDefaultOperatorConfig(t *testing.T) {
g := NewGomegaWithT(t)

Expand Down Expand Up @@ -207,6 +221,41 @@ func TestValidateSriovOperatorConfigDisableDrain(t *testing.T) {
g.Expect(ok).To(Equal(true))
}

func TestValidateSriovNetworkPoolConfigWithDefault(t *testing.T) {
g := NewGomegaWithT(t)

config := newDefaultNetworkPoolConfig()
snclient = fakesnclientset.NewSimpleClientset()

ok, _, err := validateSriovNetworkPoolConfig(config, "DELETE")
g.Expect(err).To(HaveOccurred())
g.Expect(ok).To(Equal(false))

ok, _, err = validateSriovNetworkPoolConfig(config, "UPDATE")
g.Expect(err).NotTo(HaveOccurred())
g.Expect(ok).To(Equal(true))

ok, _, err = validateSriovNetworkPoolConfig(config, "CREATE")
g.Expect(err).NotTo(HaveOccurred())
g.Expect(ok).To(Equal(true))
}

func TestValidateSriovNetworkPoolConfigWithParallelAndHWOffload(t *testing.T) {
g := NewGomegaWithT(t)

config := newDefaultNetworkPoolConfig()
config.Spec.OvsHardwareOffloadConfig.Name = "test"
snclient = fakesnclientset.NewSimpleClientset()

ok, _, err := validateSriovNetworkPoolConfig(config, "UPDATE")
g.Expect(err).To(HaveOccurred())
g.Expect(ok).To(BeFalse())

ok, _, err = validateSriovNetworkPoolConfig(config, "CREATE")
g.Expect(err).To(HaveOccurred())
g.Expect(ok).To(BeFalse())
}

func TestValidateSriovNetworkNodePolicyWithDefaultPolicy(t *testing.T) {
var err error
var ok bool
Expand Down
15 changes: 15 additions & 0 deletions pkg/webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,21 @@ func ValidateCustomResource(ar v1.AdmissionReview) *v1.AdmissionResponse {
Reason: metav1.StatusReason(err.Error()),
}
}

case "SriovNetworkPoolConfig":
config := sriovnetworkv1.SriovNetworkPoolConfig{}

err = json.Unmarshal(raw, &config)
if err != nil {
log.Log.Error(err, "failed to unmarshal object")
return toV1AdmissionResponse(err)
}

if reviewResponse.Allowed, reviewResponse.Warnings, err = validateSriovNetworkPoolConfig(&config, ar.Request.Operation); err != nil {
reviewResponse.Result = &metav1.Status{
Reason: metav1.StatusReason(err.Error()),
}
}
}

return &reviewResponse
Expand Down

0 comments on commit 8788997

Please sign in to comment.