add ns networkpolicy

This commit is contained in:
magicsong
2019-08-05 18:48:32 +08:00
parent cc15fbe983
commit 90fa38851f
101 changed files with 3737 additions and 120 deletions

View File

@@ -0,0 +1,66 @@
package provider
import (
"reflect"
"github.com/projectcalico/libcalico-go/lib/errors"
"k8s.io/client-go/tools/cache"
api "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1"
)
func NewFakeCalicoNetworkProvider() *FakeCalicoNetworkProvider {
f := new(FakeCalicoNetworkProvider)
f.NSNPData = make(map[string]*api.NamespaceNetworkPolicy)
return f
}
type FakeCalicoNetworkProvider struct {
NSNPData map[string]*api.NamespaceNetworkPolicy
}
func (f *FakeCalicoNetworkProvider) Get(o *api.NamespaceNetworkPolicy) (interface{}, error) {
namespacename, _ := cache.MetaNamespaceKeyFunc(o)
obj, ok := f.NSNPData[namespacename]
if !ok {
return nil, errors.ErrorResourceDoesNotExist{}
}
return obj, nil
}
func (f *FakeCalicoNetworkProvider) Add(o *api.NamespaceNetworkPolicy) error {
namespacename, _ := cache.MetaNamespaceKeyFunc(o)
if _, ok := f.NSNPData[namespacename]; ok {
return errors.ErrorResourceAlreadyExists{}
}
f.NSNPData[namespacename] = o
return nil
}
func (f *FakeCalicoNetworkProvider) CheckExist(o *api.NamespaceNetworkPolicy) (bool, error) {
namespacename, _ := cache.MetaNamespaceKeyFunc(o)
if _, ok := f.NSNPData[namespacename]; ok {
return true, nil
}
return false, nil
}
func (f *FakeCalicoNetworkProvider) NeedUpdate(o *api.NamespaceNetworkPolicy) (bool, error) {
namespacename, _ := cache.MetaNamespaceKeyFunc(o)
store := f.NSNPData[namespacename]
if !reflect.DeepEqual(store, o) {
return true, nil
}
return false, nil
}
func (f *FakeCalicoNetworkProvider) Update(o *api.NamespaceNetworkPolicy) error {
namespacename, _ := cache.MetaNamespaceKeyFunc(o)
f.NSNPData[namespacename] = o
return nil
}
func (f *FakeCalicoNetworkProvider) Delete(o *api.NamespaceNetworkPolicy) error {
namespacename, _ := cache.MetaNamespaceKeyFunc(o)
delete(f.NSNPData, namespacename)
return nil
}

View File

@@ -0,0 +1 @@
package provider

View File

@@ -0,0 +1,35 @@
package provider
import (
k8snetworkinformer "k8s.io/client-go/informers/networking/v1"
k8snetworklister "k8s.io/client-go/listers/networking/v1"
api "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1"
)
// NsNetworkPolicyProvider is a interface to let different cnis to implement our api
type NsNetworkPolicyProvider interface {
Add(*api.NamespaceNetworkPolicy) error
CheckExist(*api.NamespaceNetworkPolicy) (bool, error)
NeedUpdate(*api.NamespaceNetworkPolicy) (bool, error)
Update(*api.NamespaceNetworkPolicy) error
Delete(*api.NamespaceNetworkPolicy) error
Get(*api.NamespaceNetworkPolicy) (interface{}, error)
}
// TODO: support no-calico CNI
type k8sNetworkProvider struct {
networkPolicyInformer k8snetworkinformer.NetworkPolicyInformer
networkPolicyLister k8snetworklister.NetworkPolicyLister
}
func (k *k8sNetworkProvider) Add(o *api.NamespaceNetworkPolicy) error {
return nil
}
func (k *k8sNetworkProvider) CheckExist(o *api.NamespaceNetworkPolicy) (bool, error) {
return false, nil
}
func (k *k8sNetworkProvider) Delete(o *api.NamespaceNetworkPolicy) error {
return nil
}

View 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
}