Merge pull request #2012 from duanjiong/network-policy

Network policy
This commit is contained in:
KubeSphere CI Bot
2020-04-29 10:44:27 +08:00
committed by GitHub
381 changed files with 4100 additions and 68577 deletions

View File

@@ -1,170 +0,0 @@
package v1alpha1
import (
corev1 "k8s.io/api/core/v1"
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1/numorstring"
)
// A Rule encapsulates a set of match criteria and an action. Both selector-based security Policy
// and security Profiles reference rules - separated out as a list of rules for both
// ingress and egress packet matching.
//
// Each positive match criteria has a negated version, prefixed with ”Not”. All the match
// criteria within a rule must be satisfied for a packet to match. A single rule can contain
// the positive and negative version of a match and both must be satisfied for the rule to match.
type Rule struct {
Action Action `json:"action" validate:"action"`
// IPVersion is an optional field that restricts the rule to only match a specific IP
// version.
IPVersion *int `json:"ipVersion,omitempty" validate:"omitempty,ipVersion"`
// Protocol is an optional field that restricts the rule to only apply to traffic of
// a specific IP protocol. Required if any of the EntityRules contain Ports
// (because ports only apply to certain protocols).
//
// Must be one of these string values: "TCP", "UDP", "ICMP", "ICMPv6", "SCTP", "UDPLite"
// or an integer in the range 1-255.
Protocol *corev1.Protocol `json:"protocol,omitempty" validate:"omitempty"`
// ICMP is an optional field that restricts the rule to apply to a specific type and
// code of ICMP traffic. This should only be specified if the Protocol field is set to
// "ICMP" or "ICMPv6".
ICMP *ICMPFields `json:"icmp,omitempty" validate:"omitempty"`
// NotProtocol is the negated version of the Protocol field.
NotProtocol *corev1.Protocol `json:"notProtocol,omitempty" validate:"omitempty"`
// NotICMP is the negated version of the ICMP field.
NotICMP *ICMPFields `json:"notICMP,omitempty" validate:"omitempty"`
// Source contains the match criteria that apply to source entity.
Source EntityRule `json:"source,omitempty" validate:"omitempty"`
// Destination contains the match criteria that apply to destination entity.
Destination EntityRule `json:"destination,omitempty" validate:"omitempty"`
// HTTP contains match criteria that apply to HTTP requests.
HTTP *HTTPMatch `json:"http,omitempty" validate:"omitempty"`
}
// HTTPPath specifies an HTTP path to match. It may be either of the form:
// exact: <path>: which matches the path exactly or
// prefix: <path-prefix>: which matches the path prefix
type HTTPPath struct {
Exact string `json:"exact,omitempty" validate:"omitempty"`
Prefix string `json:"prefix,omitempty" validate:"omitempty"`
}
// HTTPMatch is an optional field that apply only to HTTP requests
// The Methods and Path fields are joined with AND
type HTTPMatch struct {
// Methods is an optional field that restricts the rule to apply only to HTTP requests that use one of the listed
// HTTP Methods (e.g. GET, PUT, etc.)
// Multiple methods are OR'd together.
Methods []string `json:"methods,omitempty" validate:"omitempty"`
// Paths is an optional field that restricts the rule to apply to HTTP requests that use one of the listed
// HTTP Paths.
// Multiple paths are OR'd together.
// e.g:
// - exact: /foo
// - prefix: /bar
// NOTE: Each entry may ONLY specify either a `exact` or a `prefix` match. The validator will check for it.
Paths []HTTPPath `json:"paths,omitempty" validate:"omitempty"`
}
// ICMPFields defines structure for ICMP and NotICMP sub-struct for ICMP code and type
type ICMPFields struct {
// Match on a specific ICMP type. For example a value of 8 refers to ICMP Echo Request
// (i.e. pings).
Type *int `json:"type,omitempty" validate:"omitempty,gte=0,lte=254"`
// Match on a specific ICMP code. If specified, the Type value must also be specified.
// This is a technical limitation imposed by the kernels iptables firewall, which
// Calico uses to enforce the rule.
Code *int `json:"code,omitempty" validate:"omitempty,gte=0,lte=255"`
}
// An EntityRule is a sub-component of a Rule comprising the match criteria specific
// to a particular entity (that is either the source or destination).
//
// A source EntityRule matches the source endpoint and originating traffic.
// A destination EntityRule matches the destination endpoint and terminating traffic.
type EntityRule struct {
// Nets is an optional field that restricts the rule to only apply to traffic that
// originates from (or terminates at) IP addresses in any of the given subnets.
Nets []string `json:"nets,omitempty" validate:"omitempty,dive,net"`
// Selector is an optional field that contains a selector expression (see Policy for
// sample syntax). Only traffic that originates from (terminates at) endpoints matching
// the selector will be matched.
//
// Note that: in addition to the negated version of the Selector (see NotSelector below), the
// selector expression syntax itself supports negation. The two types of negation are subtly
// different. One negates the set of matched endpoints, the other negates the whole match:
//
// Selector = "!has(my_label)" matches packets that are from other Calico-controlled
// endpoints that do not have the label “my_label”.
//
// NotSelector = "has(my_label)" matches packets that are not from Calico-controlled
// endpoints that do have the label “my_label”.
//
// The effect is that the latter will accept packets from non-Calico sources whereas the
// former is limited to packets from Calico-controlled endpoints.
Selector string `json:"selector,omitempty" validate:"omitempty,selector"`
// NamespaceSelector is an optional field that contains a selector expression. Only traffic
// that originates from (or terminates at) endpoints within the selected namespaces will be
// matched. When both NamespaceSelector and Selector are defined on the same rule, then only
// workload endpoints that are matched by both selectors will be selected by the rule.
//
// For NetworkPolicy, an empty NamespaceSelector implies that the Selector is limited to selecting
// only workload endpoints in the same namespace as the NetworkPolicy.
//
// For GlobalNetworkPolicy, an empty NamespaceSelector implies the Selector applies to workload
// endpoints across all namespaces.
NamespaceSelector string `json:"namespaceSelector,omitempty" validate:"omitempty,selector"`
// Ports is an optional field that restricts the rule to only apply to traffic that has a
// source (destination) port that matches one of these ranges/values. This value is a
// list of integers or strings that represent ranges of ports.
//
// Since only some protocols have ports, if any ports are specified it requires the
// Protocol match in the Rule to be set to "TCP" or "UDP".
Ports []numorstring.Port `json:"ports,omitempty" validate:"omitempty,dive"`
// NotNets is the negated version of the Nets field.
NotNets []string `json:"notNets,omitempty" validate:"omitempty,dive,net"`
// NotSelector is the negated version of the Selector field. See Selector field for
// subtleties with negated selectors.
NotSelector string `json:"notSelector,omitempty" validate:"omitempty,selector"`
// NotPorts is the negated version of the Ports field.
// Since only some protocols have ports, if any ports are specified it requires the
// Protocol match in the Rule to be set to "TCP" or "UDP".
NotPorts []numorstring.Port `json:"notPorts,omitempty" validate:"omitempty,dive"`
// ServiceAccounts is an optional field that restricts the rule to only apply to traffic that originates from (or
// terminates at) a pod running as a matching service account.
ServiceAccounts *ServiceAccountMatch `json:"serviceAccounts,omitempty" validate:"omitempty"`
}
type ServiceAccountMatch struct {
// Names is an optional field that restricts the rule to only apply to traffic that originates from (or terminates
// at) a pod running as a service account whose name is in the list.
Names []string `json:"names,omitempty" validate:"omitempty"`
// Selector is an optional field that restricts the rule to only apply to traffic that originates from
// (or terminates at) a pod running as a service account that matches the given label selector.
// If both Names and Selector are specified then they are AND'ed.
Selector string `json:"selector,omitempty" validate:"omitempty,selector"`
}
type Action string
const (
Allow Action = "Allow"
Deny = "Deny"
Log = "Log"
Pass = "Pass"
)
type PolicyType string
const (
PolicyTypeIngress PolicyType = "Ingress"
PolicyTypeEgress PolicyType = "Egress"
)

View File

@@ -17,68 +17,114 @@ limitations under the License.
package v1alpha1
import (
k8snet "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// All types in this file is copy from calicoapi as we use calico to policy
const (
ResourceKindNamespaceNetworkPolicy = "NamespaceNetworkPolicy"
ResourceSingularNamespaceNetworkPolicy = "namespacenetworkpolicy"
ResourcePluralNamespaceNetworkPolicy = "namespacenetworkpolicies"
)
// NamespaceNetworkPolicySpec defines the desired state of NamespaceNetworkPolicy
// NamespaceNetworkPolicySpec provides the specification of a NamespaceNetworkPolicy
type NamespaceNetworkPolicySpec struct {
// Order is an optional field that specifies the order in which the policy is applied.
// Policies with higher "order" are applied after those with lower
// order. If the order is omitted, it may be considered to be "infinite" - i.e. the
// policy will be applied last. Policies with identical order will be applied in
// alphanumerical order based on the Policy "Name".
Order *int `json:"order,omitempty"`
// The ordered set of ingress rules. Each rule contains a set of packet match criteria and
// a corresponding action to apply.
Ingress []Rule `json:"ingress,omitempty" validate:"omitempty,dive"`
// The ordered set of egress rules. Each rule contains a set of packet match criteria and
// a corresponding action to apply.
Egress []Rule `json:"egress,omitempty" validate:"omitempty,dive"`
// The selector is an expression used to pick pick out the endpoints that the policy should
// be applied to.
//
// Selector expressions follow this syntax:
//
// label == "string_literal" -> comparison, e.g. my_label == "foo bar"
// label != "string_literal" -> not equal; also matches if label is not present
// label in { "a", "b", "c", ... } -> true if the value of label X is one of "a", "b", "c"
// label not in { "a", "b", "c", ... } -> true if the value of label X is not one of "a", "b", "c"
// has(label_name) -> True if that label is present
// ! expr -> negation of expr
// expr && expr -> Short-circuit and
// expr || expr -> Short-circuit or
// ( expr ) -> parens for grouping
// all() or the empty selector -> matches all endpoints.
//
// Label names are allowed to contain alphanumerics, -, _ and /. String literals are more permissive
// but they do not support escape characters.
//
// Examples (with made-up labels):
//
// type == "webserver" && deployment == "prod"
// type in {"frontend", "backend"}
// deployment != "dev"
// ! has(label_name)
Selector string `json:"selector" validate:"selector"`
// Types indicates whether this policy applies to ingress, or to egress, or to both. When
// not explicitly specified (and so the value on creation is empty or nil), Calico defaults
// Types according to what Ingress and Egress are present in the policy. The
// default is:
//
// - [ PolicyTypeIngress ], if there are no Egress rules (including the case where there are
// also no Ingress rules)
//
// - [ PolicyTypeEgress ], if there are Egress rules but no Ingress rules
//
// - [ PolicyTypeIngress, PolicyTypeEgress ], if there are both Ingress and Egress rules.
//
// When the policy is read back again, Types will always be one of these values, never empty
// or nil.
Types []PolicyType `json:"types,omitempty" validate:"omitempty,dive,policyType"`
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
// 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 []NetworkPolicyIngressRule `json:"ingress,omitempty" protobuf:"bytes,1,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 []NetworkPolicyEgressRule `json:"egress,omitempty" protobuf:"bytes,2,rep,name=egress"`
// List of rule types that the NetworkPolicy 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" ]).
// This field is beta-level in 1.8
// +optional
PolicyTypes []k8snet.PolicyType `json:"policyTypes,omitempty" protobuf:"bytes,3,rep,name=policyTypes,casttype=PolicyType"`
}
// NetworkPolicyIngressRule describes a particular set of traffic that is allowed to the pods
// matched by a NetworkPolicySpec's podSelector. The traffic must match both ports and from.
type NetworkPolicyIngressRule 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 []k8snet.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 one item, this rule
// allows traffic only if the traffic matches at least one item in the from list.
// +optional
From []NetworkPolicyPeer `json:"from,omitempty" protobuf:"bytes,2,rep,name=from"`
}
// NetworkPolicyEgressRule describes a particular set of traffic that is allowed out of pods
// matched by a NetworkPolicySpec's podSelector. The traffic must match both ports and to.
// This type is beta-level in 1.8
type NetworkPolicyEgressRule struct {
// List of destination ports for outgoing traffic.
// 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 []k8snet.NetworkPolicyPort `json:"ports,omitempty" protobuf:"bytes,1,rep,name=ports"`
// List of destinations for outgoing traffic of 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 destinations (traffic not restricted by
// destination). If this field is present and contains at least one item, this rule
// allows traffic only if the traffic matches at least one item in the to list.
// +optional
To []NetworkPolicyPeer `json:"to,omitempty" protobuf:"bytes,2,rep,name=to"`
}
type NamespaceSelector struct {
Name string `json:"name" protobuf:"bytes,1,name=name"`
}
type ServiceSelector struct {
Name string `json:"name" protobuf:"bytes,1,name=name"`
Namespace string `json:"namespace" protobuf:"bytes,2,name=namespace"`
}
// NetworkPolicyPeer describes a peer to allow traffic from. Only certain combinations of
// fields are allowed
type NetworkPolicyPeer struct {
// +optional
NamespaceSelector *NamespaceSelector `json:"namespace,omitempty" protobuf:"bytes,1,opt,name=namespace"`
// IPBlock defines policy on a particular IPBlock. If this field is set then
// neither of the other fields can be.
// +optional
IPBlock *k8snet.IPBlock `json:"ipBlock,omitempty" protobuf:"bytes,2,rep,name=ipBlock"`
ServiceSelector *ServiceSelector `json:"service,omitempty" protobuf:"bytes,3,opt,name=service"`
}
// +genclient

View File

@@ -1,73 +0,0 @@
// Copyright (c) 2016 Tigera, Inc. All rights reserved.
// 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 numorstring
import (
"encoding/json"
"errors"
"fmt"
"strconv"
"strings"
)
type ASNumber uint32
// ASNumberFromString creates an ASNumber struct from a string value. The
// string value may simply be a number or may be the ASN in dotted notation.
func ASNumberFromString(s string) (ASNumber, error) {
if num, err := strconv.ParseUint(s, 10, 32); err == nil {
return ASNumber(num), nil
}
parts := strings.Split(s, ".")
if len(parts) != 2 {
msg := fmt.Sprintf("invalid AS Number format (%s)", s)
return 0, errors.New(msg)
}
if num1, err := strconv.ParseUint(parts[0], 10, 16); err != nil {
msg := fmt.Sprintf("invalid AS Number format (%s)", s)
return 0, errors.New(msg)
} else if num2, err := strconv.ParseUint(parts[1], 10, 16); err != nil {
msg := fmt.Sprintf("invalid AS Number format (%s)", s)
return 0, errors.New(msg)
} else {
return ASNumber((num1 << 16) + num2), nil
}
}
// UnmarshalJSON implements the json.Unmarshaller uinterface.
func (a *ASNumber) UnmarshalJSON(b []byte) error {
if err := json.Unmarshal(b, (*uint32)(a)); err == nil {
return nil
} else {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
if v, err := ASNumberFromString(s); err != nil {
return err
} else {
*a = v
return nil
}
}
}
// String returns the string value, or the Itoa of the uint value.
func (a ASNumber) String() string {
return strconv.FormatUint(uint64(a), 10)
}

View File

@@ -1,19 +0,0 @@
// Copyright (c) 2016 Tigera, Inc. All rights reserved.
// 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 numorstring implements a set of type definitions that in YAML or JSON
format may be represented by either a number or a string.
*/
package numorstring

View File

@@ -1,26 +0,0 @@
// Copyright (c) 2016,2018 Tigera, Inc. All rights reserved.
// 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 numorstring_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestNumorstring(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Numorstring Suite")
}

View File

