From 75d787f15f015b81cf9f6be1567aa513737d64ab Mon Sep 17 00:00:00 2001 From: magicsong Date: Tue, 23 Jul 2019 11:26:41 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=9F=20add=20support=20of=20workspace?= =?UTF-8?q?=20networkpolicy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + .travis.yml | 3 + Makefile | 30 +- ...ubesphere.io_workspacenetworkpolicies.yaml | 519 ++++++++++++++++++ go.mod | 5 +- go.sum | 3 + hack/generate_client.sh | 9 + hack/generate_group.sh | 92 ++++ pkg/apis/addtoscheme_network_v1alpha1.go | 26 + pkg/apis/network/group.go | 18 + pkg/apis/network/v1alpha1/doc.go | 23 + pkg/apis/network/v1alpha1/register.go | 46 ++ .../network/v1alpha1/v1alpha1_suite_test.go | 55 ++ .../v1alpha1/workspacenetworkpolicy_types.go | 138 +++++ .../workspacenetworkpolicy_types_test.go | 56 ++ .../network/v1alpha1/zz_generated.deepcopy.go | 214 ++++++++ .../v1alpha2/zz_generated.deepcopy.go | 30 +- .../tenant/v1alpha1/zz_generated.deepcopy.go | 8 +- pkg/client/clientset/versioned/clientset.go | 22 + .../versioned/fake/clientset_generated.go | 12 + .../clientset/versioned/fake/register.go | 2 + .../clientset/versioned/scheme/register.go | 2 + .../versioned/typed/network/v1alpha1/doc.go | 20 + .../typed/network/v1alpha1/fake/doc.go | 20 + .../v1alpha1/fake/fake_network_client.go | 40 ++ .../fake/fake_workspacenetworkpolicy.go | 131 +++++ .../network/v1alpha1/generated_expansion.go | 21 + .../typed/network/v1alpha1/network_client.go | 90 +++ .../v1alpha1/workspacenetworkpolicy.go | 180 ++++++ .../informers/externalversions/factory.go | 6 + .../informers/externalversions/generic.go | 11 +- .../externalversions/network/interface.go | 46 ++ .../network/v1alpha1/interface.go | 45 ++ .../v1alpha1/workspacenetworkpolicy.go | 88 +++ .../network/v1alpha1/expansion_generated.go | 23 + .../v1alpha1/workspacenetworkpolicy.go | 65 +++ pkg/controller/network/testing/controller.go | 38 ++ pkg/controller/network/testing/util.go | 12 + .../network/wsnetworkpolicy/controller.go | 283 ++++++++++ .../network/wsnetworkpolicy/reconcile.go | 203 +++++++ .../wsnetworkpolicy_suite_test.go | 21 + .../wsnetworkpolicy/wsnetworkpolicy_test.go | 241 ++++++++ 42 files changed, 2867 insertions(+), 31 deletions(-) create mode 100644 config/crds/network.kubesphere.io_workspacenetworkpolicies.yaml create mode 100755 hack/generate_client.sh create mode 100755 hack/generate_group.sh create mode 100644 pkg/apis/addtoscheme_network_v1alpha1.go create mode 100644 pkg/apis/network/group.go create mode 100644 pkg/apis/network/v1alpha1/doc.go create mode 100644 pkg/apis/network/v1alpha1/register.go create mode 100644 pkg/apis/network/v1alpha1/v1alpha1_suite_test.go create mode 100644 pkg/apis/network/v1alpha1/workspacenetworkpolicy_types.go create mode 100644 pkg/apis/network/v1alpha1/workspacenetworkpolicy_types_test.go create mode 100644 pkg/apis/network/v1alpha1/zz_generated.deepcopy.go create mode 100644 pkg/client/clientset/versioned/typed/network/v1alpha1/doc.go create mode 100644 pkg/client/clientset/versioned/typed/network/v1alpha1/fake/doc.go create mode 100644 pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_network_client.go create mode 100644 pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_workspacenetworkpolicy.go create mode 100644 pkg/client/clientset/versioned/typed/network/v1alpha1/generated_expansion.go create mode 100644 pkg/client/clientset/versioned/typed/network/v1alpha1/network_client.go create mode 100644 pkg/client/clientset/versioned/typed/network/v1alpha1/workspacenetworkpolicy.go create mode 100644 pkg/client/informers/externalversions/network/interface.go create mode 100644 pkg/client/informers/externalversions/network/v1alpha1/interface.go create mode 100644 pkg/client/informers/externalversions/network/v1alpha1/workspacenetworkpolicy.go create mode 100644 pkg/client/listers/network/v1alpha1/expansion_generated.go create mode 100644 pkg/client/listers/network/v1alpha1/workspacenetworkpolicy.go create mode 100644 pkg/controller/network/testing/controller.go create mode 100644 pkg/controller/network/testing/util.go create mode 100644 pkg/controller/network/wsnetworkpolicy/controller.go create mode 100644 pkg/controller/network/wsnetworkpolicy/reconcile.go create mode 100644 pkg/controller/network/wsnetworkpolicy/wsnetworkpolicy_suite_test.go create mode 100644 pkg/controller/network/wsnetworkpolicy/wsnetworkpolicy_test.go diff --git a/.gitignore b/.gitignore index 192f2e5d0..14586e3dc 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,4 @@ tmp/ # OSX trash .DS_Store api.json +*.coverprofile diff --git a/.travis.yml b/.travis.yml index b6f82f94a..36f64754b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,9 @@ go: - "1.12.x" env: - GO111MODULE=on +cache: + directories: + - $HOME/gopath/pkg/mod before_script: - docker --version diff --git a/Makefile b/Makefile index 23cca5298..9a3edd0f2 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,17 @@ # The binary to build BIN ?= ks-apiserver +# Produce CRDs that work back to Kubernetes 1.11 (no version conversion) +CRD_OPTIONS ?= "crd:trivialVersions=true" + +# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) +ifeq (,$(shell go env GOBIN)) +GOBIN=$(shell go env GOPATH)/bin +else +GOBIN=$(shell go env GOBIN) +endif + + IMG ?= kubespheredev/ks-apiserver OUTPUT_DIR=bin @@ -58,6 +69,8 @@ vet: manifests: go run vendor/sigs.k8s.io/controller-tools/cmd/controller-gen/main.go all +crds: + $(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./pkg/apis/network/..." output:crd:artifacts:config=config/crd/bases deploy: manifests kubectl apply -f config/crds kustomize build config/default | kubectl apply -f - @@ -66,9 +79,11 @@ deploy: manifests deepcopy: ./vendor/k8s.io/code-generator/generate-groups.sh all kubesphere.io/kubesphere/pkg/client kubesphere.io/kubesphere/pkg/apis "servicemesh:v1alpha2 tenant:v1alpha1" -# Generate code generate: go generate ./pkg/... ./cmd/... +# Generate code +generate-apis: controller-gen + $(CONTROLLER_GEN) object:headerFile=./hack/boilerplate.go.txt paths=./pkg/apis/... # Build the docker image docker-build: all @@ -82,3 +97,16 @@ test: generate fmt vet clean: -make -C ./pkg/version clean @echo "ok" + +# find or download controller-gen +# download controller-gen if necessary +controller-gen: +ifeq (, $(shell which controller-gen)) + go get sigs.k8s.io/controller-tools/cmd/controller-gen@v0.2.0-beta.4 +CONTROLLER_GEN=$(GOBIN)/controller-gen +else +CONTROLLER_GEN=$(shell which controller-gen) +endif + +clientset: + ./hack/generate_client.sh diff --git a/config/crds/network.kubesphere.io_workspacenetworkpolicies.yaml b/config/crds/network.kubesphere.io_workspacenetworkpolicies.yaml new file mode 100644 index 000000000..584b56e83 --- /dev/null +++ b/config/crds/network.kubesphere.io_workspacenetworkpolicies.yaml @@ -0,0 +1,519 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + creationTimestamp: null + name: workspacenetworkpolicies.network.kubesphere.io +spec: + group: network.kubesphere.io + names: + kind: WorkspaceNetworkPolicy + plural: workspacenetworkpolicies + scope: "Cluster" + validation: + openAPIV3Schema: + description: WorkspaceNetworkPolicy is a set of network policies applied to + the scope to workspace + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: WorkspaceNetworkPolicySpec defines the desired state of WorkspaceNetworkPolicy + properties: + egress: + description: List of egress rules to be applied to the selected pods. + Outgoing traffic is allowed if there are no NetworkPolicies selecting + the pod (and cluster policy otherwise allows the traffic), OR if the + traffic matches at least one egress rule across all of the NetworkPolicy + objects whose podSelector matches the pod. If this field is empty + then this NetworkPolicy limits all outgoing traffic (and serves solely + to ensure that the pods it selects are isolated by default). This + field is beta-level in 1.8 + items: + description: WorkspaceNetworkPolicyEgressRule describes a particular + set of traffic that is allowed out of pods matched by a WorkspaceNetworkPolicySpec's + podSelector. The traffic must match both ports and to. + properties: + from: + description: List of sources which should be able to access the + pods selected for this rule. Items in this list are combined + using a logical OR operation. If this field is empty or missing, + this rule matches all sources (traffic not restricted by source). + If this field is present and contains at least on item, this + rule allows traffic only if the traffic matches at least one + item in the from list. + items: + description: WorkspaceNetworkPolicyPeer describes a peer to + allow traffic from. Only certain combinations of fields are + allowed. It is same as 'NetworkPolicyPeer' in k8s but with + an additional field 'WorkspaceSelector' + properties: + ipBlock: + description: IPBlock defines policy on a particular IPBlock. + If this field is set then neither of the other fields + can be. + properties: + cidr: + description: CIDR is a string representing the IP Block + Valid examples are "192.168.1.1/24" + type: string + except: + description: Except is a slice of CIDRs that should + not be included within an IP Block Valid examples + are "192.168.1.1/24" Except values will be rejected + if they are outside the CIDR range + items: + type: string + type: array + required: + - cidr + type: object + namespaceSelector: + description: "Selects Namespaces using cluster-scoped labels. + This field follows standard label selector semantics; + if present but empty, it selects all namespaces. \n If + PodSelector is also set, then the NetworkPolicyPeer as + a whole selects the Pods matching PodSelector in the Namespaces + selected by NamespaceSelector. Otherwise it selects all + Pods in the Namespaces selected by NamespaceSelector." + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists + or DoesNotExist, the values array must be empty. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + podSelector: + description: "This is a label selector which selects Pods. + This field follows standard label selector semantics; + if present but empty, it selects all pods. \n If NamespaceSelector + is also set, then the NetworkPolicyPeer as a whole selects + the Pods matching PodSelector in the Namespaces selected + by NamespaceSelector. Otherwise it selects the Pods matching + PodSelector in the policy's own Namespace." + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists + or DoesNotExist, the values array must be empty. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + workspaceSelector: + description: A label selector is a label query over a set + of resources. The result of matchLabels and matchExpressions + are ANDed. An empty label selector matches all objects. + A null label selector matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists + or DoesNotExist, the values array must be empty. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + type: object + type: array + ports: + description: List of ports which should be made accessible on + the pods selected for this rule. Each item in this list is combined + using a logical OR. If this field is empty or missing, this + rule matches all ports (traffic not restricted by port). If + this field is present and contains at least one item, then this + rule allows traffic only if the traffic matches at least one + port in the list. + items: + description: NetworkPolicyPort describes a port to allow traffic + on + properties: + port: + anyOf: + - type: string + - type: integer + description: The port on the given protocol. This can either + be a numerical or named port on a pod. If this field is + not provided, this matches all port names and numbers. + protocol: + description: The protocol (TCP, UDP, or SCTP) which traffic + must match. If not specified, this field defaults to TCP. + type: string + type: object + type: array + type: object + type: array + ingress: + description: List of ingress rules to be applied to the selected pods. + Traffic is allowed to a pod if there are no NetworkPolicies selecting + the pod (and cluster policy otherwise allows the traffic), OR if the + traffic source is the pod's local node, OR if the traffic matches + at least one ingress rule across all of the NetworkPolicy objects + whose podSelector matches the pod. If this field is empty then this + NetworkPolicy does not allow any traffic (and serves solely to ensure + that the pods it selects are isolated by default) + items: + description: WorkspaceNetworkPolicyIngressRule describes a particular + set of traffic that is allowed to the pods matched by a WorkspaceNetworkPolicySpec's + podSelector. The traffic must match both ports and from. + properties: + from: + description: List of sources which should be able to access the + pods selected for this rule. Items in this list are combined + using a logical OR operation. If this field is empty or missing, + this rule matches all sources (traffic not restricted by source). + If this field is present and contains at least on item, this + rule allows traffic only if the traffic matches at least one + item in the from list. + items: + description: WorkspaceNetworkPolicyPeer describes a peer to + allow traffic from. Only certain combinations of fields are + allowed. It is same as 'NetworkPolicyPeer' in k8s but with + an additional field 'WorkspaceSelector' + properties: + ipBlock: + description: IPBlock defines policy on a particular IPBlock. + If this field is set then neither of the other fields + can be. + properties: + cidr: + description: CIDR is a string representing the IP Block + Valid examples are "192.168.1.1/24" + type: string + except: + description: Except is a slice of CIDRs that should + not be included within an IP Block Valid examples + are "192.168.1.1/24" Except values will be rejected + if they are outside the CIDR range + items: + type: string + type: array + required: + - cidr + type: object + namespaceSelector: + description: "Selects Namespaces using cluster-scoped labels. + This field follows standard label selector semantics; + if present but empty, it selects all namespaces. \n If + PodSelector is also set, then the NetworkPolicyPeer as + a whole selects the Pods matching PodSelector in the Namespaces + selected by NamespaceSelector. Otherwise it selects all + Pods in the Namespaces selected by NamespaceSelector." + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists + or DoesNotExist, the values array must be empty. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + podSelector: + description: "This is a label selector which selects Pods. + This field follows standard label selector semantics; + if present but empty, it selects all pods. \n If NamespaceSelector + is also set, then the NetworkPolicyPeer as a whole selects + the Pods matching PodSelector in the Namespaces selected + by NamespaceSelector. Otherwise it selects the Pods matching + PodSelector in the policy's own Namespace." + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists + or DoesNotExist, the values array must be empty. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + workspaceSelector: + description: A label selector is a label query over a set + of resources. The result of matchLabels and matchExpressions + are ANDed. An empty label selector matches all objects. + A null label selector matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists + or DoesNotExist, the values array must be empty. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + type: object + type: array + ports: + description: List of ports which should be made accessible on + the pods selected for this rule. Each item in this list is combined + using a logical OR. If this field is empty or missing, this + rule matches all ports (traffic not restricted by port). If + this field is present and contains at least one item, then this + rule allows traffic only if the traffic matches at least one + port in the list. + items: + description: NetworkPolicyPort describes a port to allow traffic + on + properties: + port: + anyOf: + - type: string + - type: integer + description: The port on the given protocol. This can either + be a numerical or named port on a pod. If this field is + not provided, this matches all port names and numbers. + protocol: + description: The protocol (TCP, UDP, or SCTP) which traffic + must match. If not specified, this field defaults to TCP. + type: string + type: object + type: array + type: object + type: array + policyTypes: + description: List of rule types that the WorkspaceNetworkPolicy relates + to. Valid options are Ingress, Egress, or Ingress,Egress. If this + field is not specified, it will default based on the existence of + Ingress or Egress rules; policies that contain an Egress section are + assumed to affect Egress, and all policies (whether or not they contain + an Ingress section) are assumed to affect Ingress. If you want to + write an egress-only policy, you must explicitly specify policyTypes + [ "Egress" ]. Likewise, if you want to write a policy that specifies + that no egress is allowed, you must specify a policyTypes value that + include "Egress" (since such a policy would not include an Egress + section and would otherwise default to just [ "Ingress" ]). + items: + description: Policy Type string describes the NetworkPolicy type This + type is beta-level in 1.8 + type: string + type: array + workspace: + description: Workspace specify the name of ws to apply this workspace + network policy + type: string + type: object + status: + description: WorkspaceNetworkPolicyStatus defines the observed state of + WorkspaceNetworkPolicy + type: object + type: object + version: v1alpha1 +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/go.mod b/go.mod index b48acea1a..6933ae158 100644 --- a/go.mod +++ b/go.mod @@ -69,6 +69,7 @@ require ( github.com/miekg/dns v1.1.9 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect + github.com/onsi/ginkgo v1.8.0 github.com/onsi/gomega v1.5.0 github.com/opencontainers/go-digest v1.0.0-rc1 // indirect github.com/openshift/api v3.9.0+incompatible // indirect @@ -122,10 +123,10 @@ require ( sigs.k8s.io/controller-runtime v0.1.10 sigs.k8s.io/controller-tools v0.1.9 // indirect sigs.k8s.io/testing_frameworks v0.1.1 // indirect - sigs.k8s.io/yaml v1.1.0 // indirect + sigs.k8s.io/yaml v1.1.0 ) replace ( - github.com/kubernetes-sigs/application => github.com/kubesphere/application v0.0.0-20190518133311-b9d9eb0b5cf7 github.com/kiali/kiali => github.com/kubesphere/kiali v0.15.1-0.20190407071308-6b5b818211c3 + github.com/kubernetes-sigs/application => github.com/kubesphere/application v0.0.0-20190518133311-b9d9eb0b5cf7 ) diff --git a/go.sum b/go.sum index c32b81e9f..b1d5ff148 100644 --- a/go.sum +++ b/go.sum @@ -381,6 +381,7 @@ golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190511041617-99f201b6807e h1:wTxRxdzKt8fn3IQa3+kVlPJMxK2hJj2Orm+M2Mzw9eg= golang.org/x/tools v0.0.0-20190511041617-99f201b6807e/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -435,8 +436,10 @@ k8s.io/apiserver v0.0.0-20181213151703-3ccfe8365421 h1:NyOpnIh+7SLvC05NGCIXF9c4K k8s.io/apiserver v0.0.0-20181213151703-3ccfe8365421/go.mod h1:6bqaTSOSJavUIXUtfaR9Os9JtTCm8ZqH2SUl2S60C4w= k8s.io/client-go v0.0.0-20181213151034-8d9ed539ba31 h1:OH3z6khCtxnJBAc0C5CMYWLl1CoK5R5fngX7wrwdN5c= k8s.io/client-go v0.0.0-20181213151034-8d9ed539ba31/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +k8s.io/code-generator v0.0.0-20181117043124-c2090bec4d9b h1:KH0fUlgdFZH8UMxJ/FDCYHpczfSQKefetq5NjL6BVF0= k8s.io/code-generator v0.0.0-20181117043124-c2090bec4d9b/go.mod h1:MYiN+ZJZ9HkETbgVZdWw2AsuAi9PZ4V80cwfuf2axe8= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a h1:QoHVuRquf80YZ+/bovwxoMO3Q/A3nt3yTgS0/0nejuk= k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0 h1:0VPpR+sizsiivjIfIAQH/rl8tan6jvWkS7lU+0di3lE= diff --git a/hack/generate_client.sh b/hack/generate_client.sh new file mode 100755 index 000000000..bdc575905 --- /dev/null +++ b/hack/generate_client.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e + +GV="network:v1alpha1 servicemesh:v1alpha2 tenant:v1alpha1" + +rm -rf ./pkg/client +./hack/generate_group.sh "client,lister,informer" kubesphere.io/kubesphere/pkg/client kubesphere.io/kubesphere/pkg/apis "$GV" --output-base=./ +mv kubesphere.io/kubesphere/pkg/client ./pkg/ +rm -rf ./kubesphere.io \ No newline at end of file diff --git a/hack/generate_group.sh b/hack/generate_group.sh new file mode 100755 index 000000000..29eb647bb --- /dev/null +++ b/hack/generate_group.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash + +# Copyright 2017 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +# generate-groups generates everything for a project with external types only, e.g. a project based +# on CustomResourceDefinitions. + +if [ "$#" -lt 4 ] || [ "${1}" == "--help" ]; then + cat < ... + + the generators comma separated to run (deepcopy,defaulter,client,lister,informer) or "all". + the output package name (e.g. github.com/example/project/pkg/generated). + the external types dir (e.g. github.com/example/api or github.com/example/project/pkg/apis). + the groups and their versions in the format "groupA:v1,v2 groupB:v1 groupC:v2", relative + to . + ... arbitrary flags passed to all generator binaries. + + +Examples: + $(basename "$0") all github.com/example/project/pkg/client github.com/example/project/pkg/apis "foo:v1 bar:v1alpha1,v1beta1" + $(basename "$0") deepcopy,client github.com/example/project/pkg/client github.com/example/project/pkg/apis "foo:v1 bar:v1alpha1,v1beta1" +EOF + exit 0 +fi + +GENS="$1" +OUTPUT_PKG="$2" +APIS_PKG="$3" +GROUPS_WITH_VERSIONS="$4" +shift 4 + +# ( +# # To support running this script from anywhere, we have to first cd into this directory +# # so we can install the tools. +# cd "$(dirname "${0}")" +# go install ./cmd/{defaulter-gen,client-gen,lister-gen,informer-gen,deepcopy-gen} +# ) + +function codegen::join() { local IFS="$1"; shift; echo "$*"; } + +# enumerate group versions +FQ_APIS=() # e.g. k8s.io/api/apps/v1 +for GVs in ${GROUPS_WITH_VERSIONS}; do + IFS=: read -r G Vs <<<"${GVs}" + + # enumerate versions + for V in ${Vs//,/ }; do + FQ_APIS+=("${APIS_PKG}/${G}/${V}") + done +done + +if [ "${GENS}" = "all" ] || grep -qw "deepcopy" <<<"${GENS}"; then + echo "Generating deepcopy funcs" + "${GOPATH}/bin/deepcopy-gen" --input-dirs "$(codegen::join , "${FQ_APIS[@]}")" -O zz_generated.deepcopy --bounding-dirs "${APIS_PKG}" "$@" +fi + +if [ "${GENS}" = "all" ] || grep -qw "client" <<<"${GENS}"; then + echo "Generating clientset for ${GROUPS_WITH_VERSIONS} at ${OUTPUT_PKG}/${CLIENTSET_PKG_NAME:-clientset}" + "${GOPATH}/bin/client-gen" --clientset-name "${CLIENTSET_NAME_VERSIONED:-versioned}" --input-base "" --input "$(codegen::join , "${FQ_APIS[@]}")" --output-package "${OUTPUT_PKG}/${CLIENTSET_PKG_NAME:-clientset}" "$@" +fi + +if [ "${GENS}" = "all" ] || grep -qw "lister" <<<"${GENS}"; then + echo "Generating listers for ${GROUPS_WITH_VERSIONS} at ${OUTPUT_PKG}/listers" + "${GOPATH}/bin/lister-gen" --input-dirs "$(codegen::join , "${FQ_APIS[@]}")" --output-package "${OUTPUT_PKG}/listers" "$@" +fi + +if [ "${GENS}" = "all" ] || grep -qw "informer" <<<"${GENS}"; then + echo "Generating informers for ${GROUPS_WITH_VERSIONS} at ${OUTPUT_PKG}/informers" + "${GOPATH}/bin/informer-gen" \ + --input-dirs "$(codegen::join , "${FQ_APIS[@]}")" \ + --versioned-clientset-package "${OUTPUT_PKG}/${CLIENTSET_PKG_NAME:-clientset}/${CLIENTSET_NAME_VERSIONED:-versioned}" \ + --listers-package "${OUTPUT_PKG}/listers" \ + --output-package "${OUTPUT_PKG}/informers" \ + "$@" +fi \ No newline at end of file diff --git a/pkg/apis/addtoscheme_network_v1alpha1.go b/pkg/apis/addtoscheme_network_v1alpha1.go new file mode 100644 index 000000000..76ae9985a --- /dev/null +++ b/pkg/apis/addtoscheme_network_v1alpha1.go @@ -0,0 +1,26 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package apis + +import ( + api "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" +) + +func init() { + // Register the types with the Scheme so the components can map objects to GroupVersionKinds and back + AddToSchemes = append(AddToSchemes, api.SchemeBuilder.AddToScheme) +} diff --git a/pkg/apis/network/group.go b/pkg/apis/network/group.go new file mode 100644 index 000000000..3010be553 --- /dev/null +++ b/pkg/apis/network/group.go @@ -0,0 +1,18 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package network contains network API versions +package network diff --git a/pkg/apis/network/v1alpha1/doc.go b/pkg/apis/network/v1alpha1/doc.go new file mode 100644 index 000000000..aaf886e4c --- /dev/null +++ b/pkg/apis/network/v1alpha1/doc.go @@ -0,0 +1,23 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1alpha1 contains API Schema definitions for the network v1alpha1 API group +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register +// +k8s:conversion-gen=kubesphere.io/kubesphere/pkg/apis/network +// +k8s:defaulter-gen=TypeMeta +// +groupName=network.kubesphere.io +package v1alpha1 diff --git a/pkg/apis/network/v1alpha1/register.go b/pkg/apis/network/v1alpha1/register.go new file mode 100644 index 000000000..8d0e7a9d0 --- /dev/null +++ b/pkg/apis/network/v1alpha1/register.go @@ -0,0 +1,46 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// NOTE: Boilerplate only. Ignore this file. + +// Package v1alpha1 contains API Schema definitions for the network v1alpha1 API group +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register +// +k8s:conversion-gen=kubesphere.io/kubesphere/pkg/apis/network +// +k8s:defaulter-gen=TypeMeta +// +groupName=network.kubesphere.io +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/runtime/scheme" +) + +var ( + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: "network.kubesphere.io", Version: "v1alpha1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} + + // AddToScheme is required by pkg/client/... + AddToScheme = SchemeBuilder.AddToScheme +) + +// Resource is required by pkg/client/listers/... +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} diff --git a/pkg/apis/network/v1alpha1/v1alpha1_suite_test.go b/pkg/apis/network/v1alpha1/v1alpha1_suite_test.go new file mode 100644 index 000000000..2206160be --- /dev/null +++ b/pkg/apis/network/v1alpha1/v1alpha1_suite_test.go @@ -0,0 +1,55 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "log" + "os" + "path/filepath" + "testing" + + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" +) + +var cfg *rest.Config +var c client.Client + +func TestMain(m *testing.M) { + t := &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "..", "config", "crds")}, + } + + err := SchemeBuilder.AddToScheme(scheme.Scheme) + if err != nil { + log.Fatal(err) + } + + if cfg, err = t.Start(); err != nil { + log.Fatal(err) + } + + if c, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}); err != nil { + log.Fatal(err) + } + + code := m.Run() + t.Stop() + os.Exit(code) +} diff --git a/pkg/apis/network/v1alpha1/workspacenetworkpolicy_types.go b/pkg/apis/network/v1alpha1/workspacenetworkpolicy_types.go new file mode 100644 index 000000000..a5ec84924 --- /dev/null +++ b/pkg/apis/network/v1alpha1/workspacenetworkpolicy_types.go @@ -0,0 +1,138 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + k8snetworkv1 "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// WorkspaceNetworkPolicySpec defines the desired state of WorkspaceNetworkPolicy +type WorkspaceNetworkPolicySpec struct { + // Workspace specify the name of ws to apply this workspace network policy + Workspace string `json:"workspace,omitempty"` + // List of rule types that the WorkspaceNetworkPolicy relates to. + // Valid options are Ingress, Egress, or Ingress,Egress. + // If this field is not specified, it will default based on the existence of Ingress or Egress rules; + // policies that contain an Egress section are assumed to affect Egress, and all policies + // (whether or not they contain an Ingress section) are assumed to affect Ingress. + // If you want to write an egress-only policy, you must explicitly specify policyTypes [ "Egress" ]. + // Likewise, if you want to write a policy that specifies that no egress is allowed, + // you must specify a policyTypes value that include "Egress" (since such a policy would not include + // an Egress section and would otherwise default to just [ "Ingress" ]). + // +optional + PolicyTypes []k8snetworkv1.PolicyType `json:"policyTypes,omitempty" protobuf:"bytes,4,rep,name=policyTypes,casttype=PolicyType"` + // List of ingress rules to be applied to the selected pods. Traffic is allowed to + // a pod if there are no NetworkPolicies selecting the pod + // (and cluster policy otherwise allows the traffic), OR if the traffic source is + // the pod's local node, OR if the traffic matches at least one ingress rule + // across all of the NetworkPolicy objects whose podSelector matches the pod. If + // this field is empty then this NetworkPolicy does not allow any traffic (and serves + // solely to ensure that the pods it selects are isolated by default) + // +optional + Ingress []WorkspaceNetworkPolicyIngressRule `json:"ingress,omitempty" protobuf:"bytes,2,rep,name=ingress"` + + // List of egress rules to be applied to the selected pods. Outgoing traffic is + // allowed if there are no NetworkPolicies selecting the pod (and cluster policy + // otherwise allows the traffic), OR if the traffic matches at least one egress rule + // across all of the NetworkPolicy objects whose podSelector matches the pod. If + // this field is empty then this NetworkPolicy limits all outgoing traffic (and serves + // solely to ensure that the pods it selects are isolated by default). + // This field is beta-level in 1.8 + // +optional + Egress []WorkspaceNetworkPolicyEgressRule `json:"egress,omitempty" protobuf:"bytes,3,rep,name=egress"` +} + +// WorkspaceNetworkPolicyStatus defines the observed state of WorkspaceNetworkPolicy +type WorkspaceNetworkPolicyStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file +} + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// WorkspaceNetworkPolicy is a set of network policies applied to the scope to workspace +// +k8s:openapi-gen=true +type WorkspaceNetworkPolicy struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec WorkspaceNetworkPolicySpec `json:"spec,omitempty"` + Status WorkspaceNetworkPolicyStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// WorkspaceNetworkPolicyList contains a list of WorkspaceNetworkPolicy +type WorkspaceNetworkPolicyList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []WorkspaceNetworkPolicy `json:"items"` +} + +// WorkspaceNetworkPolicyIngressRule describes a particular set of traffic that is allowed to the pods +// matched by a WorkspaceNetworkPolicySpec's podSelector. The traffic must match both ports and from. +type WorkspaceNetworkPolicyIngressRule struct { + // List of ports which should be made accessible on the pods selected for this + // rule. Each item in this list is combined using a logical OR. If this field is + // empty or missing, this rule matches all ports (traffic not restricted by port). + // If this field is present and contains at least one item, then this rule allows + // traffic only if the traffic matches at least one port in the list. + // +optional + Ports []k8snetworkv1.NetworkPolicyPort `json:"ports,omitempty" protobuf:"bytes,1,rep,name=ports"` + + // List of sources which should be able to access the pods selected for this rule. + // Items in this list are combined using a logical OR operation. If this field is + // empty or missing, this rule matches all sources (traffic not restricted by + // source). If this field is present and contains at least on item, this rule + // allows traffic only if the traffic matches at least one item in the from list. + // +optional + From []WorkspaceNetworkPolicyPeer `json:"from,omitempty" protobuf:"bytes,2,rep,name=from"` +} + +// WorkspaceNetworkPolicyPeer describes a peer to allow traffic from. Only certain combinations of +// fields are allowed. It is same as 'NetworkPolicyPeer' in k8s but with an additional field 'WorkspaceSelector' +type WorkspaceNetworkPolicyPeer struct { + k8snetworkv1.NetworkPolicyPeer `json:",inline"` + WorkspaceSelector *metav1.LabelSelector `json:"workspaceSelector,omitempty"` +} + +// WorkspaceNetworkPolicyEgressRule describes a particular set of traffic that is allowed out of pods +// matched by a WorkspaceNetworkPolicySpec's podSelector. The traffic must match both ports and to. +type WorkspaceNetworkPolicyEgressRule struct { + // List of ports which should be made accessible on the pods selected for this + // rule. Each item in this list is combined using a logical OR. If this field is + // empty or missing, this rule matches all ports (traffic not restricted by port). + // If this field is present and contains at least one item, then this rule allows + // traffic only if the traffic matches at least one port in the list. + // +optional + Ports []k8snetworkv1.NetworkPolicyPort `json:"ports,omitempty" protobuf:"bytes,1,rep,name=ports"` + + // List of sources which should be able to access the pods selected for this rule. + // Items in this list are combined using a logical OR operation. If this field is + // empty or missing, this rule matches all sources (traffic not restricted by + // source). If this field is present and contains at least on item, this rule + // allows traffic only if the traffic matches at least one item in the from list. + // +optional + To []WorkspaceNetworkPolicyPeer `json:"from,omitempty" protobuf:"bytes,2,rep,name=from"` +} + +func init() { + SchemeBuilder.Register(&WorkspaceNetworkPolicy{}, &WorkspaceNetworkPolicyList{}) +} diff --git a/pkg/apis/network/v1alpha1/workspacenetworkpolicy_types_test.go b/pkg/apis/network/v1alpha1/workspacenetworkpolicy_types_test.go new file mode 100644 index 000000000..134655158 --- /dev/null +++ b/pkg/apis/network/v1alpha1/workspacenetworkpolicy_types_test.go @@ -0,0 +1,56 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "testing" + + "github.com/onsi/gomega" + "golang.org/x/net/context" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +func TestStorageWorkspaceNetworkPolicy(t *testing.T) { + key := types.NamespacedName{ + Name: "foo", + } + created := &WorkspaceNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + }} + g := gomega.NewGomegaWithT(t) + + // Test Create + fetched := &WorkspaceNetworkPolicy{} + g.Expect(c.Create(context.TODO(), created)).To(gomega.Succeed()) + + g.Expect(c.Get(context.TODO(), key, fetched)).To(gomega.Succeed()) + g.Expect(fetched).To(gomega.Equal(created)) + + // Test Updating the Labels + updated := fetched.DeepCopy() + updated.Labels = map[string]string{"hello": "world"} + g.Expect(c.Update(context.TODO(), updated)).To(gomega.Succeed()) + + g.Expect(c.Get(context.TODO(), key, fetched)).To(gomega.Succeed()) + g.Expect(fetched).To(gomega.Equal(updated)) + + // Test Delete + g.Expect(c.Delete(context.TODO(), fetched)).To(gomega.Succeed()) + g.Expect(c.Get(context.TODO(), key, fetched)).ToNot(gomega.Succeed()) +} diff --git a/pkg/apis/network/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/network/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 000000000..d01da1d0a --- /dev/null +++ b/pkg/apis/network/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,214 @@ +// +build !ignore_autogenerated + +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// autogenerated by controller-gen object, do not modify manually + +package v1alpha1 + +import ( + "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspaceNetworkPolicy) DeepCopyInto(out *WorkspaceNetworkPolicy) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceNetworkPolicy. +func (in *WorkspaceNetworkPolicy) DeepCopy() *WorkspaceNetworkPolicy { + if in == nil { + return nil + } + out := new(WorkspaceNetworkPolicy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *WorkspaceNetworkPolicy) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspaceNetworkPolicyEgressRule) DeepCopyInto(out *WorkspaceNetworkPolicyEgressRule) { + *out = *in + if in.Ports != nil { + in, out := &in.Ports, &out.Ports + *out = make([]v1.NetworkPolicyPort, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.To != nil { + in, out := &in.To, &out.To + *out = make([]WorkspaceNetworkPolicyPeer, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceNetworkPolicyEgressRule. +func (in *WorkspaceNetworkPolicyEgressRule) DeepCopy() *WorkspaceNetworkPolicyEgressRule { + if in == nil { + return nil + } + out := new(WorkspaceNetworkPolicyEgressRule) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspaceNetworkPolicyIngressRule) DeepCopyInto(out *WorkspaceNetworkPolicyIngressRule) { + *out = *in + if in.Ports != nil { + in, out := &in.Ports, &out.Ports + *out = make([]v1.NetworkPolicyPort, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.From != nil { + in, out := &in.From, &out.From + *out = make([]WorkspaceNetworkPolicyPeer, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceNetworkPolicyIngressRule. +func (in *WorkspaceNetworkPolicyIngressRule) DeepCopy() *WorkspaceNetworkPolicyIngressRule { + if in == nil { + return nil + } + out := new(WorkspaceNetworkPolicyIngressRule) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspaceNetworkPolicyList) DeepCopyInto(out *WorkspaceNetworkPolicyList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]WorkspaceNetworkPolicy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceNetworkPolicyList. +func (in *WorkspaceNetworkPolicyList) DeepCopy() *WorkspaceNetworkPolicyList { + if in == nil { + return nil + } + out := new(WorkspaceNetworkPolicyList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *WorkspaceNetworkPolicyList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspaceNetworkPolicyPeer) DeepCopyInto(out *WorkspaceNetworkPolicyPeer) { + *out = *in + in.NetworkPolicyPeer.DeepCopyInto(&out.NetworkPolicyPeer) + if in.WorkspaceSelector != nil { + in, out := &in.WorkspaceSelector, &out.WorkspaceSelector + *out = new(metav1.LabelSelector) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceNetworkPolicyPeer. +func (in *WorkspaceNetworkPolicyPeer) DeepCopy() *WorkspaceNetworkPolicyPeer { + if in == nil { + return nil + } + out := new(WorkspaceNetworkPolicyPeer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspaceNetworkPolicySpec) DeepCopyInto(out *WorkspaceNetworkPolicySpec) { + *out = *in + if in.PolicyTypes != nil { + in, out := &in.PolicyTypes, &out.PolicyTypes + *out = make([]v1.PolicyType, len(*in)) + copy(*out, *in) + } + if in.Ingress != nil { + in, out := &in.Ingress, &out.Ingress + *out = make([]WorkspaceNetworkPolicyIngressRule, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Egress != nil { + in, out := &in.Egress, &out.Egress + *out = make([]WorkspaceNetworkPolicyEgressRule, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceNetworkPolicySpec. +func (in *WorkspaceNetworkPolicySpec) DeepCopy() *WorkspaceNetworkPolicySpec { + if in == nil { + return nil + } + out := new(WorkspaceNetworkPolicySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspaceNetworkPolicyStatus) DeepCopyInto(out *WorkspaceNetworkPolicyStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceNetworkPolicyStatus. +func (in *WorkspaceNetworkPolicyStatus) DeepCopy() *WorkspaceNetworkPolicyStatus { + if in == nil { + return nil + } + out := new(WorkspaceNetworkPolicyStatus) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/apis/servicemesh/v1alpha2/zz_generated.deepcopy.go b/pkg/apis/servicemesh/v1alpha2/zz_generated.deepcopy.go index f16f7ebb5..ad3e11fdb 100644 --- a/pkg/apis/servicemesh/v1alpha2/zz_generated.deepcopy.go +++ b/pkg/apis/servicemesh/v1alpha2/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright The Kubernetes Authors. +Copyright 2019 The KubeSphere authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -16,12 +16,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Code generated by deepcopy-gen. DO NOT EDIT. +// autogenerated by controller-gen object, do not modify manually package v1alpha2 import ( - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -30,7 +30,6 @@ func (in *DestinationRuleSpecTemplate) DeepCopyInto(out *DestinationRuleSpecTemp *out = *in in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) in.Spec.DeepCopyInto(&out.Spec) - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DestinationRuleSpecTemplate. @@ -50,7 +49,6 @@ func (in *ServicePolicy) DeepCopyInto(out *ServicePolicy) { in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) in.Spec.DeepCopyInto(&out.Spec) in.Status.DeepCopyInto(&out.Status) - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServicePolicy. @@ -76,7 +74,6 @@ func (in *ServicePolicyCondition) DeepCopyInto(out *ServicePolicyCondition) { *out = *in in.LastProbeTime.DeepCopyInto(&out.LastProbeTime) in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServicePolicyCondition. @@ -101,7 +98,6 @@ func (in *ServicePolicyList) DeepCopyInto(out *ServicePolicyList) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServicePolicyList. @@ -131,7 +127,6 @@ func (in *ServicePolicySpec) DeepCopyInto(out *ServicePolicySpec) { (*in).DeepCopyInto(*out) } in.Template.DeepCopyInto(&out.Template) - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServicePolicySpec. @@ -156,13 +151,14 @@ func (in *ServicePolicyStatus) DeepCopyInto(out *ServicePolicyStatus) { } if in.StartTime != nil { in, out := &in.StartTime, &out.StartTime - *out = (*in).DeepCopy() + *out = new(v1.Time) + (*in).DeepCopyInto(*out) } if in.CompletionTime != nil { in, out := &in.CompletionTime, &out.CompletionTime - *out = (*in).DeepCopy() + *out = new(v1.Time) + (*in).DeepCopyInto(*out) } - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServicePolicyStatus. @@ -182,7 +178,6 @@ func (in *Strategy) DeepCopyInto(out *Strategy) { in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) in.Spec.DeepCopyInto(&out.Spec) in.Status.DeepCopyInto(&out.Status) - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Strategy. @@ -208,7 +203,6 @@ func (in *StrategyCondition) DeepCopyInto(out *StrategyCondition) { *out = *in in.LastProbeTime.DeepCopyInto(&out.LastProbeTime) in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StrategyCondition. @@ -233,7 +227,6 @@ func (in *StrategyList) DeepCopyInto(out *StrategyList) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StrategyList. @@ -263,7 +256,6 @@ func (in *StrategySpec) DeepCopyInto(out *StrategySpec) { (*in).DeepCopyInto(*out) } in.Template.DeepCopyInto(&out.Template) - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StrategySpec. @@ -288,13 +280,14 @@ func (in *StrategyStatus) DeepCopyInto(out *StrategyStatus) { } if in.StartTime != nil { in, out := &in.StartTime, &out.StartTime - *out = (*in).DeepCopy() + *out = new(v1.Time) + (*in).DeepCopyInto(*out) } if in.CompletionTime != nil { in, out := &in.CompletionTime, &out.CompletionTime - *out = (*in).DeepCopy() + *out = new(v1.Time) + (*in).DeepCopyInto(*out) } - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StrategyStatus. @@ -312,7 +305,6 @@ func (in *VirtualServiceTemplateSpec) DeepCopyInto(out *VirtualServiceTemplateSp *out = *in in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) in.Spec.DeepCopyInto(&out.Spec) - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualServiceTemplateSpec. diff --git a/pkg/apis/tenant/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/tenant/v1alpha1/zz_generated.deepcopy.go index 12e60b27d..9096edb38 100644 --- a/pkg/apis/tenant/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/tenant/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright The Kubernetes Authors. +Copyright 2019 The KubeSphere authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -16,7 +16,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Code generated by deepcopy-gen. DO NOT EDIT. +// autogenerated by controller-gen object, do not modify manually package v1alpha1 @@ -31,7 +31,6 @@ func (in *Workspace) DeepCopyInto(out *Workspace) { in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) out.Spec = in.Spec out.Status = in.Status - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Workspace. @@ -64,7 +63,6 @@ func (in *WorkspaceList) DeepCopyInto(out *WorkspaceList) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceList. @@ -88,7 +86,6 @@ func (in *WorkspaceList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspaceSpec) DeepCopyInto(out *WorkspaceSpec) { *out = *in - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceSpec. @@ -104,7 +101,6 @@ func (in *WorkspaceSpec) DeepCopy() *WorkspaceSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspaceStatus) DeepCopyInto(out *WorkspaceStatus) { *out = *in - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceStatus. diff --git a/pkg/client/clientset/versioned/clientset.go b/pkg/client/clientset/versioned/clientset.go index 70342b04d..4ae271d29 100644 --- a/pkg/client/clientset/versioned/clientset.go +++ b/pkg/client/clientset/versioned/clientset.go @@ -22,12 +22,16 @@ import ( discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" + networkv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/network/v1alpha1" servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/servicemesh/v1alpha2" tenantv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/tenant/v1alpha1" ) type Interface interface { Discovery() discovery.DiscoveryInterface + NetworkV1alpha1() networkv1alpha1.NetworkV1alpha1Interface + // Deprecated: please explicitly pick a version if possible. + Network() networkv1alpha1.NetworkV1alpha1Interface ServicemeshV1alpha2() servicemeshv1alpha2.ServicemeshV1alpha2Interface // Deprecated: please explicitly pick a version if possible. Servicemesh() servicemeshv1alpha2.ServicemeshV1alpha2Interface @@ -40,10 +44,22 @@ type Interface interface { // version included in a Clientset. type Clientset struct { *discovery.DiscoveryClient + networkV1alpha1 *networkv1alpha1.NetworkV1alpha1Client servicemeshV1alpha2 *servicemeshv1alpha2.ServicemeshV1alpha2Client tenantV1alpha1 *tenantv1alpha1.TenantV1alpha1Client } +// NetworkV1alpha1 retrieves the NetworkV1alpha1Client +func (c *Clientset) NetworkV1alpha1() networkv1alpha1.NetworkV1alpha1Interface { + return c.networkV1alpha1 +} + +// Deprecated: Network retrieves the default version of NetworkClient. +// Please explicitly pick a version. +func (c *Clientset) Network() networkv1alpha1.NetworkV1alpha1Interface { + return c.networkV1alpha1 +} + // ServicemeshV1alpha2 retrieves the ServicemeshV1alpha2Client func (c *Clientset) ServicemeshV1alpha2() servicemeshv1alpha2.ServicemeshV1alpha2Interface { return c.servicemeshV1alpha2 @@ -82,6 +98,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { } var cs Clientset var err error + cs.networkV1alpha1, err = networkv1alpha1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } cs.servicemeshV1alpha2, err = servicemeshv1alpha2.NewForConfig(&configShallowCopy) if err != nil { return nil, err @@ -102,6 +122,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { // panics if there is an error in the config. func NewForConfigOrDie(c *rest.Config) *Clientset { var cs Clientset + cs.networkV1alpha1 = networkv1alpha1.NewForConfigOrDie(c) cs.servicemeshV1alpha2 = servicemeshv1alpha2.NewForConfigOrDie(c) cs.tenantV1alpha1 = tenantv1alpha1.NewForConfigOrDie(c) @@ -112,6 +133,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset { // New creates a new Clientset for the given RESTClient. func New(c rest.Interface) *Clientset { var cs Clientset + cs.networkV1alpha1 = networkv1alpha1.New(c) cs.servicemeshV1alpha2 = servicemeshv1alpha2.New(c) cs.tenantV1alpha1 = tenantv1alpha1.New(c) diff --git a/pkg/client/clientset/versioned/fake/clientset_generated.go b/pkg/client/clientset/versioned/fake/clientset_generated.go index 9e7380c49..6e063c05c 100644 --- a/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -25,6 +25,8 @@ import ( fakediscovery "k8s.io/client-go/discovery/fake" "k8s.io/client-go/testing" clientset "kubesphere.io/kubesphere/pkg/client/clientset/versioned" + networkv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/network/v1alpha1" + fakenetworkv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/network/v1alpha1/fake" servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/servicemesh/v1alpha2" fakeservicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/servicemesh/v1alpha2/fake" tenantv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/tenant/v1alpha1" @@ -73,6 +75,16 @@ func (c *Clientset) Discovery() discovery.DiscoveryInterface { var _ clientset.Interface = &Clientset{} +// NetworkV1alpha1 retrieves the NetworkV1alpha1Client +func (c *Clientset) NetworkV1alpha1() networkv1alpha1.NetworkV1alpha1Interface { + return &fakenetworkv1alpha1.FakeNetworkV1alpha1{Fake: &c.Fake} +} + +// Network retrieves the NetworkV1alpha1Client +func (c *Clientset) Network() networkv1alpha1.NetworkV1alpha1Interface { + return &fakenetworkv1alpha1.FakeNetworkV1alpha1{Fake: &c.Fake} +} + // ServicemeshV1alpha2 retrieves the ServicemeshV1alpha2Client func (c *Clientset) ServicemeshV1alpha2() servicemeshv1alpha2.ServicemeshV1alpha2Interface { return &fakeservicemeshv1alpha2.FakeServicemeshV1alpha2{Fake: &c.Fake} diff --git a/pkg/client/clientset/versioned/fake/register.go b/pkg/client/clientset/versioned/fake/register.go index 2698edceb..6602ca986 100644 --- a/pkg/client/clientset/versioned/fake/register.go +++ b/pkg/client/clientset/versioned/fake/register.go @@ -24,6 +24,7 @@ import ( schema "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + networkv1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/apis/servicemesh/v1alpha2" tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1" ) @@ -32,6 +33,7 @@ var scheme = runtime.NewScheme() var codecs = serializer.NewCodecFactory(scheme) var parameterCodec = runtime.NewParameterCodec(scheme) var localSchemeBuilder = runtime.SchemeBuilder{ + networkv1alpha1.AddToScheme, servicemeshv1alpha2.AddToScheme, tenantv1alpha1.AddToScheme, } diff --git a/pkg/client/clientset/versioned/scheme/register.go b/pkg/client/clientset/versioned/scheme/register.go index 5d3335afa..c8d08cb3b 100644 --- a/pkg/client/clientset/versioned/scheme/register.go +++ b/pkg/client/clientset/versioned/scheme/register.go @@ -24,6 +24,7 @@ import ( schema "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + networkv1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/apis/servicemesh/v1alpha2" tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1" ) @@ -32,6 +33,7 @@ var Scheme = runtime.NewScheme() var Codecs = serializer.NewCodecFactory(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme) var localSchemeBuilder = runtime.SchemeBuilder{ + networkv1alpha1.AddToScheme, servicemeshv1alpha2.AddToScheme, tenantv1alpha1.AddToScheme, } diff --git a/pkg/client/clientset/versioned/typed/network/v1alpha1/doc.go b/pkg/client/clientset/versioned/typed/network/v1alpha1/doc.go new file mode 100644 index 000000000..df51baa4d --- /dev/null +++ b/pkg/client/clientset/versioned/typed/network/v1alpha1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/doc.go b/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/doc.go new file mode 100644 index 000000000..16f443990 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_network_client.go b/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_network_client.go new file mode 100644 index 000000000..0588efd8e --- /dev/null +++ b/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_network_client.go @@ -0,0 +1,40 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" + v1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/network/v1alpha1" +) + +type FakeNetworkV1alpha1 struct { + *testing.Fake +} + +func (c *FakeNetworkV1alpha1) WorkspaceNetworkPolicies() v1alpha1.WorkspaceNetworkPolicyInterface { + return &FakeWorkspaceNetworkPolicies{c} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeNetworkV1alpha1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_workspacenetworkpolicy.go b/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_workspacenetworkpolicy.go new file mode 100644 index 000000000..499c730fa --- /dev/null +++ b/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_workspacenetworkpolicy.go @@ -0,0 +1,131 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" +) + +// FakeWorkspaceNetworkPolicies implements WorkspaceNetworkPolicyInterface +type FakeWorkspaceNetworkPolicies struct { + Fake *FakeNetworkV1alpha1 +} + +var workspacenetworkpoliciesResource = schema.GroupVersionResource{Group: "network.kubesphere.io", Version: "v1alpha1", Resource: "workspacenetworkpolicies"} + +var workspacenetworkpoliciesKind = schema.GroupVersionKind{Group: "network.kubesphere.io", Version: "v1alpha1", Kind: "WorkspaceNetworkPolicy"} + +// Get takes name of the workspaceNetworkPolicy, and returns the corresponding workspaceNetworkPolicy object, and an error if there is any. +func (c *FakeWorkspaceNetworkPolicies) Get(name string, options v1.GetOptions) (result *v1alpha1.WorkspaceNetworkPolicy, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(workspacenetworkpoliciesResource, name), &v1alpha1.WorkspaceNetworkPolicy{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.WorkspaceNetworkPolicy), err +} + +// List takes label and field selectors, and returns the list of WorkspaceNetworkPolicies that match those selectors. +func (c *FakeWorkspaceNetworkPolicies) List(opts v1.ListOptions) (result *v1alpha1.WorkspaceNetworkPolicyList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(workspacenetworkpoliciesResource, workspacenetworkpoliciesKind, opts), &v1alpha1.WorkspaceNetworkPolicyList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.WorkspaceNetworkPolicyList{ListMeta: obj.(*v1alpha1.WorkspaceNetworkPolicyList).ListMeta} + for _, item := range obj.(*v1alpha1.WorkspaceNetworkPolicyList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested workspaceNetworkPolicies. +func (c *FakeWorkspaceNetworkPolicies) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(workspacenetworkpoliciesResource, opts)) +} + +// Create takes the representation of a workspaceNetworkPolicy and creates it. Returns the server's representation of the workspaceNetworkPolicy, and an error, if there is any. +func (c *FakeWorkspaceNetworkPolicies) Create(workspaceNetworkPolicy *v1alpha1.WorkspaceNetworkPolicy) (result *v1alpha1.WorkspaceNetworkPolicy, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(workspacenetworkpoliciesResource, workspaceNetworkPolicy), &v1alpha1.WorkspaceNetworkPolicy{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.WorkspaceNetworkPolicy), err +} + +// Update takes the representation of a workspaceNetworkPolicy and updates it. Returns the server's representation of the workspaceNetworkPolicy, and an error, if there is any. +func (c *FakeWorkspaceNetworkPolicies) Update(workspaceNetworkPolicy *v1alpha1.WorkspaceNetworkPolicy) (result *v1alpha1.WorkspaceNetworkPolicy, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(workspacenetworkpoliciesResource, workspaceNetworkPolicy), &v1alpha1.WorkspaceNetworkPolicy{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.WorkspaceNetworkPolicy), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeWorkspaceNetworkPolicies) UpdateStatus(workspaceNetworkPolicy *v1alpha1.WorkspaceNetworkPolicy) (*v1alpha1.WorkspaceNetworkPolicy, error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(workspacenetworkpoliciesResource, "status", workspaceNetworkPolicy), &v1alpha1.WorkspaceNetworkPolicy{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.WorkspaceNetworkPolicy), err +} + +// Delete takes name of the workspaceNetworkPolicy and deletes it. Returns an error if one occurs. +func (c *FakeWorkspaceNetworkPolicies) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(workspacenetworkpoliciesResource, name), &v1alpha1.WorkspaceNetworkPolicy{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeWorkspaceNetworkPolicies) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(workspacenetworkpoliciesResource, listOptions) + + _, err := c.Fake.Invokes(action, &v1alpha1.WorkspaceNetworkPolicyList{}) + return err +} + +// Patch applies the patch and returns the patched workspaceNetworkPolicy. +func (c *FakeWorkspaceNetworkPolicies) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.WorkspaceNetworkPolicy, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(workspacenetworkpoliciesResource, name, pt, data, subresources...), &v1alpha1.WorkspaceNetworkPolicy{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.WorkspaceNetworkPolicy), err +} diff --git a/pkg/client/clientset/versioned/typed/network/v1alpha1/generated_expansion.go b/pkg/client/clientset/versioned/typed/network/v1alpha1/generated_expansion.go new file mode 100644 index 000000000..526e35bb5 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/network/v1alpha1/generated_expansion.go @@ -0,0 +1,21 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +type WorkspaceNetworkPolicyExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/network/v1alpha1/network_client.go b/pkg/client/clientset/versioned/typed/network/v1alpha1/network_client.go new file mode 100644 index 000000000..9319c616b --- /dev/null +++ b/pkg/client/clientset/versioned/typed/network/v1alpha1/network_client.go @@ -0,0 +1,90 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + rest "k8s.io/client-go/rest" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" + "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme" +) + +type NetworkV1alpha1Interface interface { + RESTClient() rest.Interface + WorkspaceNetworkPoliciesGetter +} + +// NetworkV1alpha1Client is used to interact with features provided by the network.kubesphere.io group. +type NetworkV1alpha1Client struct { + restClient rest.Interface +} + +func (c *NetworkV1alpha1Client) WorkspaceNetworkPolicies() WorkspaceNetworkPolicyInterface { + return newWorkspaceNetworkPolicies(c) +} + +// NewForConfig creates a new NetworkV1alpha1Client for the given config. +func NewForConfig(c *rest.Config) (*NetworkV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &NetworkV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new NetworkV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *NetworkV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new NetworkV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *NetworkV1alpha1Client { + return &NetworkV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *NetworkV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/pkg/client/clientset/versioned/typed/network/v1alpha1/workspacenetworkpolicy.go b/pkg/client/clientset/versioned/typed/network/v1alpha1/workspacenetworkpolicy.go new file mode 100644 index 000000000..3b4f29f80 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/network/v1alpha1/workspacenetworkpolicy.go @@ -0,0 +1,180 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" + scheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme" +) + +// WorkspaceNetworkPoliciesGetter has a method to return a WorkspaceNetworkPolicyInterface. +// A group's client should implement this interface. +type WorkspaceNetworkPoliciesGetter interface { + WorkspaceNetworkPolicies() WorkspaceNetworkPolicyInterface +} + +// WorkspaceNetworkPolicyInterface has methods to work with WorkspaceNetworkPolicy resources. +type WorkspaceNetworkPolicyInterface interface { + Create(*v1alpha1.WorkspaceNetworkPolicy) (*v1alpha1.WorkspaceNetworkPolicy, error) + Update(*v1alpha1.WorkspaceNetworkPolicy) (*v1alpha1.WorkspaceNetworkPolicy, error) + UpdateStatus(*v1alpha1.WorkspaceNetworkPolicy) (*v1alpha1.WorkspaceNetworkPolicy, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.WorkspaceNetworkPolicy, error) + List(opts v1.ListOptions) (*v1alpha1.WorkspaceNetworkPolicyList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.WorkspaceNetworkPolicy, err error) + WorkspaceNetworkPolicyExpansion +} + +// workspaceNetworkPolicies implements WorkspaceNetworkPolicyInterface +type workspaceNetworkPolicies struct { + client rest.Interface +} + +// newWorkspaceNetworkPolicies returns a WorkspaceNetworkPolicies +func newWorkspaceNetworkPolicies(c *NetworkV1alpha1Client) *workspaceNetworkPolicies { + return &workspaceNetworkPolicies{ + client: c.RESTClient(), + } +} + +// Get takes name of the workspaceNetworkPolicy, and returns the corresponding workspaceNetworkPolicy object, and an error if there is any. +func (c *workspaceNetworkPolicies) Get(name string, options v1.GetOptions) (result *v1alpha1.WorkspaceNetworkPolicy, err error) { + result = &v1alpha1.WorkspaceNetworkPolicy{} + err = c.client.Get(). + Resource("workspacenetworkpolicies"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of WorkspaceNetworkPolicies that match those selectors. +func (c *workspaceNetworkPolicies) List(opts v1.ListOptions) (result *v1alpha1.WorkspaceNetworkPolicyList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.WorkspaceNetworkPolicyList{} + err = c.client.Get(). + Resource("workspacenetworkpolicies"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested workspaceNetworkPolicies. +func (c *workspaceNetworkPolicies) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("workspacenetworkpolicies"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a workspaceNetworkPolicy and creates it. Returns the server's representation of the workspaceNetworkPolicy, and an error, if there is any. +func (c *workspaceNetworkPolicies) Create(workspaceNetworkPolicy *v1alpha1.WorkspaceNetworkPolicy) (result *v1alpha1.WorkspaceNetworkPolicy, err error) { + result = &v1alpha1.WorkspaceNetworkPolicy{} + err = c.client.Post(). + Resource("workspacenetworkpolicies"). + Body(workspaceNetworkPolicy). + Do(). + Into(result) + return +} + +// Update takes the representation of a workspaceNetworkPolicy and updates it. Returns the server's representation of the workspaceNetworkPolicy, and an error, if there is any. +func (c *workspaceNetworkPolicies) Update(workspaceNetworkPolicy *v1alpha1.WorkspaceNetworkPolicy) (result *v1alpha1.WorkspaceNetworkPolicy, err error) { + result = &v1alpha1.WorkspaceNetworkPolicy{} + err = c.client.Put(). + Resource("workspacenetworkpolicies"). + Name(workspaceNetworkPolicy.Name). + Body(workspaceNetworkPolicy). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *workspaceNetworkPolicies) UpdateStatus(workspaceNetworkPolicy *v1alpha1.WorkspaceNetworkPolicy) (result *v1alpha1.WorkspaceNetworkPolicy, err error) { + result = &v1alpha1.WorkspaceNetworkPolicy{} + err = c.client.Put(). + Resource("workspacenetworkpolicies"). + Name(workspaceNetworkPolicy.Name). + SubResource("status"). + Body(workspaceNetworkPolicy). + Do(). + Into(result) + return +} + +// Delete takes name of the workspaceNetworkPolicy and deletes it. Returns an error if one occurs. +func (c *workspaceNetworkPolicies) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Resource("workspacenetworkpolicies"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *workspaceNetworkPolicies) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("workspacenetworkpolicies"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched workspaceNetworkPolicy. +func (c *workspaceNetworkPolicies) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.WorkspaceNetworkPolicy, err error) { + result = &v1alpha1.WorkspaceNetworkPolicy{} + err = c.client.Patch(pt). + Resource("workspacenetworkpolicies"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/client/informers/externalversions/factory.go b/pkg/client/informers/externalversions/factory.go index 200efe448..dc0a9de93 100644 --- a/pkg/client/informers/externalversions/factory.go +++ b/pkg/client/informers/externalversions/factory.go @@ -29,6 +29,7 @@ import ( cache "k8s.io/client-go/tools/cache" versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned" internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces" + network "kubesphere.io/kubesphere/pkg/client/informers/externalversions/network" servicemesh "kubesphere.io/kubesphere/pkg/client/informers/externalversions/servicemesh" tenant "kubesphere.io/kubesphere/pkg/client/informers/externalversions/tenant" ) @@ -173,10 +174,15 @@ type SharedInformerFactory interface { ForResource(resource schema.GroupVersionResource) (GenericInformer, error) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + Network() network.Interface Servicemesh() servicemesh.Interface Tenant() tenant.Interface } +func (f *sharedInformerFactory) Network() network.Interface { + return network.New(f, f.namespace, f.tweakListOptions) +} + func (f *sharedInformerFactory) Servicemesh() servicemesh.Interface { return servicemesh.New(f, f.namespace, f.tweakListOptions) } diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index ab24560f8..a0317ce7a 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -23,8 +23,9 @@ import ( schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" v1alpha2 "kubesphere.io/kubesphere/pkg/apis/servicemesh/v1alpha2" - v1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1" + tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1" ) // GenericInformer is type of SharedIndexInformer which will locate and delegate to other @@ -53,14 +54,18 @@ func (f *genericInformer) Lister() cache.GenericLister { // TODO extend this to unknown resources with a client pool func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { - // Group=servicemesh.kubesphere.io, Version=v1alpha2 + // Group=network.kubesphere.io, Version=v1alpha1 + case v1alpha1.SchemeGroupVersion.WithResource("workspacenetworkpolicies"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Network().V1alpha1().WorkspaceNetworkPolicies().Informer()}, nil + + // Group=servicemesh.kubesphere.io, Version=v1alpha2 case v1alpha2.SchemeGroupVersion.WithResource("servicepolicies"): return &genericInformer{resource: resource.GroupResource(), informer: f.Servicemesh().V1alpha2().ServicePolicies().Informer()}, nil case v1alpha2.SchemeGroupVersion.WithResource("strategies"): return &genericInformer{resource: resource.GroupResource(), informer: f.Servicemesh().V1alpha2().Strategies().Informer()}, nil // Group=tenant.kubesphere.io, Version=v1alpha1 - case v1alpha1.SchemeGroupVersion.WithResource("workspaces"): + case tenantv1alpha1.SchemeGroupVersion.WithResource("workspaces"): return &genericInformer{resource: resource.GroupResource(), informer: f.Tenant().V1alpha1().Workspaces().Informer()}, nil } diff --git a/pkg/client/informers/externalversions/network/interface.go b/pkg/client/informers/externalversions/network/interface.go new file mode 100644 index 000000000..83232bcd6 --- /dev/null +++ b/pkg/client/informers/externalversions/network/interface.go @@ -0,0 +1,46 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package network + +import ( + internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces" + v1alpha1 "kubesphere.io/kubesphere/pkg/client/informers/externalversions/network/v1alpha1" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1alpha1 provides access to shared informers for resources in V1alpha1. + V1alpha1() v1alpha1.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// V1alpha1 returns a new v1alpha1.Interface. +func (g *group) V1alpha1() v1alpha1.Interface { + return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/pkg/client/informers/externalversions/network/v1alpha1/interface.go b/pkg/client/informers/externalversions/network/v1alpha1/interface.go new file mode 100644 index 000000000..34158dc3c --- /dev/null +++ b/pkg/client/informers/externalversions/network/v1alpha1/interface.go @@ -0,0 +1,45 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // WorkspaceNetworkPolicies returns a WorkspaceNetworkPolicyInformer. + WorkspaceNetworkPolicies() WorkspaceNetworkPolicyInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// WorkspaceNetworkPolicies returns a WorkspaceNetworkPolicyInformer. +func (v *version) WorkspaceNetworkPolicies() WorkspaceNetworkPolicyInformer { + return &workspaceNetworkPolicyInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/client/informers/externalversions/network/v1alpha1/workspacenetworkpolicy.go b/pkg/client/informers/externalversions/network/v1alpha1/workspacenetworkpolicy.go new file mode 100644 index 000000000..b75a52125 --- /dev/null +++ b/pkg/client/informers/externalversions/network/v1alpha1/workspacenetworkpolicy.go @@ -0,0 +1,88 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + networkv1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" + versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned" + internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces" + v1alpha1 "kubesphere.io/kubesphere/pkg/client/listers/network/v1alpha1" +) + +// WorkspaceNetworkPolicyInformer provides access to a shared informer and lister for +// WorkspaceNetworkPolicies. +type WorkspaceNetworkPolicyInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.WorkspaceNetworkPolicyLister +} + +type workspaceNetworkPolicyInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewWorkspaceNetworkPolicyInformer constructs a new informer for WorkspaceNetworkPolicy type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewWorkspaceNetworkPolicyInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredWorkspaceNetworkPolicyInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredWorkspaceNetworkPolicyInformer constructs a new informer for WorkspaceNetworkPolicy type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredWorkspaceNetworkPolicyInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.NetworkV1alpha1().WorkspaceNetworkPolicies().List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.NetworkV1alpha1().WorkspaceNetworkPolicies().Watch(options) + }, + }, + &networkv1alpha1.WorkspaceNetworkPolicy{}, + resyncPeriod, + indexers, + ) +} + +func (f *workspaceNetworkPolicyInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredWorkspaceNetworkPolicyInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *workspaceNetworkPolicyInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&networkv1alpha1.WorkspaceNetworkPolicy{}, f.defaultInformer) +} + +func (f *workspaceNetworkPolicyInformer) Lister() v1alpha1.WorkspaceNetworkPolicyLister { + return v1alpha1.NewWorkspaceNetworkPolicyLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/listers/network/v1alpha1/expansion_generated.go b/pkg/client/listers/network/v1alpha1/expansion_generated.go new file mode 100644 index 000000000..19e12fd3d --- /dev/null +++ b/pkg/client/listers/network/v1alpha1/expansion_generated.go @@ -0,0 +1,23 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +// WorkspaceNetworkPolicyListerExpansion allows custom methods to be added to +// WorkspaceNetworkPolicyLister. +type WorkspaceNetworkPolicyListerExpansion interface{} diff --git a/pkg/client/listers/network/v1alpha1/workspacenetworkpolicy.go b/pkg/client/listers/network/v1alpha1/workspacenetworkpolicy.go new file mode 100644 index 000000000..c062a4d14 --- /dev/null +++ b/pkg/client/listers/network/v1alpha1/workspacenetworkpolicy.go @@ -0,0 +1,65 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" +) + +// WorkspaceNetworkPolicyLister helps list WorkspaceNetworkPolicies. +type WorkspaceNetworkPolicyLister interface { + // List lists all WorkspaceNetworkPolicies in the indexer. + List(selector labels.Selector) (ret []*v1alpha1.WorkspaceNetworkPolicy, err error) + // Get retrieves the WorkspaceNetworkPolicy from the index for a given name. + Get(name string) (*v1alpha1.WorkspaceNetworkPolicy, error) + WorkspaceNetworkPolicyListerExpansion +} + +// workspaceNetworkPolicyLister implements the WorkspaceNetworkPolicyLister interface. +type workspaceNetworkPolicyLister struct { + indexer cache.Indexer +} + +// NewWorkspaceNetworkPolicyLister returns a new WorkspaceNetworkPolicyLister. +func NewWorkspaceNetworkPolicyLister(indexer cache.Indexer) WorkspaceNetworkPolicyLister { + return &workspaceNetworkPolicyLister{indexer: indexer} +} + +// List lists all WorkspaceNetworkPolicies in the indexer. +func (s *workspaceNetworkPolicyLister) List(selector labels.Selector) (ret []*v1alpha1.WorkspaceNetworkPolicy, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.WorkspaceNetworkPolicy)) + }) + return ret, err +} + +// Get retrieves the WorkspaceNetworkPolicy from the index for a given name. +func (s *workspaceNetworkPolicyLister) Get(name string) (*v1alpha1.WorkspaceNetworkPolicy, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("workspacenetworkpolicy"), name) + } + return obj.(*v1alpha1.WorkspaceNetworkPolicy), nil +} diff --git a/pkg/controller/network/testing/controller.go b/pkg/controller/network/testing/controller.go new file mode 100644 index 000000000..c958d5dc2 --- /dev/null +++ b/pkg/controller/network/testing/controller.go @@ -0,0 +1,38 @@ +package testing + +import ( + "time" + + "k8s.io/apimachinery/pkg/runtime" + kubeinformers "k8s.io/client-go/informers" + k8sfake "k8s.io/client-go/kubernetes/fake" + "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake" + informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions" +) + +var ( + AlwaysReady = func() bool { return true } + ResyncPeriodFunc = func() time.Duration { return 1 * time.Second } +) + +type FakeControllerBuilder struct { + KsClient *fake.Clientset + KubeClient *k8sfake.Clientset + Kubeobjects []runtime.Object + CRDObjects []runtime.Object +} + +func NewFakeControllerBuilder() *FakeControllerBuilder { + return &FakeControllerBuilder{ + Kubeobjects: make([]runtime.Object, 0), + CRDObjects: make([]runtime.Object, 0), + } +} + +func (f *FakeControllerBuilder) NewControllerInformer() (informers.SharedInformerFactory, kubeinformers.SharedInformerFactory) { + f.KsClient = fake.NewSimpleClientset(f.CRDObjects...) + f.KubeClient = k8sfake.NewSimpleClientset(f.Kubeobjects...) + i := informers.NewSharedInformerFactory(f.KsClient, ResyncPeriodFunc()) + k8sI := kubeinformers.NewSharedInformerFactory(f.KubeClient, ResyncPeriodFunc()) + return i, k8sI +} diff --git a/pkg/controller/network/testing/util.go b/pkg/controller/network/testing/util.go new file mode 100644 index 000000000..a92efd1cd --- /dev/null +++ b/pkg/controller/network/testing/util.go @@ -0,0 +1,12 @@ +package testing + +import ( + "strings" + + "k8s.io/apimachinery/pkg/util/yaml" +) + +func StringToObject(data string, obj interface{}) error { + reader := strings.NewReader(data) + return yaml.NewYAMLOrJSONDecoder(reader, 10).Decode(obj) +} diff --git a/pkg/controller/network/wsnetworkpolicy/controller.go b/pkg/controller/network/wsnetworkpolicy/controller.go new file mode 100644 index 000000000..3c358c8df --- /dev/null +++ b/pkg/controller/network/wsnetworkpolicy/controller.go @@ -0,0 +1,283 @@ +package wsnetworkpolicy + +import ( + "fmt" + "time" + + corev1 "k8s.io/api/core/v1" + k8snetwork "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + corev1informer "k8s.io/client-go/informers/core/v1" + k8snetworkinformer "k8s.io/client-go/informers/networking/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/scheme" + typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" + corev1lister "k8s.io/client-go/listers/core/v1" + k8snetworklister "k8s.io/client-go/listers/networking/v1" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/tools/record" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog" + "k8s.io/klog/klogr" + workspaceapi "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1" + kubesphereclient "kubesphere.io/kubesphere/pkg/client/clientset/versioned" + kubespherescheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme" + networkinformer "kubesphere.io/kubesphere/pkg/client/informers/externalversions/network/v1alpha1" + workspaceinformer "kubesphere.io/kubesphere/pkg/client/informers/externalversions/tenant/v1alpha1" + networklister "kubesphere.io/kubesphere/pkg/client/listers/network/v1alpha1" + workspacelister "kubesphere.io/kubesphere/pkg/client/listers/tenant/v1alpha1" +) + +const controllerAgentName = "wsnp-controller" + +var ( + log = klogr.New().WithName("Controller").WithValues(controllerAgentName) + errCount = 0 +) + +// Controller expose Run method +type Controller interface { + Run(threadiness int, stopCh <-chan struct{}) error +} +type controller struct { + kubeClientset kubernetes.Interface + kubesphereClientset kubesphereclient.Interface + + wsnpInformer networkinformer.WorkspaceNetworkPolicyInformer + wsnpLister networklister.WorkspaceNetworkPolicyLister + wsnpSynced cache.InformerSynced + + networkPolicyInformer k8snetworkinformer.NetworkPolicyInformer + networkPolicyLister k8snetworklister.NetworkPolicyLister + networkPolicySynced cache.InformerSynced + + namespaceLister corev1lister.NamespaceLister + namespaceInformer corev1informer.NamespaceInformer + namespaceSynced cache.InformerSynced + + workspaceLister workspacelister.WorkspaceLister + workspaceInformer workspaceinformer.WorkspaceInformer + workspaceSynced cache.InformerSynced + // workqueue is a rate limited work queue. This is used to queue work to be + // processed instead of performing it as soon as a change happens. This + // means we can ensure we only process a fixed amount of resources at a + // time, and makes it easy to ensure we are never processing the same item + // simultaneously in two different workers. + workqueue workqueue.RateLimitingInterface + // recorder is an event recorder for recording Event resources to the + // Kubernetes API. + recorder record.EventRecorder +} + +func NewController(kubeclientset kubernetes.Interface, + kubesphereclientset kubesphereclient.Interface, + wsnpInformer networkinformer.WorkspaceNetworkPolicyInformer, + networkPolicyInformer k8snetworkinformer.NetworkPolicyInformer, + namespaceInformer corev1informer.NamespaceInformer, + workspaceInformer workspaceinformer.WorkspaceInformer) Controller { + utilruntime.Must(kubespherescheme.AddToScheme(scheme.Scheme)) + log.V(4).Info("Creating event broadcaster") + eventBroadcaster := record.NewBroadcaster() + eventBroadcaster.StartLogging(klog.Infof) + eventBroadcaster.StartRecordingToSink(&typedcorev1.EventSinkImpl{Interface: kubeclientset.CoreV1().Events("")}) + recorder := eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: controllerAgentName}) + ctl := &controller{ + kubeClientset: kubeclientset, + kubesphereClientset: kubesphereclientset, + wsnpInformer: wsnpInformer, + wsnpLister: wsnpInformer.Lister(), + wsnpSynced: wsnpInformer.Informer().HasSynced, + networkPolicyInformer: networkPolicyInformer, + networkPolicyLister: networkPolicyInformer.Lister(), + networkPolicySynced: networkPolicyInformer.Informer().HasSynced, + namespaceInformer: namespaceInformer, + namespaceLister: namespaceInformer.Lister(), + namespaceSynced: namespaceInformer.Informer().HasSynced, + workspaceInformer: workspaceInformer, + workspaceLister: workspaceInformer.Lister(), + workspaceSynced: workspaceInformer.Informer().HasSynced, + + workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "WorkspaceNetworkPolicies"), + recorder: recorder, + } + log.Info("Setting up event handlers") + wsnpInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: ctl.enqueueWSNP, + UpdateFunc: func(old, new interface{}) { + ctl.enqueueWSNP(new) + }, + }) + networkPolicyInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: ctl.handleNP, + UpdateFunc: func(old, new interface{}) { + newNP := new.(*k8snetwork.NetworkPolicy) + oldNP := old.(*k8snetwork.NetworkPolicy) + if newNP.ResourceVersion == oldNP.ResourceVersion { + return + } + ctl.handleNP(new) + }, + DeleteFunc: ctl.handleNP, + }) + workspaceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: ctl.handleWS, + UpdateFunc: func(old, new interface{}) { + newNP := new.(*workspaceapi.Workspace) + oldNP := old.(*workspaceapi.Workspace) + if newNP.ResourceVersion == oldNP.ResourceVersion { + return + } + ctl.handleWS(new) + }, + DeleteFunc: ctl.handleNP, + }) + return ctl +} + +func (c *controller) handleWS(obj interface{}) { + ws := obj.(*workspaceapi.Workspace) + wsnps, err := c.wsnpLister.List(labels.Everything()) + if err != nil { + log.Error(err, "Failed to get WSNP when a workspace changed ") + return + } + for _, wsnp := range wsnps { + log.V(4).Info("Enqueue wsnp because a workspace being changed", "obj", ws.Name) + c.enqueueWSNP(wsnp) + } + return +} + +func (c *controller) Run(threadiness int, stopCh <-chan struct{}) error { + defer utilruntime.HandleCrash() + defer c.workqueue.ShutDown() + + // Start the informer factories to begin populating the informer caches + log.Info("Starting WSNP controller") + + // Wait for the caches to be synced before starting workers + log.Info("Waiting for informer caches to sync") + if ok := cache.WaitForCacheSync(stopCh, c.wsnpSynced, c.namespaceSynced, c.networkPolicySynced, c.workspaceSynced); !ok { + return fmt.Errorf("failed to wait for caches to sync") + } + + log.Info("Starting workers") + // Launch two workers to process Foo resources + for i := 0; i < threadiness; i++ { + go wait.Until(c.runWorker, time.Second, stopCh) + } + + klog.Info("Started workers") + <-stopCh + log.Info("Shutting down workers") + + return nil +} + +func (c *controller) enqueueWSNP(obj interface{}) { + var key string + var err error + if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil { + utilruntime.HandleError(err) + return + } + c.workqueue.Add(key) +} + +func (c *controller) handleNP(obj interface{}) { + var object metav1.Object + var ok bool + if object, ok = obj.(metav1.Object); !ok { + tombstone, ok := obj.(cache.DeletedFinalStateUnknown) + if !ok { + utilruntime.HandleError(fmt.Errorf("error decoding object, invalid type")) + return + } + object, ok = tombstone.Obj.(metav1.Object) + if !ok { + utilruntime.HandleError(fmt.Errorf("error decoding object tombstone, invalid type")) + return + } + log.V(4).Info("Recovered deleted object from tombstone", "name", object.GetName()) + } + log.V(4).Info("Processing object:", "name", object.GetName()) + if ownerRef := metav1.GetControllerOf(object); ownerRef != nil { + if ownerRef.Kind != "WorkspaceNetworkPol" { + return + } + + wsnp, err := c.wsnpLister.Get(ownerRef.Name) + if err != nil { + log.V(4).Info("ignoring orphaned object", "link", object.GetSelfLink(), "name", ownerRef.Name) + return + } + c.enqueueWSNP(wsnp) + return + } +} + +func (c *controller) runWorker() { + for c.processNextWorkItem() { + } +} + +func (c *controller) processNextWorkItem() bool { + obj, shutdown := c.workqueue.Get() + + if shutdown { + return false + } + + // We wrap this block in a func so we can defer c.workqueue.Done. + err := func(obj interface{}) error { + // We call Done here so the workqueue knows we have finished + // processing this item. We also must remember to call Forget if we + // do not want this work item being re-queued. For example, we do + // not call Forget if a transient error occurs, instead the item is + // put back on the workqueue and attempted again after a back-off + // period. + defer c.workqueue.Done(obj) + var key string + var ok bool + // We expect strings to come off the workqueue. These are of the + // form namespace/name. We do this as the delayed nature of the + // workqueue means the items in the informer cache may actually be + // more up to date that when the item was initially put onto the + // workqueue. + if key, ok = obj.(string); !ok { + // As the item in the workqueue is actually invalid, we call + // Forget here else we'd go into a loop of attempting to + // process a work item that is invalid. + c.workqueue.Forget(obj) + utilruntime.HandleError(fmt.Errorf("expected string in workqueue but got %#v", obj)) + return nil + } + // Run the reconcile, passing it the namespace/name string of the + // Foo resource to be synced. + if err := c.reconcile(key); err != nil { + // Put the item back on the workqueue to handle any transient errors. + c.workqueue.AddRateLimited(key) + return fmt.Errorf("error syncing '%s': %s, requeuing", key, err.Error()) + } + // Finally, if no error occurs we Forget this item so it does not + // get queued again until another change happens. + c.workqueue.Forget(obj) + log.Info("Successfully synced", key) + return nil + }(obj) + + if err != nil { + utilruntime.HandleError(err) + return true + } + + return true +} + +func (c *controller) handleError(err error) { + log.Error(err, "Error in handling") + errCount++ +} diff --git a/pkg/controller/network/wsnetworkpolicy/reconcile.go b/pkg/controller/network/wsnetworkpolicy/reconcile.go new file mode 100644 index 000000000..f6bad5366 --- /dev/null +++ b/pkg/controller/network/wsnetworkpolicy/reconcile.go @@ -0,0 +1,203 @@ +package wsnetworkpolicy + +import ( + "fmt" + "reflect" + "sort" + + corev1 "k8s.io/api/core/v1" + ks8network "k8s.io/api/networking/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + errutil "k8s.io/apimachinery/pkg/util/errors" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/retry" + wsnpapi "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" +) + +const ( + workspaceSelectorLabel = "kubesphere.io/workspace" + workspaceNetworkPolicyLabel = "networking.kubesphere.io/wsnp" + + MessageResourceExists = "Resource %q already exists and is not managed by WorkspaceNetworkPolicy" + ErrResourceExists = "ErrResourceExists" +) + +var everything = labels.Everything() +var reconcileCount = 0 + +// NetworkPolicyNameForWSNP return the name of the networkpolicy owned by this WNSP +func NetworkPolicyNameForWSNP(wsnp string) string { + return wsnp + "-np" +} + +func (c *controller) reconcile(key string) error { + reconcileCount++ + _, name, err := cache.SplitMetaNamespaceKey(key) + if err != nil { + utilruntime.HandleError(fmt.Errorf("invalid resource key: %s", key)) + return nil + } + olog := log.WithName(name) + olog.Info("Begin to reconcile") + owner, err := c.wsnpLister.Get(name) + if err != nil { + if errors.IsNotFound(err) { + utilruntime.HandleError(fmt.Errorf("WSNP '%s' in work queue no longer exists", key)) + return nil + } + return err + } + namespaces, err := c.listNamespacesInWorkspace(owner.Spec.Workspace) + if err != nil { + return err + } + var errs []error + for _, ns := range namespaces { + err = c.reconcileNamespace(ns.Name, owner) + if err != nil { + errs = append(errs, err) + } + } + if len(errs) == 0 { + return nil + } + return errutil.NewAggregate(errs) +} + +func (c *controller) reconcileNamespace(name string, wsnp *wsnpapi.WorkspaceNetworkPolicy) error { + npname := NetworkPolicyNameForWSNP(wsnp.Name) + np, err := c.generateNPForNamesapce(name, wsnp) + if err != nil { + log.Error(nil, "Failed to generate NetworkPolicy", "wsnp", wsnp, "namespace", name) + return err + } + old, err := c.networkPolicyLister.NetworkPolicies(name).Get(npname) + if errors.IsNotFound(err) { + _, err = c.kubeClientset.NetworkingV1().NetworkPolicies(name).Create(np) + if err != nil { + log.Error(err, "cannot create networkpolicy of this wsnp", wsnp) + return err + } + return nil + } + if err != nil { + log.Error(err, "Failed to get networkPolicy") + return err + } + if !metav1.IsControlledBy(old, wsnp) { + msg := fmt.Sprintf(MessageResourceExists, old.Name) + c.recorder.Event(wsnp, corev1.EventTypeWarning, ErrResourceExists, msg) + return fmt.Errorf(msg) + } + if !reflect.DeepEqual(old.Spec, np.Spec) { + log.V(2).Info("Detect network policy changed, updating network policy", "the old one", old.Spec, "the new one", np.Spec) + err = retry.RetryOnConflict(retry.DefaultBackoff, func() error { + _, err = c.kubeClientset.NetworkingV1().NetworkPolicies(name).Update(np) + return err + }) + if err != nil { + log.Error(err, "Failed to update wsnp") + return err + } + log.V(2).Info("updating completed") + } + return nil +} + +func (c *controller) generateNPForNamesapce(ns string, wsnp *wsnpapi.WorkspaceNetworkPolicy) (*ks8network.NetworkPolicy, error) { + np := &ks8network.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: NetworkPolicyNameForWSNP(wsnp.Name), + Namespace: ns, + Labels: map[string]string{workspaceNetworkPolicyLabel: wsnp.Name}, + OwnerReferences: []metav1.OwnerReference{ + *metav1.NewControllerRef(wsnp, wsnpapi.SchemeGroupVersion.WithKind("WorkspaceNetworkPolicy")), + }, + }, + Spec: ks8network.NetworkPolicySpec{ + PolicyTypes: wsnp.Spec.PolicyTypes, + }, + } + + if wsnp.Spec.Ingress != nil { + np.Spec.Ingress = make([]ks8network.NetworkPolicyIngressRule, len(wsnp.Spec.Ingress)) + for index, ing := range wsnp.Spec.Ingress { + ingRule, err := c.transformWSNPIngressToK8sIngress(ing) + if err != nil { + return nil, err + } + np.Spec.Ingress[index] = *ingRule + } + } + return np, nil +} + +func (c *controller) transformWSNPIngressToK8sIngress(rule wsnpapi.WorkspaceNetworkPolicyIngressRule) (*ks8network.NetworkPolicyIngressRule, error) { + k8srule := &ks8network.NetworkPolicyIngressRule{ + Ports: rule.Ports, + From: make([]ks8network.NetworkPolicyPeer, len(rule.From)), + } + for index, f := range rule.From { + k8srule.From[index] = f.NetworkPolicyPeer + if f.WorkspaceSelector != nil { + if f.WorkspaceSelector.Size() == 0 { + k8srule.From[index].NamespaceSelector = &metav1.LabelSelector{} + } else { + selector, err := metav1.LabelSelectorAsSelector(f.WorkspaceSelector) + if err != nil { + log.Error(err, "Failed to convert label selectors") + return nil, err + } + ws, err := c.workspaceLister.List(selector) + if err != nil { + log.Error(err, "Failed to list workspaces") + return nil, err + } + if len(ws) == 0 { + log.Info("ws selector doesnot match anything") + continue + } + if k8srule.From[index].NamespaceSelector == nil { + k8srule.From[index].NamespaceSelector = &metav1.LabelSelector{} + } + if len(ws) == 1 { + if k8srule.From[index].NamespaceSelector.MatchLabels == nil { + k8srule.From[index].NamespaceSelector.MatchLabels = make(map[string]string) + } + k8srule.From[index].NamespaceSelector.MatchLabels[workspaceSelectorLabel] = ws[0].Name + } else { + if k8srule.From[index].NamespaceSelector.MatchExpressions == nil { + k8srule.From[index].NamespaceSelector.MatchExpressions = make([]metav1.LabelSelectorRequirement, 0) + } + re := metav1.LabelSelectorRequirement{ + Key: workspaceSelectorLabel, + Operator: metav1.LabelSelectorOpIn, + Values: make([]string, len(ws)), + } + for index, w := range ws { + re.Values[index] = w.Name + } + sort.Strings(re.Values) + k8srule.From[index].NamespaceSelector.MatchExpressions = append(k8srule.From[index].NamespaceSelector.MatchExpressions, re) + } + } + } + } + return k8srule, nil +} +func (c *controller) listNamespacesInWorkspace(workspace string) ([]*corev1.Namespace, error) { + selector, err := labels.Parse(workspaceSelectorLabel + "==" + workspace) + if err != nil { + log.Error(err, "Failed to parse label selector") + return nil, err + } + namespaces, err := c.namespaceLister.List(selector) + if err != nil { + log.Error(err, "Failed to list namespaces in this workspace") + return nil, err + } + return namespaces, nil +} diff --git a/pkg/controller/network/wsnetworkpolicy/wsnetworkpolicy_suite_test.go b/pkg/controller/network/wsnetworkpolicy/wsnetworkpolicy_suite_test.go new file mode 100644 index 000000000..c6c007075 --- /dev/null +++ b/pkg/controller/network/wsnetworkpolicy/wsnetworkpolicy_suite_test.go @@ -0,0 +1,21 @@ +package wsnetworkpolicy + +import ( + "flag" + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "k8s.io/klog" +) + +func TestWsnetworkpolicy(t *testing.T) { + klog.InitFlags(nil) + flag.Set("logtostderr", "false") + flag.Set("alsologtostderr", "false") + flag.Set("v", "4") + flag.Parse() + klog.SetOutput(GinkgoWriter) + RegisterFailHandler(Fail) + RunSpecs(t, "Wsnetworkpolicy Suite") +} diff --git a/pkg/controller/network/wsnetworkpolicy/wsnetworkpolicy_test.go b/pkg/controller/network/wsnetworkpolicy/wsnetworkpolicy_test.go new file mode 100644 index 000000000..fc493dc2b --- /dev/null +++ b/pkg/controller/network/wsnetworkpolicy/wsnetworkpolicy_test.go @@ -0,0 +1,241 @@ +package wsnetworkpolicy + +import ( + "fmt" + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gstruct" + corev1 "k8s.io/api/core/v1" + k8snetwork "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + netv1lister "k8s.io/client-go/listers/networking/v1" + "k8s.io/client-go/tools/record" + "k8s.io/klog" + "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" + tenant "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1" + controllertesting "kubesphere.io/kubesphere/pkg/controller/network/testing" +) + +var ( + fakeControllerBuilder *controllertesting.FakeControllerBuilder + c Controller + npLister netv1lister.NetworkPolicyLister + stopCh chan struct{} + deletePolicy metav1.DeletionPropagation + testName string +) + +var _ = Describe("Wsnetworkpolicy", func() { + BeforeEach(func() { + deletePolicy = metav1.DeletePropagationBackground + fakeControllerBuilder = controllertesting.NewFakeControllerBuilder() + informer, k8sinformer := fakeControllerBuilder.NewControllerInformer() + stopCh = make(chan struct{}) + c = NewController(fakeControllerBuilder.KubeClient, fakeControllerBuilder.KsClient, + informer.Network().V1alpha1().WorkspaceNetworkPolicies(), k8sinformer.Networking().V1().NetworkPolicies(), + k8sinformer.Core().V1().Namespaces(), informer.Tenant().V1alpha1().Workspaces()) + originalController := c.(*controller) + go originalController.wsnpInformer.Informer().Run(stopCh) + go originalController.networkPolicyInformer.Informer().Run(stopCh) + go originalController.namespaceInformer.Informer().Run(stopCh) + go originalController.workspaceInformer.Informer().Run(stopCh) + originalController.recorder = &record.FakeRecorder{} + go c.Run(1, stopCh) + npLister = k8sinformer.Networking().V1().NetworkPolicies().Lister() + testName = "test" + ns1 := newWorkspaceNamespaces("ns1", testName) + ns2 := newWorkspaceNamespaces("ns2", testName) + _, err := fakeControllerBuilder.KubeClient.CoreV1().Namespaces().Create(ns1) + Expect(err).ShouldNot(HaveOccurred()) + _, err = fakeControllerBuilder.KubeClient.CoreV1().Namespaces().Create(ns2) + Expect(err).ShouldNot(HaveOccurred()) + }) + + AfterEach(func() { + close(stopCh) + }) + + It("Should proper ingress rule when using workspaceSelector", func() { + label := map[string]string{"workspace": "test-selector"} + ws := &tenant.Workspace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Labels: label, + }, + } + _, err := fakeControllerBuilder.KsClient.TenantV1alpha1().Workspaces().Create(ws) + wsnp := newWorkspaceNP(testName) + wsnp.Spec.PolicyTypes = []k8snetwork.PolicyType{k8snetwork.PolicyTypeIngress} + wsnp.Spec.Ingress = []v1alpha1.WorkspaceNetworkPolicyIngressRule{ + v1alpha1.WorkspaceNetworkPolicyIngressRule{ + From: []v1alpha1.WorkspaceNetworkPolicyPeer{ + v1alpha1.WorkspaceNetworkPolicyPeer{ + WorkspaceSelector: &metav1.LabelSelector{ + MatchLabels: label, + }, + }, + }, + }} + _, err = fakeControllerBuilder.KsClient.NetworkV1alpha1().WorkspaceNetworkPolicies().Create(wsnp) + Expect(err).ShouldNot(HaveOccurred()) + expect1Json := `{ + "apiVersion": "networking.k8s.io/v1", + "kind": "NetworkPolicy", + "metadata": { + "name": "test-np", + "namespace": "ns1", + "labels": { + "networking.kubesphere.io/wsnp": "test" + } + }, + "spec": { + "policyTypes": [ + "Ingress" + ], + "ingress": [ + { + "from": [ + { + "namespaceSelector": { + "matchLabels": { + "kubesphere.io/workspace": "test" + } + } + } + ] + } + ] + } + }` + expect1 := &k8snetwork.NetworkPolicy{} + Expect(controllertesting.StringToObject(expect1Json, expect1)).ShouldNot(HaveOccurred()) + nps := []*k8snetwork.NetworkPolicy{} + Eventually(func() error { + selector, _ := labels.Parse(workspaceNetworkPolicyLabel + "==test") + nps, err = npLister.List(selector) + if err != nil { + klog.Errorf("Failed to list npmerr:%s", err.Error()) + return err + } + if len(nps) != 2 { + return fmt.Errorf("Length is not right, current length :%d", len(nps)) + } + return nil + }, time.Second*5, time.Second).ShouldNot(HaveOccurred()) + + for _, np := range nps { + Expect(np.Labels).To(Equal(expect1.Labels)) + Expect(np.Spec).To(Equal(expect1.Spec)) + } + // create a new ws will change the `From` + ws2 := &tenant.Workspace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test2", + Labels: label, + }, + } + _, err = fakeControllerBuilder.KsClient.TenantV1alpha1().Workspaces().Create(ws2) + Expect(err).ShouldNot(HaveOccurred()) + expect2Json := `{ + "apiVersion": "networking.k8s.io/v1", + "kind": "NetworkPolicy", + "metadata": { + "name": "test-np", + "namespace": "ns1", + "labels": { + "networking.kubesphere.io/wsnp": "test" + } + }, + "spec": { + "policyTypes": [ + "Ingress" + ], + "ingress": [ + { + "from": [ + { + "namespaceSelector": { + "matchExpressions": [{ + "key": "kubesphere.io/workspace", + "operator":"In", + "values": ["test", "test2"] + }] + } + } + ] + } + ] + } + }` + expect2 := &k8snetwork.NetworkPolicy{} + Expect(controllertesting.StringToObject(expect2Json, expect2)).ShouldNot(HaveOccurred()) + + id := func(element interface{}) string { + e := element.(*k8snetwork.NetworkPolicy) + return e.Namespace + } + Eventually(func() []*k8snetwork.NetworkPolicy { + selector, _ := labels.Parse(workspaceNetworkPolicyLabel + "=test") + nps, err := npLister.List(selector) + if err != nil { + return nil + } + if len(nps) != 2 { + klog.Errorf("Length is not right, current length :%d", len(nps)) + return nil + } + return nps + }, time.Second*5, time.Second).Should(MatchAllElements(id, Elements{ + "ns1": PointTo(MatchFields(IgnoreExtras, Fields{ + "Spec": Equal(expect2.Spec), + })), + "ns2": PointTo(MatchFields(IgnoreExtras, Fields{ + "Spec": Equal(expect2.Spec), + })), + })) + }) + + It("Should create networkpolicies", func() { + //create a wsnp + _, err := fakeControllerBuilder.KsClient.NetworkV1alpha1().WorkspaceNetworkPolicies().Create(newWorkspaceNP(testName)) + Expect(err).ShouldNot(HaveOccurred()) + Eventually(func() error { + selector, _ := labels.Parse(workspaceNetworkPolicyLabel + "=" + testName) + nps, err := npLister.List(selector) + if err != nil { + return err + } + if len(nps) != 2 { + return fmt.Errorf("Length is not right, current length :%d", len(nps)) + } + return nil + }, time.Second*5, time.Second).ShouldNot(HaveOccurred()) + err = fakeControllerBuilder.KsClient.NetworkV1alpha1().WorkspaceNetworkPolicies().Delete(testName, &metav1.DeleteOptions{ + PropagationPolicy: &deletePolicy, + }) + Expect(err).ShouldNot(HaveOccurred()) + }) +}) + +func newWorkspaceNP(name string) *v1alpha1.WorkspaceNetworkPolicy { + return &v1alpha1.WorkspaceNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Spec: v1alpha1.WorkspaceNetworkPolicySpec{ + Workspace: name, + }, + } +} + +func newWorkspaceNamespaces(ns, ws string) *corev1.Namespace { + return &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: ns, + Labels: map[string]string{workspaceSelectorLabel: ws}, + }, + } +}