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

added namespace validation for custom resources #1523

Merged
merged 4 commits into from Aug 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions api/v1beta1/addresspool_webhook.go
Expand Up @@ -18,6 +18,7 @@ package v1beta1

import (
"context"
"fmt"

"github.com/go-kit/log/level"
"github.com/pkg/errors"
Expand All @@ -41,6 +42,10 @@ var _ webhook.Validator = &AddressPool{}
func (addressPool *AddressPool) ValidateCreate() error {
level.Debug(Logger).Log("webhook", "addressPool", "action", "create", "name", addressPool.Name, "namespace", addressPool.Namespace)

if addressPool.Namespace != MetalLBNamespace {
return fmt.Errorf("resource must be created in %s namespace", MetalLBNamespace)
}

existingAddressPoolList, err := getExistingAddressPools()
if err != nil {
return err
Expand Down
13 changes: 13 additions & 0 deletions api/v1beta1/addresspool_webhook_test.go
Expand Up @@ -15,6 +15,7 @@ const (
)

func TestValidateAddressPool(t *testing.T) {
MetalLBNamespace = MetalLBTestNameSpace
addressPool := AddressPool{
ObjectMeta: metav1.ObjectMeta{
Name: "test-addresspool",
Expand Down Expand Up @@ -115,6 +116,18 @@ func TestValidateAddressPool(t *testing.T) {
},
failValidate: true,
},
{
desc: "Validation must fail if created in different namespace",
addressPool: &AddressPool{
ObjectMeta: metav1.ObjectMeta{
Name: "test-addresspool2",
Namespace: "default",
},
},
isNewAddressPool: true,
expected: nil,
failValidate: true,
},
}

for _, test := range tests {
Expand Down
8 changes: 7 additions & 1 deletion api/v1beta1/bfdprofile_webhook.go
Expand Up @@ -32,12 +32,18 @@ func (bfdProfile *BFDProfile) SetupWebhookWithManager(mgr ctrl.Manager) error {
Complete()
}

//+kubebuilder:webhook:verbs=delete,path=/validate-metallb-io-v1beta1-bfdprofile,mutating=false,failurePolicy=fail,groups=metallb.io,resources=bfdprofiles,versions=v1beta1,name=bfdprofilevalidationwebhook.metallb.io,sideEffects=None,admissionReviewVersions=v1
//+kubebuilder:webhook:verbs=create;delete,path=/validate-metallb-io-v1beta1-bfdprofile,mutating=false,failurePolicy=fail,groups=metallb.io,resources=bfdprofiles,versions=v1beta1,name=bfdprofilevalidationwebhook.metallb.io,sideEffects=None,admissionReviewVersions=v1

var _ webhook.Validator = &BFDProfile{}

// ValidateCreate implements webhook.Validator so a webhook will be registered for BFDProfile.
func (bfdProfile *BFDProfile) ValidateCreate() error {
level.Debug(Logger).Log("webhook", "bfdProfile", "action", "create", "name", bfdProfile.Name, "namespace", bfdProfile.Namespace)

if bfdProfile.Namespace != MetalLBNamespace {
return fmt.Errorf("resource must be created in %s namespace", MetalLBNamespace)
}

return nil
}

Expand Down
53 changes: 45 additions & 8 deletions api/v1beta1/bfdprofile_webhook_test.go
Expand Up @@ -5,12 +5,15 @@ package v1beta1
import (
"testing"

"github.com/go-kit/log"
"go.universe.tf/metallb/api/v1beta2"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestValidateBFDProfile(t *testing.T) {
MetalLBNamespace = MetalLBTestNameSpace
Logger = log.NewNopLogger()
toRestoreBGPPeers := v1beta2.GetExistingBGPPeers
v1beta2.GetExistingBGPPeers = func() (*v1beta2.BGPPeerList, error) {
return &v1beta2.BGPPeerList{
Expand All @@ -31,17 +34,51 @@ func TestValidateBFDProfile(t *testing.T) {
v1beta2.GetExistingBGPPeers = toRestoreBGPPeers
}()

desc := "Delete bfdprofile used by bgppeer"
bfdProfile := &BFDProfile{
ObjectMeta: metav1.ObjectMeta{
Name: "bfdprofile",
Namespace: MetalLBTestNameSpace,
const (
isNew int = iota
isDel
)
tests := []struct {
desc string
bfdProfile *BFDProfile
validateType int
failValidate bool
}{
{
desc: "Delete bfdprofile used by bgppeer",
validateType: isDel,
bfdProfile: &BFDProfile{
ObjectMeta: metav1.ObjectMeta{
Name: "bfdprofile",
Namespace: MetalLBTestNameSpace,
},
},
failValidate: true,
},
{
desc: "Validation must fail if created in different namespace",
validateType: isNew,
bfdProfile: &BFDProfile{
ObjectMeta: metav1.ObjectMeta{
Name: "bfdprofile1",
Namespace: "default",
},
},
failValidate: true,
},
}

err := bfdProfile.ValidateDelete()
for _, test := range tests {
var err error
switch test.validateType {
case isNew:
err = test.bfdProfile.ValidateCreate()
case isDel:
err = test.bfdProfile.ValidateDelete()
}

if err == nil {
t.Fatalf("test %s failed, expecting error", desc)
if test.failValidate && err == nil {
t.Fatalf("test %s failed, expecting error", test.desc)
}
}
}
5 changes: 5 additions & 0 deletions api/v1beta1/bgpadvertisement_webhook.go
Expand Up @@ -18,6 +18,7 @@ package v1beta1

import (
"context"
"fmt"

"github.com/go-kit/log/level"
"github.com/pkg/errors"
Expand All @@ -41,6 +42,10 @@ var _ webhook.Validator = &BGPAdvertisement{}
func (bgpAdv *BGPAdvertisement) ValidateCreate() error {
level.Debug(Logger).Log("webhook", "bgpadvertisement", "action", "create", "name", bgpAdv.Name, "namespace", bgpAdv.Namespace)

if bgpAdv.Namespace != MetalLBNamespace {
return fmt.Errorf("resource must be created in %s namespace", MetalLBNamespace)
}

existingBGPAdvList, err := getExistingBGPAdvs()
if err != nil {
return err
Expand Down
13 changes: 13 additions & 0 deletions api/v1beta1/bgpadvertisement_webhook_test.go
Expand Up @@ -11,6 +11,7 @@ import (
)

func TestValidateBGPAdvertisement(t *testing.T) {
MetalLBNamespace = MetalLBTestNameSpace
bgpAdv := BGPAdvertisement{
ObjectMeta: metav1.ObjectMeta{
Name: "test-bgpadv",
Expand Down Expand Up @@ -117,6 +118,18 @@ func TestValidateBGPAdvertisement(t *testing.T) {
},
failValidate: true,
},
{
desc: "Validation must fail if created in different namespace",
bgpAdv: &BGPAdvertisement{
ObjectMeta: metav1.ObjectMeta{
Name: "test-bgpadv1",
Namespace: "default",
},
},
isNew: true,
expected: nil,
failValidate: true,
},
}
for _, test := range tests {
var err error
Expand Down
5 changes: 5 additions & 0 deletions api/v1beta1/community_webhook.go
Expand Up @@ -18,6 +18,7 @@ package v1beta1

import (
"context"
"fmt"

"github.com/go-kit/log/level"
"github.com/pkg/errors"
Expand All @@ -41,6 +42,10 @@ var _ webhook.Validator = &Community{}
func (community *Community) ValidateCreate() error {
level.Debug(Logger).Log("webhook", "community", "action", "create", "name", community.Name, "namespace", community.Namespace)

if community.Namespace != MetalLBNamespace {
return fmt.Errorf("resource must be created in %s namespace", MetalLBNamespace)
}

existingCommunityList, err := getExistingCommunities()
if err != nil {
return err
Expand Down
13 changes: 13 additions & 0 deletions api/v1beta1/community_webhook_test.go
Expand Up @@ -11,6 +11,7 @@ import (
)

func TestValidateCommunity(t *testing.T) {
MetalLBNamespace = MetalLBTestNameSpace
Logger = log.NewNopLogger()

toRestoreCommunities := getExistingCommunities
Expand Down Expand Up @@ -104,6 +105,18 @@ func TestValidateCommunity(t *testing.T) {
},
failValidate: true,
},
{
desc: "Validation must fail if created in different namespace",
commuinty: &Community{
ObjectMeta: metav1.ObjectMeta{
Name: "test-commuinty2",
Namespace: "default",
},
},
isNewCommunity: true,
expected: nil,
failValidate: true,
},
}
for _, test := range tests {
var err error
Expand Down
4 changes: 4 additions & 0 deletions api/v1beta1/ipaddresspool_webhook.go
Expand Up @@ -18,6 +18,7 @@ package v1beta1

import (
"context"
"fmt"

"github.com/go-kit/log/level"
"github.com/pkg/errors"
Expand All @@ -41,6 +42,9 @@ var _ webhook.Validator = &IPAddressPool{}
func (ipAddress *IPAddressPool) ValidateCreate() error {
level.Debug(Logger).Log("webhook", "ipaddresspool", "action", "create", "name", ipAddress.Name, "namespace", ipAddress.Namespace)

if ipAddress.Namespace != MetalLBNamespace {
return fmt.Errorf("resource must be created in %s namespace", MetalLBNamespace)
}
existingIPAddressPoolList, err := getExistingIPAddressPools()
if err != nil {
return err
Expand Down
13 changes: 13 additions & 0 deletions api/v1beta1/ipaddresspool_webhook_test.go
Expand Up @@ -11,6 +11,7 @@ import (
)

func TestValidateIPAddressPool(t *testing.T) {
MetalLBNamespace = MetalLBTestNameSpace
ipAddressPool := IPAddressPool{
ObjectMeta: metav1.ObjectMeta{
Name: "test-ippool",
Expand Down Expand Up @@ -111,6 +112,18 @@ func TestValidateIPAddressPool(t *testing.T) {
},
failValidate: true,
},
{
desc: "Validation must fail if created in different namespace",
ipAddressPool: &IPAddressPool{
ObjectMeta: metav1.ObjectMeta{
Name: "test-ippool2",
Namespace: "default",
},
},
isNew: true,
expected: nil,
failValidate: true,
},
}

for _, test := range tests {
Expand Down
5 changes: 5 additions & 0 deletions api/v1beta1/l2advertisement_webhook.go
Expand Up @@ -18,6 +18,7 @@ package v1beta1

import (
"context"
"fmt"

"github.com/go-kit/log/level"
"github.com/pkg/errors"
Expand All @@ -41,6 +42,10 @@ var _ webhook.Validator = &L2Advertisement{}
func (l2Adv *L2Advertisement) ValidateCreate() error {
level.Debug(Logger).Log("webhook", "l2advertisement", "action", "create", "name", l2Adv.Name, "namespace", l2Adv.Namespace)

if l2Adv.Namespace != MetalLBNamespace {
return fmt.Errorf("resource must be created in %s namespace", MetalLBNamespace)
}

existingL2AdvList, err := getExistingL2Advs()
if err != nil {
return err
Expand Down
13 changes: 13 additions & 0 deletions api/v1beta1/l2advertisement_webhook_test.go
Expand Up @@ -11,6 +11,7 @@ import (
)

func TestValidateL2Advertisement(t *testing.T) {
MetalLBNamespace = MetalLBTestNameSpace
l2Adv := L2Advertisement{
ObjectMeta: metav1.ObjectMeta{
Name: "test-l2adv",
Expand Down Expand Up @@ -117,6 +118,18 @@ func TestValidateL2Advertisement(t *testing.T) {
},
failValidate: true,
},
{
desc: "Validation must fail if created in different namespace",
l2Adv: &L2Advertisement{
ObjectMeta: metav1.ObjectMeta{
Name: "test-l2adv1",
Namespace: "default",
},
},
isNew: true,
expected: nil,
failValidate: true,
},
}
for _, test := range tests {
var err error
Expand Down
4 changes: 4 additions & 0 deletions api/v1beta2/bgppeer_webhook.go
Expand Up @@ -18,6 +18,7 @@ package v1beta2

import (
"context"
"fmt"

"github.com/go-kit/log/level"
"github.com/pkg/errors"
Expand All @@ -41,6 +42,9 @@ var _ webhook.Validator = &BGPPeer{}
func (bgpPeer *BGPPeer) ValidateCreate() error {
level.Debug(Logger).Log("webhook", "bgppeer", "action", "create", "name", bgpPeer.Name, "namespace", bgpPeer.Namespace)

if bgpPeer.Namespace != MetalLBNamespace {
return fmt.Errorf("resource must be created in %s namespace", MetalLBNamespace)
}
existingBGPPeers, err := GetExistingBGPPeers()
if err != nil {
return err
Expand Down
13 changes: 13 additions & 0 deletions api/v1beta2/bgppeer_webhook_test.go
Expand Up @@ -13,6 +13,7 @@ import (
const testNamespace = "namespace"

func TestValidateBGPPeer(t *testing.T) {
MetalLBNamespace = testNamespace
bgpPeer := BGPPeer{
ObjectMeta: metav1.ObjectMeta{
Name: "test-peer",
Expand Down Expand Up @@ -109,6 +110,18 @@ func TestValidateBGPPeer(t *testing.T) {
},
failValidate: true,
},
{
desc: "Validation must fail if created in different namespace",
bgpPeer: &BGPPeer{
ObjectMeta: metav1.ObjectMeta{
Name: "test-peer1",
Namespace: "default",
},
},
isNew: true,
expected: nil,
failValidate: true,
},
}
for _, test := range tests {
var err error
Expand Down
3 changes: 2 additions & 1 deletion charts/metallb/templates/webhooks.yaml
Expand Up @@ -113,13 +113,14 @@ webhooks:
namespace: {{ .Release.Namespace }}
path: /validate-metallb-io-v1beta1-bfdprofile
failurePolicy: Fail
name: bfdprofileyvalidationwebhook.metallb.io
name: bfdprofilevalidationwebhook.metallb.io
rules:
- apiGroups:
- metallb.io
apiVersions:
- v1beta1
operations:
- CREATE
- DELETE
resources:
- bfdprofiles
Expand Down
1 change: 1 addition & 0 deletions config/manifests/metallb-frr.yaml
Expand Up @@ -1999,6 +1999,7 @@ webhooks:
apiVersions:
- v1beta1
operations:
- CREATE
- DELETE
resources:
- bfdprofiles
Expand Down