@@ -1,204 +0,0 @@
// Copyright (c) 2016-2017 Tigera, Inc. All rights reserved.
// 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 numorstring_test
import (
"encoding/json"
"fmt"
"reflect"
. "github.com/onsi/ginkgo/extensions/table"
. "github.com/onsi/gomega"
"github.com/projectcalico/libcalico-go/lib/numorstring"
)
func init() {
asNumberType := reflect.TypeOf(numorstring.ASNumber(0))
protocolType := reflect.TypeOf(numorstring.Protocol{})
portType := reflect.TypeOf(numorstring.Port{})
// Perform tests of JSON unmarshaling of the various field types.
DescribeTable("NumOrStringJSONUnmarshaling",
func(jtext string, typ reflect.Type, expected interface{}) {
// Create a new field type and invoke the unmarshaller interface
// directly (this covers a couple more error cases than calling
// through json.Unmarshal.
new := reflect.New(typ)
u := new.Interface().(json.Unmarshaler)
err := u.UnmarshalJSON([]byte(jtext))
if expected != nil {
Expect(err).To(BeNil(),
"expected json unmarshal to not error")
Expect(new.Elem().Interface()).To(Equal(expected),
"expected value not same as json unmarshalled value")
} else {
Expect(err).ToNot(BeNil(),
"expected json unmarshal to error")
}
},
// ASNumber tests.
Entry("should accept 0 AS number as int", "0", asNumberType, numorstring.ASNumber(0)),
Entry("should accept 4294967295 AS number as int", "4294967295", asNumberType, numorstring.ASNumber(4294967295)),
Entry("should accept 0 AS number as string", "\"0\"", asNumberType, numorstring.ASNumber(0)),
Entry("should accept 4294967295 AS number as string", "\"4294967295\"", asNumberType, numorstring.ASNumber(4294967295)),
Entry("should accept 1.10 AS number as string", "\"1.10\"", asNumberType, numorstring.ASNumber(65546)),
Entry("should accept 00.00 AS number as string", "\"00.00\"", asNumberType, numorstring.ASNumber(0)),
Entry("should accept 00.01 AS number as string", "\"00.01\"", asNumberType, numorstring.ASNumber(1)),
Entry("should accept 65535.65535 AS number as string", "\"65535.65535\"", asNumberType, numorstring.ASNumber(4294967295)),
Entry("should reject 1.1.1 AS number as string", "\"1.1.1\"", asNumberType, nil),
Entry("should reject 65536.65535 AS number as string", "\"65536.65535\"", asNumberType, nil),
Entry("should reject 65535.65536 AS number as string", "\"65535.65536\"", asNumberType, nil),
Entry("should reject 0.-1 AS number as string", "\"0.-1\"", asNumberType, nil),
Entry("should reject -1 AS number as int", "-1", asNumberType, nil),
Entry("should reject 4294967296 AS number as int", "4294967296", asNumberType, nil),
// Port tests.
Entry("should accept 0 port as int", "0", portType, numorstring.SinglePort(0)),
Entry("should accept 65535 port as int", "65535", portType, numorstring.SinglePort(65535)),
Entry("should accept 0:65535 port range as string", "\"0:65535\"", portType, portFromRange(0, 65535)),
Entry("should accept 1:10 port range as string", "\"1:10\"", portType, portFromRange(1, 10)),
Entry("should accept foo-bar as named port", "\"foo-bar\"", portType, numorstring.NamedPort("foo-bar")),
Entry("should reject -1 port as int", "-1", portType, nil),
Entry("should reject 65536 port as int", "65536", portType, nil),
Entry("should reject 0:65536 port range as string", "\"0:65536\"", portType, nil),
Entry("should reject -1:65535 port range as string", "\"-1:65535\"", portType, nil),
Entry("should reject 10:1 port range as string", "\"10:1\"", portType, nil),
Entry("should reject 1:2:3 port range as string", "\"1:2:3\"", portType, nil),
Entry("should reject bad named port string", "\"*\"", portType, nil),
Entry("should reject bad port string", "\"1:2", portType, nil),
// Protocol tests. Invalid integer values will be stored as strings.
Entry("should accept 0 protocol as int", "0", protocolType, numorstring.ProtocolFromInt(0)),
Entry("should accept 255 protocol as int", "255", protocolType, numorstring.ProtocolFromInt(255)),
Entry("should accept tcp protocol as string", "\"TCP\"", protocolType, numorstring.ProtocolFromString("TCP")),
Entry("should accept tcp protocol as string", "\"TCP\"", protocolType, numorstring.ProtocolFromString("TCP")),
Entry("should accept 0 protocol as string", "\"0\"", protocolType, numorstring.ProtocolFromInt(0)),
Entry("should accept 0 protocol as string", "\"255\"", protocolType, numorstring.ProtocolFromInt(255)),
Entry("should accept 256 protocol as string", "\"256\"", protocolType, numorstring.ProtocolFromString("256")),
Entry("should reject bad protocol string", "\"25", protocolType, nil),
)
// Perform tests of JSON marshaling of the various field types.
DescribeTable("NumOrStringJSONMarshaling",
func(field interface{}, jtext string) {
b, err := json.Marshal(field)
if jtext != "" {
Expect(err).To(BeNil(),
"expected json marshal to not error")
Expect(string(b)).To(Equal(jtext),
"expected json not same as marshalled value")
} else {
Expect(err).ToNot(BeNil(),
"expected json marshal to error")
}
},
// ASNumber tests.
Entry("should marshal ASN of 0", numorstring.ASNumber(0), "0"),
Entry("should marshal ASN of 4294967295", numorstring.ASNumber(4294967295), "4294967295"),
// Port tests.
Entry("should marshal port of 0", numorstring.SinglePort(0), "0"),
Entry("should marshal port of 65535", portFromRange(65535, 65535), "65535"),
Entry("should marshal port of 10", portFromString("10"), "10"),
Entry("should marshal port range of 10:20", portFromRange(10, 20), "\"10:20\""),
Entry("should marshal port range of 20:30", portFromRange(20, 30), "\"20:30\""),
Entry("should marshal named port", numorstring.NamedPort("foobar"), `"foobar"`),
// Protocol tests.
Entry("should marshal protocol of 0", numorstring.ProtocolFromInt(0), "0"),
Entry("should marshal protocol of udp", numorstring.ProtocolFromString("UDP"), "\"UDP\""),
)
// Perform tests of Stringer interface various field types.
DescribeTable("NumOrStringStringify",
func(field interface{}, s string) {
a := fmt.Sprint(field)
Expect(a).To(Equal(s),
"expected String() value to match")
},
// ASNumber tests.
Entry("should stringify ASN of 0", numorstring.ASNumber(0), "0"),
Entry("should stringify ASN of 4294967295", numorstring.ASNumber(4294967295), "4294967295"),
// Port tests.
Entry("should stringify port of 20", numorstring.SinglePort(20), "20"),
Entry("should stringify port range of 10:20", portFromRange(10, 20), "10:20"),
// Protocol tests.
Entry("should stringify protocol of 0", numorstring.ProtocolFromInt(0), "0"),
Entry("should stringify protocol of udp", numorstring.ProtocolFromString("UDP"), "UDP"),
)
// Perform tests of Protocols supporting ports.
DescribeTable("NumOrStringProtocolsSupportingPorts",
func(protocol numorstring.Protocol, supportsPorts bool) {
Expect(protocol.SupportsPorts()).To(Equal(supportsPorts),
"expected protocol port support to match")
},
Entry("protocol 6 supports ports", numorstring.ProtocolFromInt(6), true),
Entry("protocol 17 supports ports", numorstring.ProtocolFromInt(17), true),
Entry("protocol udp supports ports", numorstring.ProtocolFromString("UDP"), true),
Entry("protocol udp supports ports", numorstring.ProtocolFromString("TCP"), true),
Entry("protocol foo does not support ports", numorstring.ProtocolFromString("foo"), false),
Entry("protocol 2 does not support ports", numorstring.ProtocolFromInt(2), false),
)
// Perform tests of Protocols FromString method.
DescribeTable("NumOrStringProtocols FromString is not case sensitive",
func(input, expected string) {
Expect(numorstring.ProtocolFromString(input).StrVal).To(Equal(expected),
"expected parsed protocol to match")
},
Entry("protocol udp -> UDP", "udp", "UDP"),
Entry("protocol tcp -> TCP", "tcp", "TCP"),
Entry("protocol updlite -> UDPLite", "udplite", "UDPLite"),
Entry("unknown protocol xxxXXX", "xxxXXX", "xxxXXX"),
)
// Perform tests of Protocols FromStringV1 method.
DescribeTable("NumOrStringProtocols FromStringV1 is lowercase",
func(input, expected string) {
Expect(numorstring.ProtocolFromStringV1(input).StrVal).To(Equal(expected),
"expected parsed protocol to match")
},
Entry("protocol udp -> UDP", "UDP", "udp"),
Entry("protocol tcp -> TCP", "TCP", "tcp"),
Entry("protocol updlite -> UDPLite", "UDPLite", "udplite"),
Entry("unknown protocol xxxXXX", "xxxXXX", "xxxxxx"),
)
// Perform tests of Protocols ToV1 method.
DescribeTable("NumOrStringProtocols FromStringV1 is lowercase",
func(input, expected numorstring.Protocol) {
Expect(input.ToV1()).To(Equal(expected),
"expected parsed protocol to match")
},
// Protocol tests.
Entry("protocol udp -> UDP", numorstring.ProtocolFromInt(2), numorstring.ProtocolFromInt(2)),
Entry("protocol tcp -> TCP", numorstring.ProtocolFromString("TCP"), numorstring.ProtocolFromStringV1("TCP")),
)
}
func portFromRange(minPort, maxPort uint16) numorstring.Port {
p, _ := numorstring.PortFromRange(minPort, maxPort)
return p
}
func portFromString(s string) numorstring.Port {
p, _ := numorstring.PortFromString(s)
return p
}

View File

@@ -1,144 +0,0 @@
// Copyright (c) 2016-2017 Tigera, Inc. All rights reserved.
//
// 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 numorstring
import (
"encoding/json"
"errors"
"fmt"
"regexp"
"strconv"
)
// Port represents either a range of numeric ports or a named port.
//
// - For a named port, set the PortName, leaving MinPort and MaxPort as 0.
// - For a port range, set MinPort and MaxPort to the (inclusive) port numbers. Set
// PortName to "".
// - For a single port, set MinPort = MaxPort and PortName = "".
type Port struct {
MinPort uint16 `json:"minPort,omitempty"`
MaxPort uint16 `json:"maxPort,omitempty"`
PortName string `validate:"omitempty,portName" json:"portName,omitempty"`
}
// SinglePort creates a Port struct representing a single port.
func SinglePort(port uint16) Port {
return Port{MinPort: port, MaxPort: port}
}
func NamedPort(name string) Port {
return Port{PortName: name}
}
// PortFromRange creates a Port struct representing a range of ports.
func PortFromRange(minPort, maxPort uint16) (Port, error) {
port := Port{MinPort: minPort, MaxPort: maxPort}
if minPort > maxPort {
msg := fmt.Sprintf("minimum port number (%d) is greater than maximum port number (%d) in port range", minPort, maxPort)
return port, errors.New(msg)
}
return port, nil
}
var (
allDigits = regexp.MustCompile(`^\d+$`)
portRange = regexp.MustCompile(`^(\d+):(\d+)$`)
nameRegex = regexp.MustCompile("^[a-zA-Z0-9_.-]{1,128}$")
)
// PortFromString creates a Port struct from its string representation. A port
// may either be single value "1234", a range of values "100:200" or a named port: "name".
func PortFromString(s string) (Port, error) {
if allDigits.MatchString(s) {
// Port is all digits, it should parse as a single port.
num, err := strconv.ParseUint(s, 10, 16)
if err != nil {
msg := fmt.Sprintf("invalid port format (%s)", s)
return Port{}, errors.New(msg)
}
return SinglePort(uint16(num)), nil
}
if groups := portRange.FindStringSubmatch(s); len(groups) > 0 {
// Port matches <digits>:<digits>, it should parse as a range of ports.
if pmin, err := strconv.ParseUint(groups[1], 10, 16); err != nil {
msg := fmt.Sprintf("invalid minimum port number in range (%s)", s)
return Port{}, errors.New(msg)
} else if pmax, err := strconv.ParseUint(groups[2], 10, 16); err != nil {
msg := fmt.Sprintf("invalid maximum port number in range (%s)", s)
return Port{}, errors.New(msg)
} else {
return PortFromRange(uint16(pmin), uint16(pmax))
}
}
if !nameRegex.MatchString(s) {
msg := fmt.Sprintf("invalid name for named port (%s)", s)
return Port{}, errors.New(msg)
}
return NamedPort(s), nil
}
// UnmarshalJSON implements the json.Unmarshaller interface.
func (p *Port) UnmarshalJSON(b []byte) error {
if b[0] == '"' {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
if v, err := PortFromString(s); err != nil {
return err
} else {
*p = v
return nil
}
}
// It's not a string, it must be a single int.
var i uint16
if err := json.Unmarshal(b, &i); err != nil {
return err
}
v := SinglePort(i)
*p = v
return nil
}
// MarshalJSON implements the json.Marshaller interface.
func (p Port) MarshalJSON() ([]byte, error) {
if p.PortName != "" {
return json.Marshal(p.PortName)
} else if p.MinPort == p.MaxPort {
return json.Marshal(p.MinPort)
} else {
return json.Marshal(p.String())
}
}
// String returns the string value. If the min and max port are the same
// this returns a single string representation of the port number, otherwise
// if returns a colon separated range of ports.
func (p Port) String() string {
if p.PortName != "" {
return p.PortName
} else if p.MinPort == p.MaxPort {
return strconv.FormatUint(uint64(p.MinPort), 10)
} else {
return fmt.Sprintf("%d:%d", p.MinPort, p.MaxPort)
}
}

View File

@@ -1,134 +0,0 @@
// Copyright (c) 2016 Tigera, Inc. All rights reserved.
// 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 numorstring
import "strings"
const (
ProtocolUDP = "UDP"
ProtocolTCP = "TCP"
ProtocolICMP = "ICMP"
ProtocolICMPv6 = "ICMPv6"
ProtocolSCTP = "SCTP"
ProtocolUDPLite = "UDPLite"
ProtocolUDPV1 = "udp"
ProtocolTCPV1 = "tcp"
)
var (
allProtocolNames = []string{
ProtocolUDP,
ProtocolTCP,
ProtocolICMP,
ProtocolICMPv6,
ProtocolSCTP,
ProtocolUDPLite,
}
)
type Protocol Uint8OrString
// ProtocolFromInt creates a Protocol struct from an integer value.
func ProtocolFromInt(p uint8) Protocol {
return Protocol(
Uint8OrString{Type: NumOrStringNum, NumVal: p},
)
}
// ProtocolV3FromProtocolV1 creates a v3 Protocol from a v1 Protocol,
// while handling case conversion.
func ProtocolV3FromProtocolV1(p Protocol) Protocol {
if p.Type == NumOrStringNum {
return p
}
for _, n := range allProtocolNames {
if strings.ToLower(n) == strings.ToLower(p.StrVal) {
return Protocol(
Uint8OrString{Type: NumOrStringString, StrVal: n},
)
}
}
return p
}
// ProtocolFromString creates a Protocol struct from a string value.
func ProtocolFromString(p string) Protocol {
for _, n := range allProtocolNames {
if strings.ToLower(n) == strings.ToLower(p) {
return Protocol(
Uint8OrString{Type: NumOrStringString, StrVal: n},
)
}
}
// Unknown protocol - return the value unchanged. Validation should catch this.
return Protocol(
Uint8OrString{Type: NumOrStringString, StrVal: p},
)
}
// ProtocolFromStringV1 creates a Protocol struct from a string value (for the v1 API)
func ProtocolFromStringV1(p string) Protocol {
return Protocol(
Uint8OrString{Type: NumOrStringString, StrVal: strings.ToLower(p)},
)
}
// UnmarshalJSON implements the json.Unmarshaller interface.
func (p *Protocol) UnmarshalJSON(b []byte) error {
return (*Uint8OrString)(p).UnmarshalJSON(b)
}
// MarshalJSON implements the json.Marshaller interface.
func (p Protocol) MarshalJSON() ([]byte, error) {
return Uint8OrString(p).MarshalJSON()
}
// String returns the string value, or the Itoa of the int value.
func (p Protocol) String() string {
return (Uint8OrString)(p).String()
}
// String returns the string value, or the Itoa of the int value.
func (p Protocol) ToV1() Protocol {
if p.Type == NumOrStringNum {
return p
}
return ProtocolFromStringV1(p.StrVal)
}
// NumValue returns the NumVal if type Int, or if
// it is a String, will attempt a conversion to int.
func (p Protocol) NumValue() (uint8, error) {
return (Uint8OrString)(p).NumValue()
}
// SupportsProtocols returns whether this protocol supports ports. This returns true if
// the numerical or string verion of the protocol indicates TCP (6) or UDP (17).
func (p Protocol) SupportsPorts() bool {
num, err := p.NumValue()
if err == nil {
return num == 6 || num == 17
} else {
switch p.StrVal {
case ProtocolTCP, ProtocolUDP, ProtocolTCPV1, ProtocolUDPV1:
return true
}
return false
}
}

View File

@@ -1,23 +0,0 @@
// Copyright (c) 2016 Tigera, Inc. All rights reserved.
// 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 numorstring
// Type represents the stored type of Int32OrString.
type NumOrStringType int
const (
NumOrStringNum NumOrStringType = iota // The structure holds a number.
NumOrStringString // The structure holds a string.
)

View File

@@ -1,80 +0,0 @@
// Copyright (c) 2016 Tigera, Inc. All rights reserved.
// 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 numorstring
import (
"encoding/json"
"strconv"
)
// UInt8OrString is a type that can hold an uint8 or a string. When used in
// JSON or YAML marshalling and unmarshalling, it produces or consumes the
// inner type. This allows you to have, for example, a JSON field that can
// accept a name or number.
type Uint8OrString struct {
Type NumOrStringType
NumVal uint8
StrVal string
}
// UnmarshalJSON implements the json.Unmarshaller interface.
func (i *Uint8OrString) UnmarshalJSON(b []byte) error {
if b[0] == '"' {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
num, err := strconv.ParseUint(s, 10, 8)
if err == nil {
i.Type = NumOrStringNum
i.NumVal = uint8(num)
} else {
i.Type = NumOrStringString
i.StrVal = s
}
return nil
}
i.Type = NumOrStringNum
return json.Unmarshal(b, &i.NumVal)
}
// MarshalJSON implements the json.Marshaller interface.
func (i Uint8OrString) MarshalJSON() ([]byte, error) {
if num, err := i.NumValue(); err == nil {
return json.Marshal(num)
} else {
return json.Marshal(i.StrVal)
}
}
// String returns the string value, or the Itoa of the int value.
func (i Uint8OrString) String() string {
if i.Type == NumOrStringString {
return i.StrVal
}
return strconv.FormatUint(uint64(i.NumVal), 10)
}
// NumValue returns the NumVal if type Int, or if
// it is a String, will attempt a conversion to int.
func (i Uint8OrString) NumValue() (uint8, error) {
if i.Type == NumOrStringString {
num, err := strconv.ParseUint(i.StrVal, 10, 8)
return uint8(num), err
}
return i.NumVal, nil
}

