add ns networkpolicy
This commit is contained in:
144
pkg/controller/network/provider/ns_calico.go
Normal file
144
pkg/controller/network/provider/ns_calico.go
Normal file
@@ -0,0 +1,144 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
v3 "github.com/projectcalico/libcalico-go/lib/apis/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/clientv3"
|
||||
"github.com/projectcalico/libcalico-go/lib/errors"
|
||||
"github.com/projectcalico/libcalico-go/lib/options"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/klog/klogr"
|
||||
api "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1"
|
||||
)
|
||||
|
||||
var log = klogr.New().WithName("calico-client")
|
||||
var defaultBackoff = wait.Backoff{
|
||||
Steps: 4,
|
||||
Duration: 10 * time.Millisecond,
|
||||
Factor: 5.0,
|
||||
Jitter: 0.1,
|
||||
}
|
||||
|
||||
type calicoNetworkProvider struct {
|
||||
np clientv3.NetworkPolicyInterface
|
||||
}
|
||||
|
||||
func NewCalicoNetworkProvider(np clientv3.NetworkPolicyInterface) NsNetworkPolicyProvider {
|
||||
return &calicoNetworkProvider{
|
||||
np: np,
|
||||
}
|
||||
}
|
||||
func convertSpec(n *api.NamespaceNetworkPolicySpec) *v3.NetworkPolicySpec {
|
||||
bytes, err := json.Marshal(&n)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
m := new(v3.NetworkPolicySpec)
|
||||
err = json.Unmarshal(bytes, m)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// ConvertAPIToCalico convert our api to calico api
|
||||
func ConvertAPIToCalico(n *api.NamespaceNetworkPolicy) *v3.NetworkPolicy {
|
||||
output := v3.NewNetworkPolicy()
|
||||
//Object Metadata
|
||||
output.ObjectMeta.Name = n.Name
|
||||
output.Namespace = n.Namespace
|
||||
output.Annotations = n.Annotations
|
||||
output.Labels = n.Labels
|
||||
//spec
|
||||
output.Spec = *(convertSpec(&n.Spec))
|
||||
return output
|
||||
}
|
||||
|
||||
func (k *calicoNetworkProvider) Get(o *api.NamespaceNetworkPolicy) (interface{}, error) {
|
||||
return k.np.Get(context.TODO(), o.Namespace, o.Name, options.GetOptions{})
|
||||
}
|
||||
|
||||
func (k *calicoNetworkProvider) Add(o *api.NamespaceNetworkPolicy) error {
|
||||
log.V(3).Info("Creating network policy", "name", o.Name, "namespace", o.Namespace)
|
||||
obj := ConvertAPIToCalico(o)
|
||||
log.V(4).Info("Show object spe detail", "name", o.Name, "namespace", o.Namespace, "Spec", obj.Spec)
|
||||
_, err := k.np.Create(context.TODO(), obj, options.SetOptions{})
|
||||
return err
|
||||
}
|
||||
|
||||
func (k *calicoNetworkProvider) CheckExist(o *api.NamespaceNetworkPolicy) (bool, error) {
|
||||
log.V(3).Info("Checking network policy whether exsits or not", "name", o.Name, "namespace", o.Namespace)
|
||||
out, err := k.np.Get(context.Background(), o.Namespace, o.Name, options.GetOptions{})
|
||||
if err != nil {
|
||||
if _, ok := err.(errors.ErrorResourceDoesNotExist); ok {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
if out != nil {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (k *calicoNetworkProvider) Delete(o *api.NamespaceNetworkPolicy) error {
|
||||
log.V(3).Info("Deleting network policy", "name", o.Name, "namespace", o.Namespace)
|
||||
_, err := k.np.Delete(context.Background(), o.Namespace, o.Name, options.DeleteOptions{})
|
||||
return err
|
||||
}
|
||||
|
||||
func (k *calicoNetworkProvider) NeedUpdate(o *api.NamespaceNetworkPolicy) (bool, error) {
|
||||
store, err := k.np.Get(context.Background(), o.Namespace, o.Name, options.GetOptions{})
|
||||
if err != nil {
|
||||
log.Error(err, "Failed to get resource", "name", o.Name, "namespace", o.Namespace)
|
||||
}
|
||||
expected := ConvertAPIToCalico(o)
|
||||
log.V(4).Info("Comparing Spec", "store", store.Spec, "current", expected.Spec)
|
||||
if !reflect.DeepEqual(store.Spec, expected.Spec) {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (k *calicoNetworkProvider) Update(o *api.NamespaceNetworkPolicy) error {
|
||||
log.V(3).Info("Updating network policy", "name", o.Name, "namespace", o.Namespace)
|
||||
updateObject, err := k.Get(o)
|
||||
if err != nil {
|
||||
log.Error(err, "Failed to get resource in store")
|
||||
return err
|
||||
}
|
||||
up := updateObject.(*v3.NetworkPolicy)
|
||||
up.Spec = *convertSpec(&o.Spec)
|
||||
err = RetryOnConflict(defaultBackoff, func() error {
|
||||
_, err := k.np.Update(context.Background(), up, options.SetOptions{})
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
log.Error(err, "Failed to update resource", "name", o.Name, "namespace", o.Namespace)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// RetryOnConflict is same as the function in k8s, but replaced with error in calico
|
||||
func RetryOnConflict(backoff wait.Backoff, fn func() error) error {
|
||||
var lastConflictErr error
|
||||
err := wait.ExponentialBackoff(backoff, func() (bool, error) {
|
||||
err := fn()
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
if _, ok := err.(errors.ErrorResourceUpdateConflict); ok {
|
||||
lastConflictErr = err
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
})
|
||||
if err == wait.ErrWaitTimeout {
|
||||
err = lastConflictErr
|
||||
}
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user