From 1374b1ceb407995c599a7742a8f4d1761217478e Mon Sep 17 00:00:00 2001 From: Ray Zhou Date: Tue, 30 Jul 2019 10:07:06 +0800 Subject: [PATCH 1/2] Update README --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index da338e682..c54e4d5eb 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,9 @@ ## What is KubeSphere -[KubeSphere](https://kubesphere.io/) is an enterprise-grade multi-tenant container management platform that built on [Kubernetes](https://kubernetes.io). It provides an easy-to-use UI for users to create computing resources with a few clicks, which reduces the learning curve and empowers the DevOps teams. It greatly reduces the complexity of the daily work of development, testing, operation and maintenance, aiming to alleviate the pain points of Kubernetes' storage, network, security and ease of use, etc. +[KubeSphere](https://kubesphere.io/) is an enterprise-grade multi-tenant container management platform that built on [Kubernetes](https://kubernetes.io). It provides an easy-to-use UI for users to manage computing resources with a few clicks, which reduces the learning curve and empowers the DevOps teams. It greatly reduces the complexity of the daily work of development, testing, operation and maintenance, aiming to alleviate the pain points of Kubernetes' storage, network, security and ease of use, etc. + +KubeSphere can run anywhere from on-premise datacenter to any cloud to edge. In addition, it can be deployed on any Kubernetes distribution. > See this [document](https://docs.kubesphere.io/advanced-v2.0/zh-CN/introduction/intro/) that describes the KubeSphere landscape and details. @@ -71,7 +73,7 @@ Choose `"1) All-in-one"` to trigger the installation. Generally, you can install ### Multi-Node -[Multi-Node](https://docs.kubesphere.io/advanced-v2.0/zh-CN/installation/multi-node/) is used for installing KubeSphere on multiple instances, supports for installing a highly available cluster in a formal environment. Multi-node installation requires pre-configuration steps, see [Multi-Node Guide](https://docs.kubesphere.io/advanced-v2.0/zh-CN/installation/multi-node/). +[Multi-Node](https://docs.kubesphere.io/advanced-v2.0/zh-CN/installation/multi-node/) is used for installing KubeSphere on multiple instances, supports for installing a highly available cluster in a mission-critical environment. Multi-node installation requires pre-configuration steps, see [Multi-Node Guide](https://docs.kubesphere.io/advanced-v2.0/zh-CN/installation/multi-node/). ## To start using KubeSphere From 75d787f15f015b81cf9f6be1567aa513737d64ab Mon Sep 17 00:00:00 2001 From: magicsong Date: Tue, 23 Jul 2019 11:26:41 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=8C=9F=20add=20support=20of=20workspa?= =?UTF-8?q?ce=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}, + }, + } +}