View File

@@ -31,78 +31,70 @@ import (
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
return map[string]common.OpenAPIDefinition{
"k8s.io/api/networking/v1.IPBlock": schema_k8sio_api_networking_v1_IPBlock(ref),
"k8s.io/api/networking/v1.NetworkPolicy": schema_k8sio_api_networking_v1_NetworkPolicy(ref),
"k8s.io/api/networking/v1.NetworkPolicyEgressRule": schema_k8sio_api_networking_v1_NetworkPolicyEgressRule(ref),
"k8s.io/api/networking/v1.NetworkPolicyIngressRule": schema_k8sio_api_networking_v1_NetworkPolicyIngressRule(ref),
"k8s.io/api/networking/v1.NetworkPolicyList": schema_k8sio_api_networking_v1_NetworkPolicyList(ref),
"k8s.io/api/networking/v1.NetworkPolicyPeer": schema_k8sio_api_networking_v1_NetworkPolicyPeer(ref),
"k8s.io/api/networking/v1.NetworkPolicyPort": schema_k8sio_api_networking_v1_NetworkPolicyPort(ref),
"k8s.io/api/networking/v1.NetworkPolicySpec": schema_k8sio_api_networking_v1_NetworkPolicySpec(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.APIGroup": schema_pkg_apis_meta_v1_APIGroup(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.APIGroupList": schema_pkg_apis_meta_v1_APIGroupList(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.APIResource": schema_pkg_apis_meta_v1_APIResource(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.APIResourceList": schema_pkg_apis_meta_v1_APIResourceList(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.APIVersions": schema_pkg_apis_meta_v1_APIVersions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.CreateOptions": schema_pkg_apis_meta_v1_CreateOptions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.DeleteOptions": schema_pkg_apis_meta_v1_DeleteOptions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.Duration": schema_pkg_apis_meta_v1_Duration(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.ExportOptions": schema_pkg_apis_meta_v1_ExportOptions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.FieldsV1": schema_pkg_apis_meta_v1_FieldsV1(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.GetOptions": schema_pkg_apis_meta_v1_GetOptions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.GroupKind": schema_pkg_apis_meta_v1_GroupKind(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.GroupResource": schema_pkg_apis_meta_v1_GroupResource(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersion": schema_pkg_apis_meta_v1_GroupVersion(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersionForDiscovery": schema_pkg_apis_meta_v1_GroupVersionForDiscovery(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersionKind": schema_pkg_apis_meta_v1_GroupVersionKind(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersionResource": schema_pkg_apis_meta_v1_GroupVersionResource(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.InternalEvent": schema_pkg_apis_meta_v1_InternalEvent(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector": schema_pkg_apis_meta_v1_LabelSelector(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelectorRequirement": schema_pkg_apis_meta_v1_LabelSelectorRequirement(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.List": schema_pkg_apis_meta_v1_List(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta": schema_pkg_apis_meta_v1_ListMeta(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.ListOptions": schema_pkg_apis_meta_v1_ListOptions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.ManagedFieldsEntry": schema_pkg_apis_meta_v1_ManagedFieldsEntry(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.MicroTime": schema_pkg_apis_meta_v1_MicroTime(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta": schema_pkg_apis_meta_v1_ObjectMeta(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.OwnerReference": schema_pkg_apis_meta_v1_OwnerReference(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.PartialObjectMetadata": schema_pkg_apis_meta_v1_PartialObjectMetadata(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.PartialObjectMetadataList": schema_pkg_apis_meta_v1_PartialObjectMetadataList(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.Patch": schema_pkg_apis_meta_v1_Patch(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.PatchOptions": schema_pkg_apis_meta_v1_PatchOptions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.Preconditions": schema_pkg_apis_meta_v1_Preconditions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.RootPaths": schema_pkg_apis_meta_v1_RootPaths(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.ServerAddressByClientCIDR": schema_pkg_apis_meta_v1_ServerAddressByClientCIDR(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.Status": schema_pkg_apis_meta_v1_Status(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.StatusCause": schema_pkg_apis_meta_v1_StatusCause(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.StatusDetails": schema_pkg_apis_meta_v1_StatusDetails(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.Table": schema_pkg_apis_meta_v1_Table(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.TableColumnDefinition": schema_pkg_apis_meta_v1_TableColumnDefinition(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.TableOptions": schema_pkg_apis_meta_v1_TableOptions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.TableRow": schema_pkg_apis_meta_v1_TableRow(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.TableRowCondition": schema_pkg_apis_meta_v1_TableRowCondition(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.Time": schema_pkg_apis_meta_v1_Time(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.Timestamp": schema_pkg_apis_meta_v1_Timestamp(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.TypeMeta": schema_pkg_apis_meta_v1_TypeMeta(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.UpdateOptions": schema_pkg_apis_meta_v1_UpdateOptions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.WatchEvent": schema_pkg_apis_meta_v1_WatchEvent(ref),
"k8s.io/apimachinery/pkg/util/intstr.IntOrString": schema_apimachinery_pkg_util_intstr_IntOrString(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.EntityRule": schema_pkg_apis_network_v1alpha1_EntityRule(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.HTTPMatch": schema_pkg_apis_network_v1alpha1_HTTPMatch(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.HTTPPath": schema_pkg_apis_network_v1alpha1_HTTPPath(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.ICMPFields": schema_pkg_apis_network_v1alpha1_ICMPFields(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NamespaceNetworkPolicy": schema_pkg_apis_network_v1alpha1_NamespaceNetworkPolicy(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NamespaceNetworkPolicyList": schema_pkg_apis_network_v1alpha1_NamespaceNetworkPolicyList(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NamespaceNetworkPolicySpec": schema_pkg_apis_network_v1alpha1_NamespaceNetworkPolicySpec(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.Rule": schema_pkg_apis_network_v1alpha1_Rule(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.ServiceAccountMatch": schema_pkg_apis_network_v1alpha1_ServiceAccountMatch(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicy": schema_pkg_apis_network_v1alpha1_WorkspaceNetworkPolicy(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicyEgressRule": schema_pkg_apis_network_v1alpha1_WorkspaceNetworkPolicyEgressRule(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicyIngressRule": schema_pkg_apis_network_v1alpha1_WorkspaceNetworkPolicyIngressRule(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicyList": schema_pkg_apis_network_v1alpha1_WorkspaceNetworkPolicyList(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicyPeer": schema_pkg_apis_network_v1alpha1_WorkspaceNetworkPolicyPeer(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicySpec": schema_pkg_apis_network_v1alpha1_WorkspaceNetworkPolicySpec(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicyStatus": schema_pkg_apis_network_v1alpha1_WorkspaceNetworkPolicyStatus(ref),
"k8s.io/api/networking/v1.IPBlock": schema_k8sio_api_networking_v1_IPBlock(ref),
"k8s.io/api/networking/v1.NetworkPolicy": schema_k8sio_api_networking_v1_NetworkPolicy(ref),
"k8s.io/api/networking/v1.NetworkPolicyEgressRule": schema_k8sio_api_networking_v1_NetworkPolicyEgressRule(ref),
"k8s.io/api/networking/v1.NetworkPolicyIngressRule": schema_k8sio_api_networking_v1_NetworkPolicyIngressRule(ref),
"k8s.io/api/networking/v1.NetworkPolicyList": schema_k8sio_api_networking_v1_NetworkPolicyList(ref),
"k8s.io/api/networking/v1.NetworkPolicyPeer": schema_k8sio_api_networking_v1_NetworkPolicyPeer(ref),
"k8s.io/api/networking/v1.NetworkPolicyPort": schema_k8sio_api_networking_v1_NetworkPolicyPort(ref),
"k8s.io/api/networking/v1.NetworkPolicySpec": schema_k8sio_api_networking_v1_NetworkPolicySpec(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.APIGroup": schema_pkg_apis_meta_v1_APIGroup(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.APIGroupList": schema_pkg_apis_meta_v1_APIGroupList(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.APIResource": schema_pkg_apis_meta_v1_APIResource(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.APIResourceList": schema_pkg_apis_meta_v1_APIResourceList(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.APIVersions": schema_pkg_apis_meta_v1_APIVersions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.CreateOptions": schema_pkg_apis_meta_v1_CreateOptions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.DeleteOptions": schema_pkg_apis_meta_v1_DeleteOptions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.Duration": schema_pkg_apis_meta_v1_Duration(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.ExportOptions": schema_pkg_apis_meta_v1_ExportOptions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.FieldsV1": schema_pkg_apis_meta_v1_FieldsV1(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.GetOptions": schema_pkg_apis_meta_v1_GetOptions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.GroupKind": schema_pkg_apis_meta_v1_GroupKind(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.GroupResource": schema_pkg_apis_meta_v1_GroupResource(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersion": schema_pkg_apis_meta_v1_GroupVersion(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersionForDiscovery": schema_pkg_apis_meta_v1_GroupVersionForDiscovery(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersionKind": schema_pkg_apis_meta_v1_GroupVersionKind(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.GroupVersionResource": schema_pkg_apis_meta_v1_GroupVersionResource(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.InternalEvent": schema_pkg_apis_meta_v1_InternalEvent(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector": schema_pkg_apis_meta_v1_LabelSelector(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelectorRequirement": schema_pkg_apis_meta_v1_LabelSelectorRequirement(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.List": schema_pkg_apis_meta_v1_List(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta": schema_pkg_apis_meta_v1_ListMeta(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.ListOptions": schema_pkg_apis_meta_v1_ListOptions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.ManagedFieldsEntry": schema_pkg_apis_meta_v1_ManagedFieldsEntry(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.MicroTime": schema_pkg_apis_meta_v1_MicroTime(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta": schema_pkg_apis_meta_v1_ObjectMeta(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.OwnerReference": schema_pkg_apis_meta_v1_OwnerReference(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.PartialObjectMetadata": schema_pkg_apis_meta_v1_PartialObjectMetadata(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.PartialObjectMetadataList": schema_pkg_apis_meta_v1_PartialObjectMetadataList(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.Patch": schema_pkg_apis_meta_v1_Patch(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.PatchOptions": schema_pkg_apis_meta_v1_PatchOptions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.Preconditions": schema_pkg_apis_meta_v1_Preconditions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.RootPaths": schema_pkg_apis_meta_v1_RootPaths(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.ServerAddressByClientCIDR": schema_pkg_apis_meta_v1_ServerAddressByClientCIDR(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.Status": schema_pkg_apis_meta_v1_Status(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.StatusCause": schema_pkg_apis_meta_v1_StatusCause(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.StatusDetails": schema_pkg_apis_meta_v1_StatusDetails(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.Table": schema_pkg_apis_meta_v1_Table(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.TableColumnDefinition": schema_pkg_apis_meta_v1_TableColumnDefinition(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.TableOptions": schema_pkg_apis_meta_v1_TableOptions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.TableRow": schema_pkg_apis_meta_v1_TableRow(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.TableRowCondition": schema_pkg_apis_meta_v1_TableRowCondition(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.Time": schema_pkg_apis_meta_v1_Time(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.Timestamp": schema_pkg_apis_meta_v1_Timestamp(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.TypeMeta": schema_pkg_apis_meta_v1_TypeMeta(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.UpdateOptions": schema_pkg_apis_meta_v1_UpdateOptions(ref),
"k8s.io/apimachinery/pkg/apis/meta/v1.WatchEvent": schema_pkg_apis_meta_v1_WatchEvent(ref),
"k8s.io/apimachinery/pkg/util/intstr.IntOrString": schema_apimachinery_pkg_util_intstr_IntOrString(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NamespaceNetworkPolicy": schema_pkg_apis_network_v1alpha1_NamespaceNetworkPolicy(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NamespaceNetworkPolicyList": schema_pkg_apis_network_v1alpha1_NamespaceNetworkPolicyList(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NamespaceNetworkPolicySpec": schema_pkg_apis_network_v1alpha1_NamespaceNetworkPolicySpec(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NamespaceSelector": schema_pkg_apis_network_v1alpha1_NamespaceSelector(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NetworkPolicyEgressRule": schema_pkg_apis_network_v1alpha1_NetworkPolicyEgressRule(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NetworkPolicyIngressRule": schema_pkg_apis_network_v1alpha1_NetworkPolicyIngressRule(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NetworkPolicyPeer": schema_pkg_apis_network_v1alpha1_NetworkPolicyPeer(ref),
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.ServiceSelector": schema_pkg_apis_network_v1alpha1_ServiceSelector(ref),
}
}
@@ -2523,196 +2515,6 @@ func schema_apimachinery_pkg_util_intstr_IntOrString(ref common.ReferenceCallbac
}
}
func schema_pkg_apis_network_v1alpha1_EntityRule(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "An EntityRule is a sub-component of a Rule comprising the match criteria specific to a particular entity (that is either the source or destination).\n\nA source EntityRule matches the source endpoint and originating traffic. A destination EntityRule matches the destination endpoint and terminating traffic.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"nets": {
SchemaProps: spec.SchemaProps{
Description: "Nets is an optional field that restricts the rule to only apply to traffic that originates from (or terminates at) IP addresses in any of the given subnets.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
},
},
},
"selector": {
SchemaProps: spec.SchemaProps{
Description: "Selector is an optional field that contains a selector expression (see Policy for sample syntax). Only traffic that originates from (terminates at) endpoints matching the selector will be matched.\n\nNote that: in addition to the negated version of the Selector (see NotSelector below), the selector expression syntax itself supports negation. The two types of negation are subtly different. One negates the set of matched endpoints, the other negates the whole match:\n\n\tSelector = \"!has(my_label)\" matches packets that are from other Calico-controlled\n\tendpoints that do not have the label “my_label”.\n\n\tNotSelector = \"has(my_label)\" matches packets that are not from Calico-controlled\n\tendpoints that do have the label “my_label”.\n\nThe effect is that the latter will accept packets from non-Calico sources whereas the former is limited to packets from Calico-controlled endpoints.",
Type: []string{"string"},
Format: "",
},
},
"namespaceSelector": {
SchemaProps: spec.SchemaProps{
Description: "NamespaceSelector is an optional field that contains a selector expression. Only traffic that originates from (or terminates at) endpoints within the selected namespaces will be matched. When both NamespaceSelector and Selector are defined on the same rule, then only workload endpoints that are matched by both selectors will be selected by the rule.\n\nFor NetworkPolicy, an empty NamespaceSelector implies that the Selector is limited to selecting only workload endpoints in the same namespace as the NetworkPolicy.\n\nFor GlobalNetworkPolicy, an empty NamespaceSelector implies the Selector applies to workload endpoints across all namespaces.",
Type: []string{"string"},
Format: "",
},
},
"ports": {
SchemaProps: spec.SchemaProps{
Description: "Ports is an optional field that restricts the rule to only apply to traffic that has a source (destination) port that matches one of these ranges/values. This value is a list of integers or strings that represent ranges of ports.\n\nSince only some protocols have ports, if any ports are specified it requires the Protocol match in the Rule to be set to \"TCP\" or \"UDP\".",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1/numorstring.Port"),
},
},
},
},
},
"notNets": {
SchemaProps: spec.SchemaProps{
Description: "NotNets is the negated version of the Nets field.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
},
},
},
"notSelector": {
SchemaProps: spec.SchemaProps{
Description: "NotSelector is the negated version of the Selector field. See Selector field for subtleties with negated selectors.",
Type: []string{"string"},
Format: "",
},
},
"notPorts": {
SchemaProps: spec.SchemaProps{
Description: "NotPorts is the negated version of the Ports field. Since only some protocols have ports, if any ports are specified it requires the Protocol match in the Rule to be set to \"TCP\" or \"UDP\".",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1/numorstring.Port"),
},
},
},
},
},
"serviceAccounts": {
SchemaProps: spec.SchemaProps{
Description: "ServiceAccounts is an optional field that restricts the rule to only apply to traffic that originates from (or terminates at) a pod running as a matching service account.",
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.ServiceAccountMatch"),
},
},
},
},
},
Dependencies: []string{
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.ServiceAccountMatch", "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1/numorstring.Port"},
}
}
func schema_pkg_apis_network_v1alpha1_HTTPMatch(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "HTTPMatch is an optional field that apply only to HTTP requests The Methods and Path fields are joined with AND",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"methods": {
SchemaProps: spec.SchemaProps{
Description: "Methods is an optional field that restricts the rule to apply only to HTTP requests that use one of the listed HTTP Methods (e.g. GET, PUT, etc.) Multiple methods are OR'd together.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
},
},
},
"paths": {
SchemaProps: spec.SchemaProps{
Description: "Paths is an optional field that restricts the rule to apply to HTTP requests that use one of the listed HTTP Paths. Multiple paths are OR'd together. e.g: - exact: /foo - prefix: /bar NOTE: Each entry may ONLY specify either a `exact` or a `prefix` match. The validator will check for it.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.HTTPPath"),
},
},
},
},
},
},
},
},
Dependencies: []string{
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.HTTPPath"},
}
}
func schema_pkg_apis_network_v1alpha1_HTTPPath(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "HTTPPath specifies an HTTP path to match. It may be either of the form: exact: <path>: which matches the path exactly or prefix: <path-prefix>: which matches the path prefix",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"exact": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
"prefix": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
},
},
},
}
}
func schema_pkg_apis_network_v1alpha1_ICMPFields(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "ICMPFields defines structure for ICMP and NotICMP sub-struct for ICMP code and type",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"type": {
SchemaProps: spec.SchemaProps{
Description: "Match on a specific ICMP type. For example a value of 8 refers to ICMP Echo Request (i.e. pings).",
Type: []string{"integer"},
Format: "int32",
},
},
"code": {
SchemaProps: spec.SchemaProps{
Description: "Match on a specific ICMP code. If specified, the Type value must also be specified. This is a technical limitation imposed by the kernels iptables firewall, which Calico uses to enforce the rule.",
Type: []string{"integer"},
Format: "int32",
},
},
},
},
},
}
}
func schema_pkg_apis_network_v1alpha1_NamespaceNetworkPolicy(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -2803,417 +2605,9 @@ func schema_pkg_apis_network_v1alpha1_NamespaceNetworkPolicySpec(ref common.Refe
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "NamespaceNetworkPolicySpec defines the desired state of NamespaceNetworkPolicy",
Description: "NetworkPolicySpec provides the specification of a NetworkPolicy",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"order": {
SchemaProps: spec.SchemaProps{
Description: "Order is an optional field that specifies the order in which the policy is applied. Policies with higher \"order\" are applied after those with lower order. If the order is omitted, it may be considered to be \"infinite\" - i.e. the policy will be applied last. Policies with identical order will be applied in alphanumerical order based on the Policy \"Name\".",
Type: []string{"integer"},
Format: "int32",
},
},
"ingress": {
SchemaProps: spec.SchemaProps{
Description: "The ordered set of ingress rules. Each rule contains a set of packet match criteria and a corresponding action to apply.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.Rule"),
},
},
},
},
},
"egress": {
SchemaProps: spec.SchemaProps{
Description: "The ordered set of egress rules. Each rule contains a set of packet match criteria and a corresponding action to apply.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.Rule"),
},
},
},
},
},
"selector": {
SchemaProps: spec.SchemaProps{
Description: "The selector is an expression used to pick pick out the endpoints that the policy should be applied to.\n\nSelector expressions follow this syntax:\n\n\tlabel == \"string_literal\" -> comparison, e.g. my_label == \"foo bar\"\n\tlabel != \"string_literal\" -> not equal; also matches if label is not present\n\tlabel in { \"a\", \"b\", \"c\", ... } -> true if the value of label X is one of \"a\", \"b\", \"c\"\n\tlabel not in { \"a\", \"b\", \"c\", ... } -> true if the value of label X is not one of \"a\", \"b\", \"c\"\n\thas(label_name) -> True if that label is present\n\t! expr -> negation of expr\n\texpr && expr -> Short-circuit and\n\texpr || expr -> Short-circuit or\n\t( expr ) -> parens for grouping\n\tall() or the empty selector -> matches all endpoints.\n\nLabel names are allowed to contain alphanumerics, -, _ and /. String literals are more permissive but they do not support escape characters.\n\nExamples (with made-up labels):\n\n\ttype == \"webserver\" && deployment == \"prod\"\n\ttype in {\"frontend\", \"backend\"}\n\tdeployment != \"dev\"\n\t! has(label_name)",
Type: []string{"string"},
Format: "",
},
},
"types": {
SchemaProps: spec.SchemaProps{
Description: "Types indicates whether this policy applies to ingress, or to egress, or to both. When not explicitly specified (and so the value on creation is empty or nil), Calico defaults Types according to what Ingress and Egress are present in the policy. The default is:\n\n- [ PolicyTypeIngress ], if there are no Egress rules (including the case where there are\n also no Ingress rules)\n\n- [ PolicyTypeEgress ], if there are Egress rules but no Ingress rules\n\n- [ PolicyTypeIngress, PolicyTypeEgress ], if there are both Ingress and Egress rules.\n\nWhen the policy is read back again, Types will always be one of these values, never empty or nil.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
},
},
},
},
Required: []string{"selector"},
},
},
Dependencies: []string{
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.Rule"},
}
}
func schema_pkg_apis_network_v1alpha1_Rule(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "A Rule encapsulates a set of match criteria and an action. Both selector-based security Policy and security Profiles reference rules - separated out as a list of rules for both ingress and egress packet matching.\n\nEach positive match criteria has a negated version, prefixed with ”Not”. All the match criteria within a rule must be satisfied for a packet to match. A single rule can contain the positive and negative version of a match and both must be satisfied for the rule to match.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"action": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
"ipVersion": {
SchemaProps: spec.SchemaProps{
Description: "IPVersion is an optional field that restricts the rule to only match a specific IP version.",
Type: []string{"integer"},
Format: "int32",
},
},
"protocol": {
SchemaProps: spec.SchemaProps{
Description: "Protocol is an optional field that restricts the rule to only apply to traffic of a specific IP protocol. Required if any of the EntityRules contain Ports (because ports only apply to certain protocols).\n\nMust be one of these string values: \"TCP\", \"UDP\", \"ICMP\", \"ICMPv6\", \"SCTP\", \"UDPLite\" or an integer in the range 1-255.",
Type: []string{"string"},
Format: "",
},
},
"icmp": {
SchemaProps: spec.SchemaProps{
Description: "ICMP is an optional field that restricts the rule to apply to a specific type and code of ICMP traffic. This should only be specified if the Protocol field is set to \"ICMP\" or \"ICMPv6\".",
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.ICMPFields"),
},
},
"notProtocol": {
SchemaProps: spec.SchemaProps{
Description: "NotProtocol is the negated version of the Protocol field.",
Type: []string{"string"},
Format: "",
},
},
"notICMP": {
SchemaProps: spec.SchemaProps{
Description: "NotICMP is the negated version of the ICMP field.",
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.ICMPFields"),
},
},
"source": {
SchemaProps: spec.SchemaProps{
Description: "Source contains the match criteria that apply to source entity.",
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.EntityRule"),
},
},
"destination": {
SchemaProps: spec.SchemaProps{
Description: "Destination contains the match criteria that apply to destination entity.",
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.EntityRule"),
},
},
"http": {
SchemaProps: spec.SchemaProps{
Description: "HTTP contains match criteria that apply to HTTP requests.",
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.HTTPMatch"),
},
},
},
Required: []string{"action"},
},
},
Dependencies: []string{
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.EntityRule", "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.HTTPMatch", "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.ICMPFields"},
}
}
func schema_pkg_apis_network_v1alpha1_ServiceAccountMatch(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"names": {
SchemaProps: spec.SchemaProps{
Description: "Names is an optional field that restricts the rule to only apply to traffic that originates from (or terminates at) a pod running as a service account whose name is in the list.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
},
},
},
"selector": {
SchemaProps: spec.SchemaProps{
Description: "Selector is an optional field that restricts the rule to only apply to traffic that originates from (or terminates at) a pod running as a service account that matches the given label selector. If both Names and Selector are specified then they are AND'ed.",
Type: []string{"string"},
Format: "",
},
},
},
},
},
}
}
func schema_pkg_apis_network_v1alpha1_WorkspaceNetworkPolicy(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "WorkspaceNetworkPolicy is a set of network policies applied to the scope to workspace",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
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/sig-architecture/api-conventions.md#types-kinds",
Type: []string{"string"},
Format: "",
},
},
"apiVersion": {
SchemaProps: spec.SchemaProps{
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/sig-architecture/api-conventions.md#resources",
Type: []string{"string"},
Format: "",
},
},
"metadata": {
SchemaProps: spec.SchemaProps{
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
},
},
"spec": {
SchemaProps: spec.SchemaProps{
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicySpec"),
},
},
"status": {
SchemaProps: spec.SchemaProps{
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicyStatus"),
},
},
},
},
},
Dependencies: []string{
"k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta", "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicySpec", "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicyStatus"},
}
}
func schema_pkg_apis_network_v1alpha1_WorkspaceNetworkPolicyEgressRule(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
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.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"ports": {
SchemaProps: spec.SchemaProps{
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.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: ref("k8s.io/api/networking/v1.NetworkPolicyPort"),
},
},
},
},
},
"from": {
SchemaProps: spec.SchemaProps{
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.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicyPeer"),
},
},
},
},
},
},
},
},
Dependencies: []string{
"k8s.io/api/networking/v1.NetworkPolicyPort", "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicyPeer"},
}
}
func schema_pkg_apis_network_v1alpha1_WorkspaceNetworkPolicyIngressRule(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
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.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"ports": {
SchemaProps: spec.SchemaProps{
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.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: ref("k8s.io/api/networking/v1.NetworkPolicyPort"),
},
},
},
},
},
"from": {
SchemaProps: spec.SchemaProps{
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.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicyPeer"),
},
},
},
},
},
},
},
},
Dependencies: []string{
"k8s.io/api/networking/v1.NetworkPolicyPort", "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicyPeer"},
}
}
func schema_pkg_apis_network_v1alpha1_WorkspaceNetworkPolicyList(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "WorkspaceNetworkPolicyList contains a list of WorkspaceNetworkPolicy",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
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/sig-architecture/api-conventions.md#types-kinds",
Type: []string{"string"},
Format: "",
},
},
"apiVersion": {
SchemaProps: spec.SchemaProps{
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/sig-architecture/api-conventions.md#resources",
Type: []string{"string"},
Format: "",
},
},
"metadata": {
SchemaProps: spec.SchemaProps{
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
},
},
"items": {
SchemaProps: spec.SchemaProps{
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicy"),
},
},
},
},
},
},
Required: []string{"items"},
},
},
Dependencies: []string{
"k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta", "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicy"},
}
}
func schema_pkg_apis_network_v1alpha1_WorkspaceNetworkPolicyPeer(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
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'",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"podSelector": {
SchemaProps: spec.SchemaProps{
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\nIf 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.",
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"),
},
},
"namespaceSelector": {
SchemaProps: spec.SchemaProps{
Description: "Selects Namespaces using cluster-scoped labels. This field follows standard label selector semantics; if present but empty, it selects all namespaces.\n\nIf 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.",
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"),
},
},
"ipBlock": {
SchemaProps: spec.SchemaProps{
Description: "IPBlock defines policy on a particular IPBlock. If this field is set then neither of the other fields can be.",
Ref: ref("k8s.io/api/networking/v1.IPBlock"),
},
},
"workspaceSelector": {
SchemaProps: spec.SchemaProps{
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"),
},
},
},
},
},
Dependencies: []string{
"k8s.io/api/networking/v1.IPBlock", "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"},
}
}
func schema_pkg_apis_network_v1alpha1_WorkspaceNetworkPolicySpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "WorkspaceNetworkPolicySpec defines the desired state of WorkspaceNetworkPolicy",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"workspace": {
SchemaProps: spec.SchemaProps{
Description: "Workspace specify the name of ws to apply this workspace network policy",
Type: []string{"string"},
Format: "",
},
},
"policyTypes": {
SchemaProps: spec.SchemaProps{
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\" ]).",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
},
},
},
"ingress": {
SchemaProps: spec.SchemaProps{
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)",
@@ -3221,7 +2615,7 @@ func schema_pkg_apis_network_v1alpha1_WorkspaceNetworkPolicySpec(ref common.Refe
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicyIngressRule"),
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NetworkPolicyIngressRule"),
},
},
},
@@ -3234,7 +2628,21 @@ func schema_pkg_apis_network_v1alpha1_WorkspaceNetworkPolicySpec(ref common.Refe
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicyEgressRule"),
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NetworkPolicyEgressRule"),
},
},
},
},
},
"policyTypes": {
SchemaProps: spec.SchemaProps{
Description: "List of rule types that the NetworkPolicy 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\" ]). This field is beta-level in 1.8",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
},
@@ -3244,16 +2652,163 @@ func schema_pkg_apis_network_v1alpha1_WorkspaceNetworkPolicySpec(ref common.Refe
},
},
Dependencies: []string{
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicyEgressRule", "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.WorkspaceNetworkPolicyIngressRule"},
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NetworkPolicyEgressRule", "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NetworkPolicyIngressRule"},
}
}
func schema_pkg_apis_network_v1alpha1_WorkspaceNetworkPolicyStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
func schema_pkg_apis_network_v1alpha1_NamespaceSelector(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "WorkspaceNetworkPolicyStatus defines the observed state of WorkspaceNetworkPolicy",
Type: []string{"object"},
Type: []string{"object"},
Properties: map[string]spec.Schema{
"name": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"name"},
},
},
}
}
func schema_pkg_apis_network_v1alpha1_NetworkPolicyEgressRule(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "NetworkPolicyEgressRule describes a particular set of traffic that is allowed out of pods matched by a NetworkPolicySpec's podSelector. The traffic must match both ports and to. This type is beta-level in 1.8",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"ports": {
SchemaProps: spec.SchemaProps{
Description: "List of destination ports for outgoing traffic. 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.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: ref("k8s.io/api/networking/v1.NetworkPolicyPort"),
},
},
},
},
},
"to": {
SchemaProps: spec.SchemaProps{
Description: "List of destinations for outgoing traffic of 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 destinations (traffic not restricted by destination). If this field is present and contains at least one item, this rule allows traffic only if the traffic matches at least one item in the to list.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NetworkPolicyPeer"),
},
},
},
},
},
},
},
},
Dependencies: []string{
"k8s.io/api/networking/v1.NetworkPolicyPort", "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NetworkPolicyPeer"},
}
}
func schema_pkg_apis_network_v1alpha1_NetworkPolicyIngressRule(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "NetworkPolicyIngressRule describes a particular set of traffic that is allowed to the pods matched by a NetworkPolicySpec's podSelector. The traffic must match both ports and from.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"ports": {
SchemaProps: spec.SchemaProps{
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.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: ref("k8s.io/api/networking/v1.NetworkPolicyPort"),
},
},
},
},
},
"from": {
SchemaProps: spec.SchemaProps{
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 one item, this rule allows traffic only if the traffic matches at least one item in the from list.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NetworkPolicyPeer"),
},
},
},
},
},
},
},
},
Dependencies: []string{
"k8s.io/api/networking/v1.NetworkPolicyPort", "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NetworkPolicyPeer"},
}
}
func schema_pkg_apis_network_v1alpha1_NetworkPolicyPeer(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "NetworkPolicyPeer describes a peer to allow traffic from. Only certain combinations of fields are allowed",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"namespace": {
SchemaProps: spec.SchemaProps{
Description: "Selects Namespaces using cluster-scoped labels. This field follows standard label selector semantics; if present but empty, it selects all namespaces.\n\nIf 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.",
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NamespaceSelector"),
},
},
"ipBlock": {
SchemaProps: spec.SchemaProps{
Description: "IPBlock defines policy on a particular IPBlock. If this field is set then neither of the other fields can be.",
Ref: ref("k8s.io/api/networking/v1.IPBlock"),
},
},
"service": {
SchemaProps: spec.SchemaProps{
Ref: ref("kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.ServiceSelector"),
},
},
},
},
},
Dependencies: []string{
"k8s.io/api/networking/v1.IPBlock", "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.NamespaceSelector", "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1.ServiceSelector"},
}
}
func schema_pkg_apis_network_v1alpha1_ServiceSelector(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"name": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
"namespace": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"name", "namespace"},
},
},
}

View File

@@ -33,7 +33,7 @@ var c client.Client
func TestMain(m *testing.M) {
t := &envtest.Environment{
CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "..", "kustomize", "network", "crds")},
CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "..", "config", "crds")},
}
err := SchemeBuilder.AddToScheme(scheme.Scheme)

View File

@@ -1,145 +0,0 @@
/*
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"
)
const (
ResourceKindWorkspaceNetworkPolicy = "WorkspaceNetworkPolicy"
ResourceSingularWorkspaceNetworkPolicy = "workspacenetworkpolicy"
ResourcePluralWorkspaceNetworkPolicy = "workspacenetworkpolicies"
)
// 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
// +kubebuilder:resource:categories="networking",scope="Cluster",shortName="wsnp"
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{})
}

View File

@@ -1,56 +0,0 @@
/*
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())
}

View File

@@ -16,129 +16,22 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by controller-gen. DO NOT EDIT.
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1alpha1
import (
"k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/api/networking/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1/numorstring"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *EntityRule) DeepCopyInto(out *EntityRule) {
*out = *in
if in.Nets != nil {
in, out := &in.Nets, &out.Nets
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Ports != nil {
in, out := &in.Ports, &out.Ports
*out = make([]numorstring.Port, len(*in))
copy(*out, *in)
}
if in.NotNets != nil {
in, out := &in.NotNets, &out.NotNets
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.NotPorts != nil {
in, out := &in.NotPorts, &out.NotPorts
*out = make([]numorstring.Port, len(*in))
copy(*out, *in)
}
if in.ServiceAccounts != nil {
in, out := &in.ServiceAccounts, &out.ServiceAccounts
*out = new(ServiceAccountMatch)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EntityRule.
func (in *EntityRule) DeepCopy() *EntityRule {
if in == nil {
return nil
}
out := new(EntityRule)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HTTPMatch) DeepCopyInto(out *HTTPMatch) {
*out = *in
if in.Methods != nil {
in, out := &in.Methods, &out.Methods
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Paths != nil {
in, out := &in.Paths, &out.Paths
*out = make([]HTTPPath, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPMatch.
func (in *HTTPMatch) DeepCopy() *HTTPMatch {
if in == nil {
return nil
}
out := new(HTTPMatch)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HTTPPath) DeepCopyInto(out *HTTPPath) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPPath.
func (in *HTTPPath) DeepCopy() *HTTPPath {
if in == nil {
return nil
}
out := new(HTTPPath)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ICMPFields) DeepCopyInto(out *ICMPFields) {
*out = *in
if in.Type != nil {
in, out := &in.Type, &out.Type
*out = new(int)
**out = **in
}
if in.Code != nil {
in, out := &in.Code, &out.Code
*out = new(int)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ICMPFields.
func (in *ICMPFields) DeepCopy() *ICMPFields {
if in == nil {
return nil
}
out := new(ICMPFields)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NamespaceNetworkPolicy) DeepCopyInto(out *NamespaceNetworkPolicy) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceNetworkPolicy.
@@ -171,6 +64,7 @@ func (in *NamespaceNetworkPolicyList) DeepCopyInto(out *NamespaceNetworkPolicyLi
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceNetworkPolicyList.
@@ -194,30 +88,26 @@ func (in *NamespaceNetworkPolicyList) DeepCopyObject() runtime.Object {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NamespaceNetworkPolicySpec) DeepCopyInto(out *NamespaceNetworkPolicySpec) {
*out = *in
if in.Order != nil {
in, out := &in.Order, &out.Order
*out = new(int)
**out = **in
}
if in.Ingress != nil {
in, out := &in.Ingress, &out.Ingress
*out = make([]Rule, len(*in))
*out = make([]NetworkPolicyIngressRule, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Egress != nil {
in, out := &in.Egress, &out.Egress
*out = make([]Rule, len(*in))
*out = make([]NetworkPolicyEgressRule, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Types != nil {
in, out := &in.Types, &out.Types
*out = make([]PolicyType, len(*in))
if in.PolicyTypes != nil {
in, out := &in.PolicyTypes, &out.PolicyTypes
*out = make([]v1.PolicyType, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceNetworkPolicySpec.
@@ -231,255 +121,124 @@ func (in *NamespaceNetworkPolicySpec) DeepCopy() *NamespaceNetworkPolicySpec {
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Rule) DeepCopyInto(out *Rule) {
func (in *NamespaceSelector) DeepCopyInto(out *NamespaceSelector) {
*out = *in
if in.IPVersion != nil {
in, out := &in.IPVersion, &out.IPVersion
*out = new(int)
**out = **in
}
if in.Protocol != nil {
in, out := &in.Protocol, &out.Protocol
*out = new(v1.Protocol)
**out = **in
}
if in.ICMP != nil {
in, out := &in.ICMP, &out.ICMP
*out = new(ICMPFields)
(*in).DeepCopyInto(*out)
}
if in.NotProtocol != nil {
in, out := &in.NotProtocol, &out.NotProtocol
*out = new(v1.Protocol)
**out = **in
}
if in.NotICMP != nil {
in, out := &in.NotICMP, &out.NotICMP
*out = new(ICMPFields)
(*in).DeepCopyInto(*out)
}
in.Source.DeepCopyInto(&out.Source)
in.Destination.DeepCopyInto(&out.Destination)
if in.HTTP != nil {
in, out := &in.HTTP, &out.HTTP
*out = new(HTTPMatch)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Rule.
func (in *Rule) DeepCopy() *Rule {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceSelector.
func (in *NamespaceSelector) DeepCopy() *NamespaceSelector {
if in == nil {
return nil
}
out := new(Rule)
out := new(NamespaceSelector)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ServiceAccountMatch) DeepCopyInto(out *ServiceAccountMatch) {
*out = *in
if in.Names != nil {
in, out := &in.Names, &out.Names
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAccountMatch.
func (in *ServiceAccountMatch) DeepCopy() *ServiceAccountMatch {
if in == nil {
return nil
}
out := new(ServiceAccountMatch)
in.DeepCopyInto(out)
return out
}
// 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) {
func (in *NetworkPolicyEgressRule) DeepCopyInto(out *NetworkPolicyEgressRule) {
*out = *in
if in.Ports != nil {
in, out := &in.Ports, &out.Ports
*out = make([]networkingv1.NetworkPolicyPort, len(*in))
*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))
*out = make([]NetworkPolicyPeer, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceNetworkPolicyEgressRule.
func (in *WorkspaceNetworkPolicyEgressRule) DeepCopy() *WorkspaceNetworkPolicyEgressRule {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPolicyEgressRule.
func (in *NetworkPolicyEgressRule) DeepCopy() *NetworkPolicyEgressRule {
if in == nil {
return nil
}
out := new(WorkspaceNetworkPolicyEgressRule)
out := new(NetworkPolicyEgressRule)
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) {
func (in *NetworkPolicyIngressRule) DeepCopyInto(out *NetworkPolicyIngressRule) {
*out = *in
if in.Ports != nil {
in, out := &in.Ports, &out.Ports
*out = make([]networkingv1.NetworkPolicyPort, len(*in))
*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))
*out = make([]NetworkPolicyPeer, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceNetworkPolicyIngressRule.
func (in *WorkspaceNetworkPolicyIngressRule) DeepCopy() *WorkspaceNetworkPolicyIngressRule {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPolicyIngressRule.
func (in *NetworkPolicyIngressRule) DeepCopy() *NetworkPolicyIngressRule {
if in == nil {
return nil
}
out := new(WorkspaceNetworkPolicyIngressRule)
out := new(NetworkPolicyIngressRule)
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) {
func (in *NetworkPolicyPeer) DeepCopyInto(out *NetworkPolicyPeer) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.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])
}
if in.NamespaceSelector != nil {
in, out := &in.NamespaceSelector, &out.NamespaceSelector
*out = new(NamespaceSelector)
**out = **in
}
}
// 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)
if in.IPBlock != nil {
in, out := &in.IPBlock, &out.IPBlock
*out = new(v1.IPBlock)
(*in).DeepCopyInto(*out)
}
if in.ServiceSelector != nil {
in, out := &in.ServiceSelector, &out.ServiceSelector
*out = new(ServiceSelector)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceNetworkPolicyPeer.
func (in *WorkspaceNetworkPolicyPeer) DeepCopy() *WorkspaceNetworkPolicyPeer {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPolicyPeer.
func (in *NetworkPolicyPeer) DeepCopy() *NetworkPolicyPeer {
if in == nil {
return nil
}
out := new(WorkspaceNetworkPolicyPeer)
out := new(NetworkPolicyPeer)
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) {
func (in *ServiceSelector) DeepCopyInto(out *ServiceSelector) {
*out = *in
if in.PolicyTypes != nil {
in, out := &in.PolicyTypes, &out.PolicyTypes
*out = make([]networkingv1.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])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceNetworkPolicySpec.
func (in *WorkspaceNetworkPolicySpec) DeepCopy() *WorkspaceNetworkPolicySpec {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceSelector.
func (in *ServiceSelector) DeepCopy() *ServiceSelector {
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)
out := new(ServiceSelector)
in.DeepCopyInto(out)
return out
}

View File

@@ -2263,6 +2263,12 @@ func schema_pkg_apis_tenant_v1alpha1_WorkspaceSpec(ref common.ReferenceCallback)
Format: "",
},
},
"networkIsolation": {
SchemaProps: spec.SchemaProps{
Type: []string{"boolean"},
Format: "",
},
},
},
},
},

View File

@@ -34,7 +34,8 @@ const (
// WorkspaceSpec defines the desired state of Workspace
type WorkspaceSpec struct {
Manager string `json:"manager,omitempty"`
Manager string `json:"manager,omitempty"`
NetworkIsolation bool `json:"networkIsolation,omitempty"`
}
// WorkspaceStatus defines the observed state of Workspace

View File

@@ -32,10 +32,6 @@ func (c *FakeNetworkV1alpha1) NamespaceNetworkPolicies(namespace string) v1alpha
return &FakeNamespaceNetworkPolicies{c, namespace}
}
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 {

View File

@@ -1,131 +0,0 @@
/*
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.
*/
// 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
}

View File

@@ -19,5 +19,3 @@ limitations under the License.
package v1alpha1
type NamespaceNetworkPolicyExpansion interface{}
type WorkspaceNetworkPolicyExpansion interface{}

View File

@@ -27,7 +27,6 @@ import (
type NetworkV1alpha1Interface interface {
RESTClient() rest.Interface
NamespaceNetworkPoliciesGetter
WorkspaceNetworkPoliciesGetter
}
// NetworkV1alpha1Client is used to interact with features provided by the network.kubesphere.io group.
@@ -39,10 +38,6 @@ func (c *NetworkV1alpha1Client) NamespaceNetworkPolicies(namespace string) Names
return newNamespaceNetworkPolicies(c, namespace)
}
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

View File

@@ -1,180 +0,0 @@
/*
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.
*/
// 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
}

View File

@@ -93,8 +93,6 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
// Group=network.kubesphere.io, Version=v1alpha1
case networkv1alpha1.SchemeGroupVersion.WithResource("namespacenetworkpolicies"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Network().V1alpha1().NamespaceNetworkPolicies().Informer()}, nil
case networkv1alpha1.SchemeGroupVersion.WithResource("workspacenetworkpolicies"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Network().V1alpha1().WorkspaceNetworkPolicies().Informer()}, nil
// Group=servicemesh.kubesphere.io, Version=v1alpha2
case servicemeshv1alpha2.SchemeGroupVersion.WithResource("servicepolicies"):

View File

@@ -26,8 +26,6 @@ import (
type Interface interface {
// NamespaceNetworkPolicies returns a NamespaceNetworkPolicyInformer.
NamespaceNetworkPolicies() NamespaceNetworkPolicyInformer
// WorkspaceNetworkPolicies returns a WorkspaceNetworkPolicyInformer.
WorkspaceNetworkPolicies() WorkspaceNetworkPolicyInformer
}
type version struct {
@@ -45,8 +43,3 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
func (v *version) NamespaceNetworkPolicies() NamespaceNetworkPolicyInformer {
return &namespaceNetworkPolicyInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}
// WorkspaceNetworkPolicies returns a WorkspaceNetworkPolicyInformer.
func (v *version) WorkspaceNetworkPolicies() WorkspaceNetworkPolicyInformer {
return &workspaceNetworkPolicyInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
}

View File

@@ -1,88 +0,0 @@
/*
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.
*/
// 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())
}

View File

@@ -25,7 +25,3 @@ type NamespaceNetworkPolicyListerExpansion interface{}
// NamespaceNetworkPolicyNamespaceListerExpansion allows custom methods to be added to
// NamespaceNetworkPolicyNamespaceLister.
type NamespaceNetworkPolicyNamespaceListerExpansion interface{}
// WorkspaceNetworkPolicyListerExpansion allows custom methods to be added to
// WorkspaceNetworkPolicyLister.
type WorkspaceNetworkPolicyListerExpansion interface{}

View File

@@ -1,65 +0,0 @@
/*
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.
*/
// 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
}

View File

@@ -34,6 +34,7 @@ const (
IngressControllerPrefix = "kubesphere-router-"
WorkspaceLabelKey = "kubesphere.io/workspace"
NamespaceLabelKey = "kubesphere.io/namespace"
DisplayNameAnnotationKey = "kubesphere.io/alias-name"
DescriptionAnnotationKey = "kubesphere.io/description"
CreatorAnnotationKey = "kubesphere.io/creator"

View File

@@ -117,6 +117,10 @@ func (r *ReconcileNamespace) Reconcile(request reconcile.Request) (reconcile.Res
// then lets add the finalizer and update the object.
if !sliceutil.HasString(instance.ObjectMeta.Finalizers, finalizer) {
instance.ObjectMeta.Finalizers = append(instance.ObjectMeta.Finalizers, finalizer)
if instance.Labels == nil {
instance.Labels = make(map[string]string)
}
instance.Labels[constants.NamespaceLabelKey] = instance.Name
if err := r.Update(context.Background(), instance); err != nil {
return reconcile.Result{}, err
}

View File

@@ -1,6 +0,0 @@
package controllerapi
// Controller expose Run method
type Controller interface {
Run(threadiness int, stopCh <-chan struct{}) error
}

View File

@@ -1,5 +1,5 @@
package network
// +kubebuilder:rbac:groups=network.kubesphere.io,resources=workspacenetworkpolicies;namespacenetworkpolicies,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups:core,resource=namespaces,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups=network.kubesphere.io,resources=namespacenetworkpolicies,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=tenant.kubesphere.io,resources=workspaces,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups:core,resource=namespaces,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups:core,resource=services,verbs=get;list;watch;create;update;patch
package network

View File

@@ -2,176 +2,658 @@ package nsnetworkpolicy
import (
"fmt"
"net"
"time"
corev1 "k8s.io/api/core/v1"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
netv1 "k8s.io/api/networking/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
typev1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/util/intstr"
uruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
v1 "k8s.io/client-go/informers/core/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/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"
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"
networklister "kubesphere.io/kubesphere/pkg/client/listers/network/v1alpha1"
"kubesphere.io/kubesphere/pkg/controller/network/controllerapi"
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1"
workspacev1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
ksnetclient "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/network/v1alpha1"
nspolicy "kubesphere.io/kubesphere/pkg/client/informers/externalversions/network/v1alpha1"
workspace "kubesphere.io/kubesphere/pkg/client/informers/externalversions/tenant/v1alpha1"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/controller/network/provider"
)
const controllerAgentName = "nsnp-controller"
const (
//TODO use set to track service:map
//use period sync service label in NSNP
defaultSleepDuration = 60 * time.Second
type controller struct {
kubeClientset kubernetes.Interface
kubesphereClientset kubesphereclient.Interface
defaultThread = 5
defaultSync = "5m"
nsnpInformer networkinformer.NamespaceNetworkPolicyInformer
nsnpLister networklister.NamespaceNetworkPolicyLister
nsnpSynced 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
nsNetworkPolicyProvider provider.NsNetworkPolicyProvider
}
//whether network isolate is enable in namespace
NamespaceNPAnnotationKey = "kubesphere.io/network-isolate"
NamespaceNPAnnotationEnabled = "enabled"
var (
log = klogr.New().WithName("Controller").WithValues("Component", controllerAgentName)
errCount = 0
AnnotationNPNAME = "network-isolate"
//TODO: configure it
DNSLocalIP = "169.254.25.10"
DNSPort = 53
DNSNamespace = "kube-system"
DNSServiceName = "kube-dns"
DNSServiceCoreDNS = "coredns"
)
func NewController(kubeclientset kubernetes.Interface,
kubesphereclientset kubesphereclient.Interface,
nsnpInformer networkinformer.NamespaceNetworkPolicyInformer,
nsNetworkPolicyProvider provider.NsNetworkPolicyProvider) controllerapi.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,
nsnpInformer: nsnpInformer,
nsnpLister: nsnpInformer.Lister(),
nsnpSynced: nsnpInformer.Informer().HasSynced,
nsNetworkPolicyProvider: nsNetworkPolicyProvider,
// namespacenpController implements the Controller interface for managing kubesphere network policies
// and convery them to k8s NetworkPolicies, then syncing them to the provider.
type NSNetworkPolicyController struct {
client kubernetes.Interface
ksclient ksnetclient.NetworkV1alpha1Interface
informer nspolicy.NamespaceNetworkPolicyInformer
informerSynced cache.InformerSynced
workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "NamespaceNetworkPolicies"),
recorder: recorder,
}
log.Info("Setting up event handlers")
nsnpInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: ctl.enqueueNSNP,
UpdateFunc: func(old, new interface{}) {
ctl.enqueueNSNP(new)
},
DeleteFunc: ctl.enqueueNSNP,
})
return ctl
//TODO support service in same namespace
serviceInformer v1.ServiceInformer
serviceInformerSynced cache.InformerSynced
nodeInformer v1.NodeInformer
nodeInformerSynced cache.InformerSynced
workspaceInformer workspace.WorkspaceInformer
workspaceInformerSynced cache.InformerSynced
namespaceInformer v1.NamespaceInformer
namespaceInformerSynced cache.InformerSynced
provider provider.NsNetworkPolicyProvider
nsQueue workqueue.RateLimitingInterface
nsnpQueue workqueue.RateLimitingInterface
}
func (c *controller) Run(threadiness int, stopCh <-chan struct{}) error {
defer utilruntime.HandleCrash()
defer c.workqueue.ShutDown()
//init client
// Start the informer factories to begin populating the informer caches
log.V(1).Info("Starting WSNP controller")
// Wait for the caches to be synced before starting workers
log.V(2).Info("Waiting for informer caches to sync")
if ok := cache.WaitForCacheSync(stopCh, c.nsnpSynced); !ok {
return fmt.Errorf("failed to wait for caches to sync")
func stringToCIDR(ipStr string) (string, error) {
cidr := ""
if ip := net.ParseIP(ipStr); ip != nil {
if ip.To4() != nil {
cidr = ipStr + "/32"
} else {
cidr = ipStr + "/128"
}
} else {
return cidr, fmt.Errorf("ip string %s parse error\n", ipStr)
}
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)
return cidr, nil
}
func generateDNSRule(nameServers []string) (netv1.NetworkPolicyEgressRule, error) {
var rule netv1.NetworkPolicyEgressRule
for _, nameServer := range nameServers {
cidr, err := stringToCIDR(nameServer)
if err != nil {
return rule, err
}
rule.To = append(rule.To, netv1.NetworkPolicyPeer{
IPBlock: &netv1.IPBlock{
CIDR: cidr,
},
})
}
protocolTCP := corev1.ProtocolTCP
protocolUDP := corev1.ProtocolUDP
dnsPort := intstr.FromInt(DNSPort)
rule.Ports = append(rule.Ports, netv1.NetworkPolicyPort{
Protocol: &protocolTCP,
Port: &dnsPort,
}, netv1.NetworkPolicyPort{
Protocol: &protocolUDP,
Port: &dnsPort,
})
return rule, nil
}
func (c *NSNetworkPolicyController) generateDNSServiceRule() (netv1.NetworkPolicyEgressRule, error) {
peer, ports, err := c.handlerPeerService(DNSNamespace, DNSServiceName, false)
if err != nil {
peer, ports, err = c.handlerPeerService(DNSNamespace, DNSServiceCoreDNS, false)
}
return netv1.NetworkPolicyEgressRule{
Ports: ports,
To: []netv1.NetworkPolicyPeer{peer},
}, err
}
func (c *NSNetworkPolicyController) handlerPeerService(namespace string, name string, ingress bool) (netv1.NetworkPolicyPeer, []netv1.NetworkPolicyPort, error) {
peerNP := netv1.NetworkPolicyPeer{}
var ports []netv1.NetworkPolicyPort
service, err := c.serviceInformer.Lister().Services(namespace).Get(name)
if err != nil {
return peerNP, nil, err
}
peerNP.PodSelector = new(metav1.LabelSelector)
peerNP.NamespaceSelector = new(metav1.LabelSelector)
if len(service.Spec.Selector) <= 0 {
return peerNP, nil, fmt.Errorf("service %s/%s has no podselect", namespace, name)
}
peerNP.PodSelector.MatchLabels = make(map[string]string)
for key, value := range service.Spec.Selector {
peerNP.PodSelector.MatchLabels[key] = value
}
peerNP.NamespaceSelector.MatchLabels = make(map[string]string)
peerNP.NamespaceSelector.MatchLabels[constants.NamespaceLabelKey] = namespace
//only allow traffic to service exposed ports
if !ingress {
ports = make([]netv1.NetworkPolicyPort, 0)
for _, port := range service.Spec.Ports {
portIntString := intstr.FromInt(int(port.Port))
ports = append(ports, netv1.NetworkPolicyPort{
Protocol: &port.Protocol,
Port: &portIntString,
})
}
}
return peerNP, ports, err
}
func (c *NSNetworkPolicyController) convertPeer(peer v1alpha1.NetworkPolicyPeer, ingress bool) (netv1.NetworkPolicyPeer, []netv1.NetworkPolicyPort, error) {
peerNP := netv1.NetworkPolicyPeer{}
var ports []netv1.NetworkPolicyPort
if peer.ServiceSelector != nil {
namespace := peer.ServiceSelector.Namespace
name := peer.ServiceSelector.Name
return c.handlerPeerService(namespace, name, ingress)
} else if peer.NamespaceSelector != nil {
name := peer.NamespaceSelector.Name
peerNP.NamespaceSelector = new(metav1.LabelSelector)
peerNP.NamespaceSelector.MatchLabels = make(map[string]string)
peerNP.NamespaceSelector.MatchLabels[constants.NamespaceLabelKey] = name
} else if peer.IPBlock != nil {
peerNP.IPBlock = peer.IPBlock
} else {
klog.Errorf("Invalid nsnp peer %v\n", peer)
return peerNP, nil, fmt.Errorf("Invalid nsnp peer %v\n", peer)
}
return peerNP, ports, nil
}
func (c *NSNetworkPolicyController) convertToK8sNP(n *v1alpha1.NamespaceNetworkPolicy) (*netv1.NetworkPolicy, error) {
np := &netv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: n.Name,
Namespace: n.Namespace,
},
Spec: netv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{},
PolicyTypes: make([]netv1.PolicyType, 0),
},
}
if n.Spec.Egress != nil {
np.Spec.Egress = make([]netv1.NetworkPolicyEgressRule, 0)
for _, egress := range n.Spec.Egress {
tmpRule := netv1.NetworkPolicyEgressRule{}
for _, peer := range egress.To {
peer, ports, err := c.convertPeer(peer, false)
if err != nil {
return nil, err
}
if ports != nil {
np.Spec.Egress = append(np.Spec.Egress, netv1.NetworkPolicyEgressRule{
Ports: ports,
To: []netv1.NetworkPolicyPeer{peer},
})
continue
}
tmpRule.To = append(tmpRule.To, peer)
}
tmpRule.Ports = egress.Ports
if tmpRule.To == nil {
continue
}
np.Spec.Egress = append(np.Spec.Egress, tmpRule)
}
np.Spec.PolicyTypes = append(np.Spec.PolicyTypes, netv1.PolicyTypeEgress)
}
if n.Spec.Ingress != nil {
np.Spec.Ingress = make([]netv1.NetworkPolicyIngressRule, 0)
for _, ingress := range n.Spec.Ingress {
tmpRule := netv1.NetworkPolicyIngressRule{}
for _, peer := range ingress.From {
peer, ports, err := c.convertPeer(peer, true)
if err != nil {
return nil, err
}
if ports != nil {
np.Spec.Ingress = append(np.Spec.Ingress, netv1.NetworkPolicyIngressRule{
Ports: ports,
From: []netv1.NetworkPolicyPeer{peer},
})
}
tmpRule.From = append(tmpRule.From, peer)
}
tmpRule.Ports = ingress.Ports
np.Spec.Ingress = append(np.Spec.Ingress, tmpRule)
}
np.Spec.PolicyTypes = append(np.Spec.PolicyTypes, netv1.PolicyTypeIngress)
}
return np, nil
}
func (c *NSNetworkPolicyController) generateNodeRule() (netv1.NetworkPolicyIngressRule, error) {
var rule netv1.NetworkPolicyIngressRule
nodes, err := c.nodeInformer.Lister().List(labels.Everything())
if err != nil {
return rule, err
}
for _, node := range nodes {
for _, address := range node.Status.Addresses {
cidr, err := stringToCIDR(address.Address)
if err != nil {
klog.V(4).Infof("Error when parse address %s", address.Address)
continue
}
rule.From = append(rule.From, netv1.NetworkPolicyPeer{
IPBlock: &netv1.IPBlock{
CIDR: cidr,
},
})
}
}
return rule, nil
}
func generateNSNP(workspace string, namespace string, matchWorkspace bool) *netv1.NetworkPolicy {
policy := &netv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: AnnotationNPNAME,
Namespace: namespace,
},
Spec: netv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{},
PolicyTypes: make([]netv1.PolicyType, 0),
Ingress: []netv1.NetworkPolicyIngressRule{{
From: []netv1.NetworkPolicyPeer{{
NamespaceSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{},
},
}},
}},
Egress: []netv1.NetworkPolicyEgressRule{{
To: []netv1.NetworkPolicyPeer{{
NamespaceSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{},
},
}},
}},
},
}
policy.Spec.PolicyTypes = append(policy.Spec.PolicyTypes, netv1.PolicyTypeIngress, netv1.PolicyTypeEgress)
if matchWorkspace {
policy.Spec.Ingress[0].From[0].NamespaceSelector.MatchLabels[constants.WorkspaceLabelKey] = workspace
policy.Spec.Egress[0].To[0].NamespaceSelector.MatchLabels[constants.WorkspaceLabelKey] = workspace
} else {
policy.Spec.Ingress[0].From[0].NamespaceSelector.MatchLabels[constants.NamespaceLabelKey] = namespace
policy.Spec.Egress[0].To[0].NamespaceSelector.MatchLabels[constants.NamespaceLabelKey] = namespace
}
return policy
}
func (c *NSNetworkPolicyController) nsEnqueue(ns *corev1.Namespace) {
key, err := cache.MetaNamespaceKeyFunc(ns)
if err != nil {
uruntime.HandleError(fmt.Errorf("Get namespace key %s failed", ns.Name))
return
}
klog.V(4).Infof("Enqueue namespace %s", ns.Name)
c.nsQueue.Add(key)
}
func (c *NSNetworkPolicyController) addWorkspace(newObj interface{}) {
new := newObj.(*workspacev1alpha1.Workspace)
klog.V(4).Infof("Add workspace %s", new.Name)
label := labels.SelectorFromSet(labels.Set{constants.WorkspaceLabelKey: new.Name})
nsList, err := c.namespaceInformer.Lister().List(label)
if err != nil {
klog.Errorf("Error while list namespace by label %s", label.String())
return
}
for _, ns := range nsList {
c.nsEnqueue(ns)
}
}
func (c *NSNetworkPolicyController) addNamespace(obj interface{}) {
ns := obj.(*corev1.Namespace)
workspaceName := ns.Labels[constants.WorkspaceLabelKey]
if workspaceName == "" {
return
}
klog.V(4).Infof("Add namespace %s", ns.Name)
c.nsEnqueue(ns)
}
func isNetworkIsolateEnabled(ns *corev1.Namespace) bool {
if ns.Annotations[NamespaceNPAnnotationKey] == NamespaceNPAnnotationEnabled {
return true
}
return false
}
func hadNamespaceLabel(ns *corev1.Namespace) bool {
if ns.Annotations[constants.NamespaceLabelKey] == ns.Name {
return true
}
return false
}
func (c *NSNetworkPolicyController) syncNs(key string) error {
klog.V(4).Infof("Sync namespace %s", key)
_, name, err := cache.SplitMetaNamespaceKey(key)
if err != nil {
klog.Errorf("Not a valid controller key %s, %#v", key, err)
return err
}
ns, err := c.namespaceInformer.Lister().Get(name)
if err != nil {
// not found, possibly been deleted
if errors.IsNotFound(err) {
klog.V(2).Infof("Namespace %v has been deleted", key)
return nil
}
return err
}
workspaceName := ns.Labels[constants.WorkspaceLabelKey]
if workspaceName == "" {
klog.Error("Workspace name should not be empty")
return nil
}
wksp, err := c.workspaceInformer.Lister().Get(workspaceName)
if err != nil {
//Should not be here
if errors.IsNotFound(err) {
klog.V(2).Infof("Workspace %v has been deleted", workspaceName)
return nil
}
return err
}
//Maybe some ns not labeled
if !hadNamespaceLabel(ns) {
ns.Labels[constants.NamespaceLabelKey] = ns.Name
_, err := c.client.CoreV1().Namespaces().Update(ns)
if err != nil {
//Just log, label can also be added by namespace controller
klog.Errorf("cannot label namespace %s", ns.Name)
}
}
matchWorkspace := false
delete := false
if isNetworkIsolateEnabled(ns) {
matchWorkspace = false
} else if wksp.Spec.NetworkIsolation {
matchWorkspace = true
} else {
delete = true
}
policy := generateNSNP(workspaceName, ns.Name, matchWorkspace)
ruleDNS, err := generateDNSRule([]string{DNSLocalIP})
if err != nil {
return err
}
policy.Spec.Egress = append(policy.Spec.Egress, ruleDNS)
ruleDNSService, err := c.generateDNSServiceRule()
if err == nil {
policy.Spec.Egress = append(policy.Spec.Egress, ruleDNSService)
} else {
klog.Warningf("Cannot handle service %s or %s", DNSServiceName, DNSServiceCoreDNS)
}
ruleNode, err := c.generateNodeRule()
if err != nil {
return err
}
policy.Spec.Ingress = append(policy.Spec.Ingress, ruleNode)
if delete {
c.provider.Delete(c.provider.GetKey(AnnotationNPNAME, ns.Name))
//delete all namespace np when networkisolate not active
if c.ksclient.NamespaceNetworkPolicies(ns.Name).DeleteCollection(nil, typev1.ListOptions{}) != nil {
klog.Errorf("Error when delete all nsnps in namespace %s", ns.Name)
}
} else {
err = c.provider.Set(policy)
if err != nil {
klog.Errorf("Error while converting %#v to provider's network policy.", policy)
return err
}
}
klog.V(2).Info("Started workers")
<-stopCh
log.V(2).Info("Shutting down workers")
return nil
}
func (c *controller) enqueueNSNP(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) runWorker() {
for c.processNextWorkItem() {
func (c *NSNetworkPolicyController) nsWorker() {
for c.processNsWorkItem() {
}
}
func (c *controller) processNextWorkItem() bool {
obj, shutdown := c.workqueue.Get()
if shutdown {
func (c *NSNetworkPolicyController) processNsWorkItem() bool {
key, quit := c.nsQueue.Get()
if quit {
return false
}
defer c.nsQueue.Done(key)
// 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", key)
return nil
}(obj)
if err != nil {
utilruntime.HandleError(err)
return true
if err := c.syncNs(key.(string)); err != nil {
klog.Errorf("Error when syncns %s", err)
}
return true
}
func (c *NSNetworkPolicyController) nsnpEnqueue(obj interface{}) {
nsnp := obj.(*v1alpha1.NamespaceNetworkPolicy)
key, err := cache.MetaNamespaceKeyFunc(nsnp)
if err != nil {
uruntime.HandleError(fmt.Errorf("get namespace network policy key %s failed", nsnp.Name))
return
}
c.nsnpQueue.Add(key)
}
func (c *NSNetworkPolicyController) syncNSNP(key string) error {
namespace, name, err := cache.SplitMetaNamespaceKey(key)
if err != nil {
klog.Errorf("Not a valid controller key %s, %#v", key, err)
return err
}
nsnp, err := c.informer.Lister().NamespaceNetworkPolicies(namespace).Get(name)
if err != nil {
if errors.IsNotFound(err) {
klog.V(4).Infof("NSNP %v has been deleted", key)
c.provider.Delete(c.provider.GetKey(name, namespace))
return nil
}
return err
}
np, err := c.convertToK8sNP(nsnp)
if err != nil {
klog.Errorf("Error while convert nsnp to k8snp: %s", err)
return err
}
err = c.provider.Set(np)
if err != nil {
return err
}
return nil
}
func (c *NSNetworkPolicyController) nsNPWorker() {
for c.processNSNPWorkItem() {
}
}
func (c *NSNetworkPolicyController) processNSNPWorkItem() bool {
key, quit := c.nsnpQueue.Get()
if quit {
return false
}
defer c.nsnpQueue.Done(key)
c.syncNSNP(key.(string))
return true
}
// NewnamespacenpController returns a controller which manages NSNSP objects.
func NewNSNetworkPolicyController(
client kubernetes.Interface,
ksclient ksnetclient.NetworkV1alpha1Interface,
nsnpInformer nspolicy.NamespaceNetworkPolicyInformer,
serviceInformer v1.ServiceInformer,
nodeInformer v1.NodeInformer,
workspaceInformer workspace.WorkspaceInformer,
namespaceInformer v1.NamespaceInformer,
policyProvider provider.NsNetworkPolicyProvider) *NSNetworkPolicyController {
controller := &NSNetworkPolicyController{
client: client,
ksclient: ksclient,
informer: nsnpInformer,
informerSynced: nsnpInformer.Informer().HasSynced,
serviceInformer: serviceInformer,
serviceInformerSynced: serviceInformer.Informer().HasSynced,
nodeInformer: nodeInformer,
nodeInformerSynced: nodeInformer.Informer().HasSynced,
workspaceInformer: workspaceInformer,
workspaceInformerSynced: workspaceInformer.Informer().HasSynced,
namespaceInformer: namespaceInformer,
namespaceInformerSynced: namespaceInformer.Informer().HasSynced,
provider: policyProvider,
nsQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "namespace"),
nsnpQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "namespacenp"),
}
workspaceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: controller.addWorkspace,
UpdateFunc: func(oldObj, newObj interface{}) {
old := oldObj.(*workspacev1alpha1.Workspace)
new := oldObj.(*workspacev1alpha1.Workspace)
if old.Spec.NetworkIsolation == new.Spec.NetworkIsolation {
return
}
controller.addWorkspace(newObj)
},
})
namespaceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: controller.addNamespace,
UpdateFunc: func(oldObj interface{}, newObj interface{}) {
old := oldObj.(*corev1.Namespace)
new := oldObj.(*corev1.Namespace)
if old.Annotations[NamespaceNPAnnotationKey] == new.Annotations[NamespaceNPAnnotationKey] {
return
}
controller.addNamespace(newObj)
},
})
nsnpInformer.Informer().AddEventHandlerWithResyncPeriod(cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
klog.V(4).Infof("Got ADD event for NSNSP: %#v", obj)
controller.nsnpEnqueue(obj)
},
UpdateFunc: func(oldObj interface{}, newObj interface{}) {
klog.V(4).Info("Got UPDATE event for NSNSP.")
klog.V(4).Infof("Old object: \n%#v\n", oldObj)
klog.V(4).Infof("New object: \n%#v\n", newObj)
controller.nsnpEnqueue(newObj)
},
DeleteFunc: func(obj interface{}) {
klog.V(4).Infof("Got DELETE event for NSNP: %#v", obj)
controller.nsnpEnqueue(obj)
},
}, defaultSleepDuration)
return controller
}
func (c *NSNetworkPolicyController) Start(stopCh <-chan struct{}) error {
return c.Run(defaultThread, defaultSync, stopCh)
}
// Run starts the controller.
func (c *NSNetworkPolicyController) Run(threadiness int, reconcilerPeriod string, stopCh <-chan struct{}) error {
defer uruntime.HandleCrash()
defer c.nsQueue.ShutDown()
defer c.nsnpQueue.ShutDown()
klog.Info("Waiting to sync with Kubernetes API (NSNP)")
if ok := cache.WaitForCacheSync(stopCh, c.informerSynced, c.serviceInformerSynced, c.workspaceInformerSynced, c.namespaceInformerSynced, c.nodeInformerSynced); !ok {
return fmt.Errorf("Failed to wait for caches to sync")
}
klog.Info("Finished syncing with Kubernetes API (NSNP)")
// Start a number of worker threads to read from the queue. Each worker
// will pull keys off the resource cache event queue and sync them to the
// K8s datastore.
for i := 0; i < threadiness; i++ {
go wait.Until(c.nsWorker, time.Second, stopCh)
go wait.Until(c.nsNPWorker, time.Second, stopCh)
}
//Work to sync K8s NetworkPolicy
go c.provider.Start(stopCh)
klog.Info("NSNP controller is now running")
<-stopCh
klog.Info("Stopping NSNP controller")
return nil
}

View File

@@ -11,8 +11,7 @@ import (
func TestNsnetworkpolicy(t *testing.T) {
klog.InitFlags(nil)
flag.Set("logtostderr", "false")
flag.Set("alsologtostderr", "false")
flag.Set("logtostderr", "true")
flag.Set("v", "4")
flag.Parse()
klog.SetOutput(GinkgoWriter)

View File

@@ -1,90 +1,337 @@
package nsnetworkpolicy
import (
"fmt"
"reflect"
"strings"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/record"
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1"
nsnplister "kubesphere.io/kubesphere/pkg/client/listers/network/v1alpha1"
"kubesphere.io/kubesphere/pkg/controller/network/controllerapi"
corev1 "k8s.io/api/core/v1"
netv1 "k8s.io/api/networking/v1"
"k8s.io/apimachinery/pkg/util/yaml"
kubeinformers "k8s.io/client-go/informers"
informerv1 "k8s.io/client-go/informers/core/v1"
kubefake "k8s.io/client-go/kubernetes/fake"
"k8s.io/klog"
netv1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1"
wkspv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
ksfake "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
nsnppolicyinformer "kubesphere.io/kubesphere/pkg/client/informers/externalversions/network/v1alpha1"
workspaceinformer "kubesphere.io/kubesphere/pkg/client/informers/externalversions/tenant/v1alpha1"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/controller/network/provider"
controllertesting "kubesphere.io/kubesphere/pkg/controller/network/testing"
)
var (
fakeControllerBuilder *controllertesting.FakeControllerBuilder
c controllerapi.Controller
stopCh chan struct{}
calicoProvider *provider.FakeCalicoNetworkProvider
nsnpLister nsnplister.NamespaceNetworkPolicyLister
c *NSNetworkPolicyController
stopCh chan struct{}
nsnpInformer nsnppolicyinformer.NamespaceNetworkPolicyInformer
serviceInformer informerv1.ServiceInformer
workspaceInformer workspaceinformer.WorkspaceInformer
namespaceInformer informerv1.NamespaceInformer
alwaysReady = func() bool { return true }
)
const (
workspaceNP = `
apiVersion: "networking.k8s.io/v1"
kind: "NetworkPolicy"
metadata:
name: networkisolate
namespace: %s
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
%s: %s
Egress:
- To:
- namespaceSelector:
matchLabels:
%s: %s
policyTypes:
- Ingress
- Egress`
serviceTmp = `
apiVersion: v1
kind: Service
metadata:
name: myservice
namespace: testns
spec:
clusterIP: 10.0.0.1
selector:
app: mylbapp
ports:
- protocol: TCP
port: 80
targetPort: 9376
`
workspaceTmp = `
apiVersion: tenant.kubesphere.io/v1alpha1
kind: Workspace
metadata:
annotations:
kubesphere.io/creator: admin
name: testworkspace
spec:
manager: admin
networkIsolation: true
status: {}
`
nsTmp = `
apiVersion: v1
kind: Namespace
metadata:
labels:
kubesphere.io/workspace: testworkspace
name: testns
spec:
finalizers:
- kubernetes
`
)
func StringToObject(data string, obj interface{}) error {
reader := strings.NewReader(data)
return yaml.NewYAMLOrJSONDecoder(reader, 10).Decode(obj)
}
var _ = Describe("Nsnetworkpolicy", func() {
BeforeEach(func() {
fakeControllerBuilder = controllertesting.NewFakeControllerBuilder()
stopCh = make(chan struct{})
informer, _ := fakeControllerBuilder.NewControllerInformer()
calicoProvider = provider.NewFakeCalicoNetworkProvider()
c = NewController(fakeControllerBuilder.KubeClient, fakeControllerBuilder.KsClient, informer.Network().V1alpha1().NamespaceNetworkPolicies(), calicoProvider)
go informer.Network().V1alpha1().NamespaceNetworkPolicies().Informer().Run(stopCh)
originalController := c.(*controller)
originalController.recorder = &record.FakeRecorder{}
go c.Run(1, stopCh)
nsnpLister = informer.Network().V1alpha1().NamespaceNetworkPolicies().Lister()
calicoProvider := provider.NewFakeNetworkProvider()
kubeClient := kubefake.NewSimpleClientset()
ksClient := ksfake.NewSimpleClientset()
kubeInformer := kubeinformers.NewSharedInformerFactory(kubeClient, 0)
ksInformer := ksinformers.NewSharedInformerFactory(ksClient, 0)
nsnpInformer := ksInformer.Network().V1alpha1().NamespaceNetworkPolicies()
serviceInformer := kubeInformer.Core().V1().Services()
nodeInforemer := kubeInformer.Core().V1().Nodes()
workspaceInformer := ksInformer.Tenant().V1alpha1().Workspaces()
namespaceInformer := kubeInformer.Core().V1().Namespaces()
c = NewNSNetworkPolicyController(kubeClient, ksClient.NetworkV1alpha1(), nsnpInformer, serviceInformer, nodeInforemer, workspaceInformer, namespaceInformer, calicoProvider)
serviceObj := &corev1.Service{}
Expect(StringToObject(serviceTmp, serviceObj)).ShouldNot(HaveOccurred())
Expect(serviceInformer.Informer().GetIndexer().Add(serviceObj)).ShouldNot(HaveOccurred())
nsObj := &corev1.Namespace{}
Expect(StringToObject(nsTmp, nsObj)).ShouldNot(HaveOccurred())
namespaceInformer.Informer().GetIndexer().Add(nsObj)
workspaceObj := &wkspv1alpha1.Workspace{}
Expect(StringToObject(workspaceTmp, workspaceObj)).ShouldNot(HaveOccurred())
workspaceInformer.Informer().GetIndexer().Add(workspaceObj)
c.namespaceInformerSynced = alwaysReady
c.serviceInformerSynced = alwaysReady
c.workspaceInformerSynced = alwaysReady
c.informerSynced = alwaysReady
go c.Start(stopCh)
})
It("Should create a new calico object", func() {
objSrt := `{
"apiVersion": "network.kubesphere.io/v1alpha1",
"kind": "NetworkPolicy",
"metadata": {
"name": "allow-tcp-6379",
"namespace": "production"
},
"spec": {
"selector": "color == 'red'",
"ingress": [
{
"action": "Allow",
"protocol": "TCP",
"source": {
"selector": "color == 'blue'"
},
"destination": {
"ports": [
6379
]
}
}
]
}
}`
obj := &v1alpha1.NamespaceNetworkPolicy{}
Expect(controllertesting.StringToObject(objSrt, obj)).ShouldNot(HaveOccurred())
_, err := fakeControllerBuilder.KsClient.NetworkV1alpha1().NamespaceNetworkPolicies(obj.Namespace).Create(obj)
It("Should create ns networkisolate np correctly in workspace", func() {
objSrt := fmt.Sprintf(workspaceNP, "testns", constants.WorkspaceLabelKey, "testworkspace", constants.WorkspaceLabelKey, "testworkspace")
obj := &netv1.NetworkPolicy{}
Expect(StringToObject(objSrt, obj)).ShouldNot(HaveOccurred())
policy := generateNSNP("testworkspace", "testns", true)
Expect(reflect.DeepEqual(obj.Spec, policy.Spec)).To(BeTrue())
})
It("Should create ns networkisolate np correctly in ns", func() {
objSrt := fmt.Sprintf(workspaceNP, "testns", constants.NamespaceLabelKey, "testns", constants.NamespaceLabelKey, "testns")
obj := &netv1.NetworkPolicy{}
Expect(StringToObject(objSrt, obj)).ShouldNot(HaveOccurred())
policy := generateNSNP("testworkspace", "testns", false)
Expect(reflect.DeepEqual(obj.Spec, policy.Spec)).To(BeTrue())
})
It("test func convertToK8sNP", func() {
objSrt := `
apiVersion: network.kubesphere.io/v1alpha1
kind: NamespaceNetworkPolicy
metadata:
name: namespaceIPblockNP
namespace: testns
spec:
ingress:
- from:
- ipBlock:
cidr: 172.0.0.1/16
ports:
- protocol: TCP
port: 80
`
obj := &netv1alpha1.NamespaceNetworkPolicy{}
Expect(StringToObject(objSrt, obj)).ShouldNot(HaveOccurred())
policy, err := c.convertToK8sNP(obj)
objSrt = `
apiVersion: "networking.k8s.io/v1"
kind: "NetworkPolicy"
metadata:
name: IPblockNP
namespace: testns
spec:
ingress:
- from:
- ipBlock:
cidr: 172.0.0.1/16
ports:
- protocol: TCP
port: 80
policyTypes:
- Ingress
`
obj2 := &netv1.NetworkPolicy{}
Expect(StringToObject(objSrt, obj2)).ShouldNot(HaveOccurred())
Expect(err).ShouldNot(HaveOccurred())
Eventually(func() bool {
exist, _ := calicoProvider.CheckExist(obj)
return exist
}).Should(BeTrue())
obj, _ = fakeControllerBuilder.KsClient.NetworkV1alpha1().NamespaceNetworkPolicies(obj.Namespace).Get(obj.Name, metav1.GetOptions{})
Expect(obj.Finalizers).To(HaveLen(1))
// TestUpdate
newStr := "color == 'green'"
obj.Spec.Selector = newStr
_, err = fakeControllerBuilder.KsClient.NetworkV1alpha1().NamespaceNetworkPolicies(obj.Namespace).Update(obj)
Expect(reflect.DeepEqual(obj2.Spec, policy.Spec)).To(BeTrue())
})
It("test func convertToK8sNP with namespace", func() {
objSrt := `
apiVersion: network.kubesphere.io/v1alpha1
kind: NamespaceNetworkPolicy
metadata:
name: testnamespace
namespace: testns2
spec:
ingress:
- from:
- namespace:
name: testns
`
obj := &netv1alpha1.NamespaceNetworkPolicy{}
Expect(StringToObject(objSrt, obj)).ShouldNot(HaveOccurred())
np, err := c.convertToK8sNP(obj)
Expect(err).ShouldNot(HaveOccurred())
Eventually(func() string {
o, err := calicoProvider.Get(obj)
if err != nil {
return err.Error()
}
n := o.(*v1alpha1.NamespaceNetworkPolicy)
return n.Spec.Selector
}).Should(Equal(newStr))
// TestDelete
Expect(fakeControllerBuilder.KsClient.NetworkV1alpha1().NamespaceNetworkPolicies(obj.Namespace).Delete(obj.Name, &metav1.DeleteOptions{})).ShouldNot(HaveOccurred())
objTmp := `
apiVersion: "networking.k8s.io/v1"
kind: "NetworkPolicy"
metadata:
name: testnamespace
namespace: testns2
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
%s: %s
policyTypes:
- Ingress`
objSrt = fmt.Sprintf(objTmp, constants.NamespaceLabelKey, "testns")
obj2 := &netv1.NetworkPolicy{}
Expect(StringToObject(objSrt, obj2)).ShouldNot(HaveOccurred())
Expect(reflect.DeepEqual(np.Spec, obj2.Spec)).To(BeTrue())
})
It("test func convertToK8sNP with service ingress", func() {
objSrt := `
apiVersion: network.kubesphere.io/v1alpha1
kind: NamespaceNetworkPolicy
metadata:
name: testnamespace
namespace: testns2
spec:
ingress:
- from:
- service:
name: myservice
namespace: testns
`
obj := &netv1alpha1.NamespaceNetworkPolicy{}
Expect(StringToObject(objSrt, obj)).ShouldNot(HaveOccurred())
np, err := c.convertToK8sNP(obj)
Expect(err).ShouldNot(HaveOccurred())
objSrt = `
apiVersion: "networking.k8s.io/v1"
kind: NetworkPolicy
metadata:
name: networkisolate
namespace: testns
spec:
podSelector: {}
ingress:
- from:
- podSelector:
matchLabels:
app: mylbapp
namespaceSelector:
matchLabels:
kubesphere.io/namespace: testns
policyTypes:
- Ingress
`
obj2 := &netv1.NetworkPolicy{}
Expect(StringToObject(objSrt, obj2)).ShouldNot(HaveOccurred())
klog.Errorf("\n%v\n%v\n", np.Spec, obj2.Spec)
Expect(reflect.DeepEqual(np.Spec, obj2.Spec)).To(BeTrue())
})
It("test func convertToK8sNP with service egress", func() {
objSrt := `
apiVersion: network.kubesphere.io/v1alpha1
kind: NamespaceNetworkPolicy
metadata:
name: testnamespace
namespace: testns2
spec:
egress:
- To:
- service:
name: myservice
namespace: testns
`
obj := &netv1alpha1.NamespaceNetworkPolicy{}
Expect(StringToObject(objSrt, obj)).ShouldNot(HaveOccurred())
np, err := c.convertToK8sNP(obj)
Expect(err).ShouldNot(HaveOccurred())
objSrt = `
apiVersion: "networking.k8s.io/v1"
kind: NetworkPolicy
metadata:
name: networkisolate
namespace: testns
spec:
podSelector: {}
egress:
- to:
- podSelector:
matchLabels:
app: mylbapp
namespaceSelector:
matchLabels:
kubesphere.io/namespace: testns
ports:
- protocol: TCP
port: 80
policyTypes:
- Egress
`
obj2 := &netv1.NetworkPolicy{}
Expect(StringToObject(objSrt, obj2)).ShouldNot(HaveOccurred())
klog.Errorf("\n%v\n%v\n", np.Spec, obj2.Spec)
Expect(reflect.DeepEqual(np.Spec, obj2.Spec)).To(BeTrue())
})
AfterEach(func() {

View File

@@ -1,119 +0,0 @@
package nsnetworkpolicy
import (
"github.com/go-logr/logr"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/retry"
"kubesphere.io/kubesphere/pkg/apis/network/v1alpha1"
"kubesphere.io/kubesphere/pkg/controller/network/utils"
)
const (
controllerFinalizier = "nsnp.finalizers.networking.kubesphere.io"
)
var clog logr.Logger
func (c *controller) reconcile(key string) error {
namespace, name, err := cache.SplitMetaNamespaceKey(key)
if err != nil {
return err
}
clog = log.WithValues("name", name, "namespace", namespace)
clog.V(1).Info("---------Begin to reconcile--------")
defer clog.V(1).Info("---------Reconcile done--------")
obj, err := c.nsnpLister.NamespaceNetworkPolicies(namespace).Get(name)
if err != nil {
if errors.IsNotFound(err) {
clog.V(2).Info("Object is removed")
return nil
}
clog.Error(err, "Failed to get resource")
return err
}
stop, err := c.addOrRemoveFinalizer(obj)
if err != nil {
return err
}
if stop {
return nil
}
clog.V(2).Info("Check if we need a create or update")
ok, err := c.nsNetworkPolicyProvider.CheckExist(obj)
if err != nil {
clog.Error(err, "Failed to check exist of network policy")
return err
}
if !ok {
clog.V(1).Info("Create a new object in backend")
err = c.nsNetworkPolicyProvider.Add(obj)
if err != nil {
clog.Error(err, "Failed to create np")
return err
}
return nil
}
needUpdate, err := c.nsNetworkPolicyProvider.NeedUpdate(obj)
if err != nil {
clog.Error(err, "Failed to check if object need a update")
return err
}
if needUpdate {
clog.V(1).Info("Update object in backend")
err = c.nsNetworkPolicyProvider.Update(obj)
if err != nil {
clog.Error(err, "Failed to update object")
return err
}
}
return nil
}
func (c *controller) addOrRemoveFinalizer(obj *v1alpha1.NamespaceNetworkPolicy) (bool, error) {
if obj.ObjectMeta.DeletionTimestamp.IsZero() {
if !utils.ContainsString(obj.ObjectMeta.Finalizers, controllerFinalizier) {
clog.V(2).Info("Detect no finalizer")
obj.ObjectMeta.Finalizers = append(obj.ObjectMeta.Finalizers, controllerFinalizier)
err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
_, err := c.kubesphereClientset.NetworkV1alpha1().NamespaceNetworkPolicies(obj.Namespace).Update(obj)
return err
})
if err != nil {
clog.Error(err, "Failed to add finalizer")
return false, err
}
return false, nil
}
} else {
// The object is being deleted
if utils.ContainsString(obj.ObjectMeta.Finalizers, controllerFinalizier) {
// our finalizer is present, so lets handle any external dependency
if err := c.deleteProviderNSNP(obj); err != nil {
// if fail to delete the external dependency here, return with error
// so that it can be retried
return false, err
}
clog.V(2).Info("Removing finalizer")
// remove our finalizer from the list and update it.
obj.ObjectMeta.Finalizers = utils.RemoveString(obj.ObjectMeta.Finalizers, controllerFinalizier)
err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
_, err := c.kubesphereClientset.NetworkV1alpha1().NamespaceNetworkPolicies(obj.Namespace).Update(obj)
return err
})
if err != nil {
clog.Error(err, "Failed to remove finalizer")
return false, err
}
return true, nil
}
}
return false, nil
}
// deleteProviderNSNP delete network policy in the backend
func (c *controller) deleteProviderNSNP(obj *v1alpha1.NamespaceNetworkPolicy) error {
clog.V(2).Info("Deleting backend network policy")
return c.nsNetworkPolicyProvider.Delete(obj)
}

View File

@@ -0,0 +1,38 @@
package nsnetworkpolicy
import (
"context"
"fmt"
"net/http"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)
// +kubebuilder:webhook:path=/validate-service-nsnp-kubesphere-io-v1alpha1-network,name=validate-v1-service,mutating=false,failurePolicy=fail,groups="",resources=services,verbs=create;update,versions=v1
// serviceValidator validates service
type ServiceValidator struct {
decoder *admission.Decoder
}
// Service must hash label, becasue nsnp will use it
func (v *ServiceValidator) Handle(ctx context.Context, req admission.Request) admission.Response {
service := &corev1.Service{}
err := v.decoder.Decode(req, service)
if err != nil {
return admission.Errored(http.StatusBadRequest, err)
}
if service.Spec.Selector == nil {
return admission.Denied(fmt.Sprintf("missing label"))
}
return admission.Allowed("")
}
func (a *ServiceValidator) InjectDecoder(d *admission.Decoder) error {
a.decoder = d
return nil
}

View File

@@ -1,3 +0,0 @@
package provider
// +kubebuilder:rbac:groups="crd.projectcalico.org",resources=globalfelixconfigs;felixconfigurations;ippools;ipamblocks;globalnetworkpolicies;globalnetworksets;networkpolicies;networksets;clusterinformations;hostendpoints,verbs=get;list;watch;create;patch;update;delete

View File

@@ -0,0 +1,49 @@
package provider
import (
"fmt"
"github.com/projectcalico/kube-controllers/pkg/converter"
api "github.com/projectcalico/libcalico-go/lib/apis/v3"
constants "github.com/projectcalico/libcalico-go/lib/backend/k8s/conversion"
v1 "k8s.io/api/networking/v1"
)
func NewFakeNetworkProvider() *FakeNetworkProvider {
f := new(FakeNetworkProvider)
f.NSNPData = make(map[string]*api.NetworkPolicy)
f.policyConverter = converter.NewPolicyConverter()
return f
}
type FakeNetworkProvider struct {
NSNPData map[string]*api.NetworkPolicy
policyConverter converter.Converter
}
func (f *FakeNetworkProvider) Delete(key string) {
delete(f.NSNPData, key)
}
func (f *FakeNetworkProvider) Start(stopCh <-chan struct{}) {
}
func (f *FakeNetworkProvider) Set(np *v1.NetworkPolicy) error {
policy, err := f.policyConverter.Convert(np)
if err != nil {
return err
}
// Add to cache.
k := f.policyConverter.GetKey(policy)
tmp := policy.(api.NetworkPolicy)
f.NSNPData[k] = &tmp
return nil
}
func (f *FakeNetworkProvider) GetKey(name, nsname string) string {
policyName := fmt.Sprintf(constants.K8sNetworkPolicyNamePrefix + name)
return fmt.Sprintf("%s/%s", nsname, policyName)
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,250 @@
package provider
import (
"context"
"fmt"
"reflect"
"strings"
"sync"
"time"
rcache "github.com/projectcalico/kube-controllers/pkg/cache"
netv1 "k8s.io/api/networking/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
uruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
informerv1 "k8s.io/client-go/informers/networking/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
"k8s.io/klog"
)
const (
defaultSyncTime = 5 * time.Minute
)
func (c *k8sPolicyController) GetKey(name, nsname string) string {
return fmt.Sprintf("%s/%s", nsname, name)
}
func getkey(key string) (string, string) {
strs := strings.Split(key, "/")
return strs[0], strs[1]
}
// policyController implements the Controller interface for managing Kubernetes network policies
// and syncing them to the k8s datastore as NetworkPolicies.
type k8sPolicyController struct {
client kubernetes.Interface
informer informerv1.NetworkPolicyInformer
ctx context.Context
resourceCache rcache.ResourceCache
hasSynced cache.InformerSynced
}
func (c *k8sPolicyController) Start(stopCh <-chan struct{}) {
c.run(5, "5m", stopCh)
}
func (c *k8sPolicyController) Set(np *netv1.NetworkPolicy) error {
klog.V(4).Infof("Set NetworkPolicy %s/%s %+v", np.Namespace, np.Name, np)
// Add to cache.
k := c.GetKey(np.Name, np.Namespace)
c.resourceCache.Set(k, *np)
return nil
}
func (c *k8sPolicyController) Delete(key string) {
klog.V(4).Infof("Delete NetworkPolicy %s", key)
c.resourceCache.Delete(key)
}
// Run starts the controller.
func (c *k8sPolicyController) run(threadiness int, reconcilerPeriod string, stopCh <-chan struct{}) {
defer uruntime.HandleCrash()
// Let the workers stop when we are done
workqueue := c.resourceCache.GetQueue()
defer workqueue.ShutDown()
// Wait until we are in sync with the Kubernetes API before starting the
// resource cache.
klog.Info("Waiting to sync with Kubernetes API (NetworkPolicy)")
if ok := cache.WaitForCacheSync(stopCh, c.hasSynced); !ok {
}
klog.Infof("Finished syncing with Kubernetes API (NetworkPolicy)")
// Start the resource cache - this will trigger the queueing of any keys
// that are out of sync onto the resource cache event queue.
c.resourceCache.Run(reconcilerPeriod)
// Start a number of worker threads to read from the queue. Each worker
// will pull keys off the resource cache event queue and sync them to the
// k8s datastore.
for i := 0; i < threadiness; i++ {
go wait.Until(c.runWorker, time.Second, stopCh)
}
klog.Info("NetworkPolicy controller is now running")
<-stopCh
klog.Info("Stopping NetworkPolicy controller")
}
func (c *k8sPolicyController) runWorker() {
for c.processNextItem() {
}
}
// processNextItem waits for an event on the output queue from the resource cache and syncs
// any received keys to the datastore.
func (c *k8sPolicyController) processNextItem() bool {
// Wait until there is a new item in the work queue.
workqueue := c.resourceCache.GetQueue()
key, quit := workqueue.Get()
if quit {
return false
}
// Sync the object to the k8s datastore.
if err := c.syncToDatastore(key.(string)); err != nil {
c.handleErr(err, key.(string))
}
// Indicate that we're done processing this key, allowing for safe parallel processing such that
// two objects with the same key are never processed in parallel.
workqueue.Done(key)
return true
}
// syncToDatastore syncs the given update to the k8s datastore. The provided key can be used to
// find the corresponding resource within the resource cache. If the resource for the provided key
// exists in the cache, then the value should be written to the datastore. If it does not exist
// in the cache, then it should be deleted from the datastore.
func (c *k8sPolicyController) syncToDatastore(key string) error {
// Check if it exists in the controller's cache.
obj, exists := c.resourceCache.Get(key)
if !exists {
// The object no longer exists - delete from the datastore.
klog.Infof("Deleting NetworkPolicy %s from k8s datastore", key)
ns, name := getkey(key)
err := c.client.NetworkingV1().NetworkPolicies(ns).Delete(name, nil)
if errors.IsNotFound(err) {
return nil
}
return err
} else {
// The object exists - update the datastore to reflect.
klog.Infof("Create/Update NetworkPolicy %s in k8s datastore", key)
p := obj.(netv1.NetworkPolicy)
// Lookup to see if this object already exists in the datastore.
gp, err := c.informer.Lister().NetworkPolicies(p.Namespace).Get(p.Name)
if err != nil {
if !errors.IsNotFound(err) {
klog.Warningf("Failed to get NetworkPolicy %s from datastore", key)
return err
}
// Doesn't exist - create it.
_, err := c.client.NetworkingV1().NetworkPolicies(p.Namespace).Create(&p)
if err != nil {
klog.Warningf("Failed to create NetworkPolicy %s", key)
return err
}
klog.Infof("Successfully created NetworkPolicy %s", key)
return nil
}
klog.V(4).Infof("New NetworkPolicy %s/%s %+v\n", p.Namespace, p.Name, p.Spec)
klog.V(4).Infof("Old NetworkPolicy %s/%s %+v\n", gp.Namespace, gp.Name, gp.Spec)
// The policy already exists, update it and write it back to the datastore.
gp.Spec = p.Spec
_, err = c.client.NetworkingV1().NetworkPolicies(p.Namespace).Update(gp)
if err != nil {
klog.Warningf("Failed to update NetworkPolicy %s", key)
return err
}
klog.Infof("Successfully updated NetworkPolicy %s", key)
return nil
}
}
// handleErr handles errors which occur while processing a key received from the resource cache.
// For a given error, we will re-queue the key in order to retry the datastore sync up to 5 times,
// at which point the update is dropped.
func (c *k8sPolicyController) handleErr(err error, key string) {
workqueue := c.resourceCache.GetQueue()
if err == nil {
// Forget about the #AddRateLimited history of the key on every successful synchronization.
// This ensures that future processing of updates for this key is not delayed because of
// an outdated error history.
workqueue.Forget(key)
return
}
// This controller retries 5 times if something goes wrong. After that, it stops trying.
if workqueue.NumRequeues(key) < 5 {
// Re-enqueue the key rate limited. Based on the rate limiter on the
// queue and the re-enqueue history, the key will be processed later again.
klog.Errorf("Error syncing NetworkPolicy %v: %v", key, err)
workqueue.AddRateLimited(key)
return
}
workqueue.Forget(key)
// Report to an external entity that, even after several retries, we could not successfully process this key
uruntime.HandleError(err)
klog.Errorf("Dropping NetworkPolicy %q out of the queue: %v", key, err)
}
//NewNsNetworkPolicyProvider sync k8s NetworkPolicy
func NewNsNetworkPolicyProvider(client kubernetes.Interface, npInformer informerv1.NetworkPolicyInformer) (NsNetworkPolicyProvider, error) {
var once sync.Once
c := &k8sPolicyController{
client: client,
informer: npInformer,
ctx: context.Background(),
hasSynced: npInformer.Informer().HasSynced,
}
// Function returns map of policyName:policy stored by policy controller
// in datastore.
listFunc := func() (map[string]interface{}, error) {
//Wait cache be set by NSNP Controller, otherwise NetworkPolicy will be delete
//by mistake
once.Do(func() {
time.Sleep(defaultSyncTime)
})
// Get all policies from datastore
//TODO filter np not belong to kubesphere
policies, err := npInformer.Lister().List(labels.Everything())
if err != nil {
return nil, err
}
// Filter in only objects that are written by policy controller.
m := make(map[string]interface{})
for _, policy := range policies {
policy.ObjectMeta = metav1.ObjectMeta{Name: policy.Name, Namespace: policy.Namespace}
k := c.GetKey(policy.Name, policy.Namespace)
m[k] = *policy
}
klog.Infof("Found %d policies in k8s datastore:", len(m))
return m, nil
}
cacheArgs := rcache.ResourceCacheArgs{
ListFunc: listFunc,
ObjectType: reflect.TypeOf(netv1.NetworkPolicy{}),
}
c.resourceCache = rcache.NewResourceCache(cacheArgs)
return c, nil
}

View File

@@ -1,80 +0,0 @@
package runoption
import (
"time"
"github.com/projectcalico/libcalico-go/lib/apiconfig"
"github.com/projectcalico/libcalico-go/lib/clientv3"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/client/clientset/versioned"
ksinformer "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/controller/network/nsnetworkpolicy"
"kubesphere.io/kubesphere/pkg/controller/network/provider"
)
const (
certPath = "/calicocerts"
KubernetesDataStore = "k8s"
EtcdDataStore = "etcd"
)
type RunOption struct {
ProviderName string
DataStoreType string
EtcdEndpoints string
AllowInsecureEtcd bool
}
func (r RunOption) Run() error {
klog.V(1).Info("Check config")
if err := r.check(); err != nil {
return err
}
klog.V(1).Info("Preparing kubernetes client")
config, err := rest.InClusterConfig()
if err != nil {
panic(err.Error())
}
// creates the clientset
k8sClientset := kubernetes.NewForConfigOrDie(config)
ksClientset := versioned.NewForConfigOrDie(config)
informer := ksinformer.NewSharedInformerFactory(ksClientset, time.Minute*10)
klog.V(1).Info("Kubernetes client initialized successfully")
var npProvider provider.NsNetworkPolicyProvider
if r.ProviderName == "calico" {
klog.V(1).Info("Preparing calico client")
config := apiconfig.NewCalicoAPIConfig()
config.Spec.EtcdEndpoints = r.EtcdEndpoints
if !r.AllowInsecureEtcd {
config.Spec.EtcdKeyFile = certPath + "/etcd-key"
config.Spec.EtcdCertFile = certPath + "/etcd-cert"
config.Spec.EtcdCACertFile = certPath + "/etcd-ca"
}
if r.DataStoreType == KubernetesDataStore {
config.Spec.DatastoreType = apiconfig.Kubernetes
} else {
config.Spec.DatastoreType = apiconfig.EtcdV3
}
client, err := clientv3.New(*config)
if err != nil {
klog.Fatal("Failed to initialize calico client", err)
}
npProvider = provider.NewCalicoNetworkProvider(client.NetworkPolicies())
klog.V(1).Info("Calico client initialized successfully")
}
//TODO: support no-calico cni
c := nsnetworkpolicy.NewController(k8sClientset, ksClientset, informer.Network().V1alpha1().NamespaceNetworkPolicies(), npProvider)
stop := make(chan struct{})
klog.V(1).Infof("Starting controller")
go informer.Network().V1alpha1().NamespaceNetworkPolicies().Informer().Run(stop)
return c.Run(1, stop)
}
func (r RunOption) check() error {
return nil
}

View File

@@ -1,38 +0,0 @@
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
}

View File

@@ -1,12 +0,0 @@
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)
}

View File

@@ -1,22 +0,0 @@
package utils
// ContainsString report if s is in a slice
func ContainsString(slice []string, s string) bool {
for _, item := range slice {
if item == s {
return true
}
}
return false
}
// RemoveString remove s from slice if exists
func RemoveString(slice []string, s string) (result []string) {
for _, item := range slice {
if item == s {
continue
}
result = append(result, item)
}
return
}

View File

@@ -1,280 +0,0 @@
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"
"kubesphere.io/kubesphere/pkg/controller/network/controllerapi"
)
const controllerAgentName = "wsnp-controller"
var (
log = klogr.New().WithName("Controller").WithValues(controllerAgentName)
errCount = 0
)
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) controllerapi.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++
}

View File

@@ -1,203 +0,0 @@
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
}

View File

@@ -1,21 +0,0 @@
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")
}

View File

@@ -1,242 +0,0 @@
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"
"kubesphere.io/kubesphere/pkg/controller/network/controllerapi"
controllertesting "kubesphere.io/kubesphere/pkg/controller/network/testing"
)
var (
fakeControllerBuilder *controllertesting.FakeControllerBuilder
c controllerapi.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{
{
From: []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},
},
}
}