-
Notifications
You must be signed in to change notification settings - Fork 202
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #375 from sdmodi/network-crd
Add network CRDs to cloud-provider-gcp
- Loading branch information
Showing
20 changed files
with
2,420 additions
and
229 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") | ||
|
||
go_library( | ||
name = "v1", | ||
srcs = [ | ||
"annotations.go", | ||
"groupversion_info.go", | ||
"network.go", | ||
"network_types.go", | ||
"networkinterface_types.go", | ||
"zz_generated.deepcopy.go", | ||
], | ||
importpath = "k8s.io/cloud-provider-gcp/crd/apis/network/v1", | ||
visibility = ["//visibility:public"], | ||
deps = [ | ||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:meta", | ||
"//vendor/k8s.io/apimachinery/pkg/runtime", | ||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema", | ||
], | ||
) | ||
|
||
go_test( | ||
name = "v1_test", | ||
embed = [":v1"], | ||
srcs = [ | ||
"annotations_test.go", | ||
], | ||
deps = [ | ||
"//vendor/github.com/google/go-cmp/cmp", | ||
], | ||
) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
package v1 | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
) | ||
|
||
// Annotation definitions. | ||
const ( | ||
// DisableSourceValidationAnnotationKey is the annotation on pod to disable source IP validation on L2 interfaces. | ||
// Useful when you want to assign new IPs onto the interface. | ||
DisableSourceIPValidationAnnotationKey = "networking.gke.io/disable-source-ip-validation" | ||
// DisableSourceValidationAnnotationValTrue is the value to disable source IP validation for the pod. | ||
DisableSourceIPValidationAnnotationValTrue = "true" | ||
// DefaultInterfaceAnnotationKey specifies the default route interface with interface name in pod. | ||
// The IP of the gateway comes from network CRs. | ||
DefaultInterfaceAnnotationKey = "networking.gke.io/default-interface" | ||
// InterfaceAnnotationKey specifies interfaces for pod. | ||
InterfaceAnnotationKey = "networking.gke.io/interfaces" | ||
// NodeNetworkAnnotationKey is the key of the annotation which indicates the status of | ||
// networks on the node. | ||
NodeNetworkAnnotationKey = "networking.gke.io/network-status" | ||
// PodIPsAnnotationKey is the key of the annotation which indicates additional pod IPs assigned to the pod. | ||
PodIPsAnnotationKey = "networking.gke.io/pod-ips" | ||
// NetworkAnnotationKey is the network annotation on NetworkPolicy object. | ||
// Value for this key will be the network on which network policy should be enforced. | ||
NetworkAnnotationKey = "networking.gke.io/network" | ||
// NetworkInUseAnnotationKey is the annotation on Network object. | ||
// It's used to indicate if the Network object is referenced by NetworkInterface/pod objects. | ||
NetworkInUseAnnotationKey = "networking.gke.io/in-use" | ||
// NetworkInUseAnnotationValTrue is the value to be set for NetworkInUseAnnotationKey to indicate | ||
// the Network object is referenced by at least one NetworkInterface/pod object. | ||
NetworkInUseAnnotationValTrue = "true" | ||
// MultiNetworkAnnotationKey is the network annotation key used to hold network data per node, eg: PodCIDRs. | ||
MultiNetworkAnnotationKey = "networking.gke.io/networks" | ||
// AutoGenAnnotationKey is to indicate if the object is auto-generated. | ||
AutoGenAnnotationKey = "networking.gke.io/auto-generated" | ||
// AutoGenAnnotationValTrue is the value to be set for auto-generated objects. | ||
AutoGenAnnotationValTrue = "true" | ||
) | ||
|
||
// InterfaceAnnotation is the value of the interface annotation. | ||
// +kubebuilder:object:generate:=false | ||
type InterfaceAnnotation []InterfaceRef | ||
|
||
// InterfaceRef specifies the reference to network interface. | ||
// All fields are mutual exclusive. | ||
// Either Network or Interface field can be specified. | ||
// +kubebuilder:object:generate:=false | ||
type InterfaceRef struct { | ||
// InterfaceName is the name of the interface in pod network namespace. | ||
InterfaceName string `json:"interfaceName,omitempty"` | ||
// Network refers to a network object within the cluster. | ||
// When network is specified, NetworkInterface object is optionally generated with default configuration. | ||
Network *string `json:"network,omitempty"` | ||
// Interface reference the NetworkInterface object within the namespace. | ||
Interface *string `json:"interface,omitempty"` | ||
} | ||
|
||
// ParseInterfaceAnnotation parses the given annotation. | ||
func ParseInterfaceAnnotation(annotation string) (InterfaceAnnotation, error) { | ||
ret := &InterfaceAnnotation{} | ||
err := json.Unmarshal([]byte(annotation), ret) | ||
return *ret, err | ||
} | ||
|
||
// MarshalAnnotation marshals any object into string using json.Marshal. | ||
func MarshalAnnotation(a interface{}) (string, error) { | ||
ret, err := json.Marshal(a) | ||
if err != nil { | ||
return "", fmt.Errorf("failed to marshal (%+v): %v", a, err) | ||
} | ||
return string(ret), nil | ||
} | ||
|
||
// NodeNetworkAnnotation is the value of the network status annotation. | ||
// +kubebuilder:object:generate:=false | ||
type NodeNetworkAnnotation []NodeNetworkStatus | ||
|
||
// PodIPsAnnotation is the value of the pod IPs annotation. | ||
// +kubebuilder:object:generate:=false | ||
type PodIPsAnnotation []PodIP | ||
|
||
// MultiNetworkAnnotation is the value of networks annotation. | ||
// +kubebuilder:object:generate:=false | ||
type MultiNetworkAnnotation []NodeNetwork | ||
|
||
// NodeNetworkStatus specifies the status of a network. | ||
// +kubebuilder:object:generate:=false | ||
type NodeNetworkStatus struct { | ||
// Name specifies the name of the network. | ||
Name string `json:"name,omitempty"` | ||
|
||
// IPv4Subnet is the Node internal IPv4 subnet for the network. | ||
IPv4Subnet string `json:"ipv4-subnet,omitempty"` | ||
|
||
// IPv6Subnet is the Node internal IPv6 subnet for the network. | ||
IPv6Subnet string `json:"ipv6-subnet,omitempty"` | ||
} | ||
|
||
// PodIP specifies the additional pod IPs assigned to the pod. | ||
// This will eventually be merged into the `podIPs` field in PodStatus, so the fields must remain compatible. | ||
// +kubebuilder:object:generate:=false | ||
type PodIP struct { | ||
// NetworkName refers to the network object associated with this IP. | ||
NetworkName string `json:"networkName"` | ||
|
||
// IP is an IP address (IPv4 or IPv6) assigned to the pod. | ||
IP string `json:"ip"` | ||
} | ||
|
||
// NodeNetwork specifies network data on a node. | ||
// +kubebuilder:object:generate:=false | ||
type NodeNetwork struct { | ||
// Name specifies the name of the network. | ||
Name string `json:"name"` | ||
// Cidrs denotes the IPv4/IPv6 ranges of the network. | ||
Cidrs []string `json:"cidrs"` | ||
// Scope specifies if the network is local to a node or global across a node pool. | ||
Scope string `json:"scope"` | ||
} | ||
|
||
// ParseNodeNetworkAnnotation parses the given annotation to NodeNetworkAnnotation. | ||
func ParseNodeNetworkAnnotation(annotation string) (NodeNetworkAnnotation, error) { | ||
ret := &NodeNetworkAnnotation{} | ||
err := json.Unmarshal([]byte(annotation), ret) | ||
return *ret, err | ||
} | ||
|
||
// ParsePodIPsAnnotation parses the given annotation to PodIPsAnnotation. | ||
func ParsePodIPsAnnotation(annotation string) (PodIPsAnnotation, error) { | ||
ret := &PodIPsAnnotation{} | ||
err := json.Unmarshal([]byte(annotation), ret) | ||
return *ret, err | ||
} | ||
|
||
// ParseMultiNetworkAnnotation parses given annotation to MultiNetworkAnnotation. | ||
func ParseMultiNetworkAnnotation(annotation string) (MultiNetworkAnnotation, error) { | ||
ret := &MultiNetworkAnnotation{} | ||
err := json.Unmarshal([]byte(annotation), ret) | ||
return *ret, err | ||
} | ||
|
||
// MarshalNodeNetworkAnnotation marshals a NodeNetworkAnnotation into string. | ||
func MarshalNodeNetworkAnnotation(a NodeNetworkAnnotation) (string, error) { | ||
return MarshalAnnotation(a) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
package v1 | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/google/go-cmp/cmp" | ||
) | ||
|
||
func TestPodIPsAnnotation(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
input PodIPsAnnotation | ||
expected string | ||
}{ | ||
{ | ||
name: "nil", | ||
input: nil, | ||
expected: "null", | ||
}, | ||
{ | ||
name: "empty list", | ||
input: PodIPsAnnotation{}, | ||
expected: "[]", | ||
}, | ||
{ | ||
name: "single pod IP", | ||
input: PodIPsAnnotation{ | ||
{NetworkName: "network-a", IP: "198.51.100.0"}, | ||
}, | ||
expected: `[{"networkName":"network-a","ip":"198.51.100.0"}]`, | ||
}, | ||
{ | ||
name: "missing network", | ||
input: PodIPsAnnotation{ | ||
{IP: "198.51.100.0"}, | ||
}, | ||
expected: `[{"networkName":"","ip":"198.51.100.0"}]`, | ||
}, | ||
{ | ||
name: "multiple pod IPs", | ||
input: PodIPsAnnotation{ | ||
{NetworkName: "network-a", IP: "198.51.100.0"}, | ||
{NetworkName: "network-b", IP: "2001:db8::"}, | ||
}, | ||
expected: `[{"networkName":"network-a","ip":"198.51.100.0"},{"networkName":"network-b","ip":"2001:db8::"}]`, | ||
}, | ||
} | ||
|
||
for _, tc := range tests { | ||
t.Run(tc.name, func(t *testing.T) { | ||
marshalled, err := MarshalAnnotation(tc.input) | ||
if err != nil { | ||
t.Fatalf("MarshalAnnotation(%+v) failed with error: %v", tc.input, err) | ||
} | ||
if marshalled != tc.expected { | ||
t.Fatalf("MarshalAnnotation(%+v) returns %q but want %q", tc.input, marshalled, tc.expected) | ||
} | ||
|
||
parsed, err := ParsePodIPsAnnotation(marshalled) | ||
if err != nil { | ||
t.Fatalf("ParsePodIPsAnnotation(%s) failed with error: %v", marshalled, err) | ||
} | ||
|
||
if diff := cmp.Diff(parsed, tc.input); diff != "" { | ||
t.Fatalf("ParsePodIPsAnnotation(%s) returns diff: (-got +want): %s", marshalled, diff) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestNodeNetworkAnnotation(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
input NodeNetworkAnnotation | ||
expected string | ||
}{ | ||
{ | ||
name: "nil", | ||
input: nil, | ||
expected: "null", | ||
}, | ||
{ | ||
name: "empty list", | ||
input: NodeNetworkAnnotation{}, | ||
expected: "[]", | ||
}, | ||
{ | ||
name: "list with items", | ||
input: NodeNetworkAnnotation{ | ||
{Name: "network-a"}, | ||
{Name: "network-b"}, | ||
}, | ||
expected: `[{"name":"network-a"},{"name":"network-b"}]`, | ||
}, | ||
{ | ||
name: "list with items with subnets", | ||
input: NodeNetworkAnnotation{ | ||
{Name: "network-a", IPv4Subnet: "198.51.100.0/24", IPv6Subnet: "2001:db8::/32"}, | ||
{Name: "network-b", IPv4Subnet: "198.52.100.0/24", IPv6Subnet: "2001:db9::/32"}, | ||
}, | ||
expected: `[{"name":"network-a","ipv4-subnet":"198.51.100.0/24","ipv6-subnet":"2001:db8::/32"},{"name":"network-b","ipv4-subnet":"198.52.100.0/24","ipv6-subnet":"2001:db9::/32"}]`, | ||
}, | ||
} | ||
|
||
for _, tc := range tests { | ||
t.Run(tc.name, func(t *testing.T) { | ||
marshalled, err := MarshalAnnotation(tc.input) | ||
if err != nil { | ||
t.Fatalf("MarshalAnnotation(%+v) failed with error: %v", tc.input, err) | ||
} | ||
if marshalled != tc.expected { | ||
t.Fatalf("MarshalAnnotation(%+v) returns %q but want %q", tc.input, marshalled, tc.expected) | ||
} | ||
|
||
parsed, err := ParseNodeNetworkAnnotation(marshalled) | ||
if err != nil { | ||
t.Fatalf("ParseNodeNetworkAnnotation(%s) failed with error: %v", marshalled, err) | ||
} | ||
|
||
if diff := cmp.Diff(parsed, tc.input); diff != "" { | ||
t.Fatalf("ParseNodeNetworkAnnotation(%s) returns diff: (-got +want): %s", marshalled, diff) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestParseMultiNetworkAnnotation(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
input MultiNetworkAnnotation | ||
expected string | ||
}{ | ||
{ | ||
name: "nil", | ||
input: nil, | ||
expected: "null", | ||
}, | ||
{ | ||
name: "empty list", | ||
input: MultiNetworkAnnotation{}, | ||
expected: "[]", | ||
}, | ||
{ | ||
name: "list with items", | ||
input: MultiNetworkAnnotation{ | ||
{Name: "network-a", Cidrs: []string{"1.1.1.1/21"}, Scope: "host-local"}, | ||
{Name: "network-b", Cidrs: []string{"2.2.2.2/12"}, Scope: "global"}, | ||
}, | ||
expected: `[{"name":"network-a","cidrs":["1.1.1.1/21"],"scope":"host-local"},{"name":"network-b","cidrs":["2.2.2.2/12"],"scope":"global"}]`, | ||
}, | ||
} | ||
|
||
for _, tc := range tests { | ||
t.Run(tc.name, func(t *testing.T) { | ||
marshalled, err := MarshalAnnotation(tc.input) | ||
if err != nil { | ||
t.Fatalf("MarshalAnnotation(%+v) failed with error: %v", tc.input, err) | ||
} | ||
if marshalled != tc.expected { | ||
t.Fatalf("MarshalAnnotation(%+v) returns %q but want %q", tc.input, marshalled, tc.expected) | ||
} | ||
|
||
parsed, err := ParseMultiNetworkAnnotation(marshalled) | ||
if err != nil { | ||
t.Fatalf("ParseMultiNetworkAnnotation(%s) failed with error: %v", marshalled, err) | ||
} | ||
|
||
if diff := cmp.Diff(parsed, tc.input); diff != "" { | ||
t.Fatalf("ParseMultiNetworkAnnotation(%s) returns diff: (-got +want): %s", marshalled, diff) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// Package v1 contains API Schema definitions for the networking v1 API group | ||
// +kubebuilder:object:generate=true | ||
// +groupName=networking.gke.io | ||
|
||
package v1 | ||
|
||
import ( | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
runtime "k8s.io/apimachinery/pkg/runtime" | ||
"k8s.io/apimachinery/pkg/runtime/schema" | ||
) | ||
|
||
var ( | ||
// GroupVersion is group version used to register these objects | ||
GroupVersion = schema.GroupVersion{Group: "networking.gke.io", Version: "v1"} | ||
|
||
schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) | ||
AddToScheme = schemeBuilder.AddToScheme | ||
) | ||
|
||
// Kind names for the Network objects. | ||
const ( | ||
KindNetwork = "Network" | ||
KindNetworkInterface = "NetworkInterface" | ||
) | ||
|
||
// Adds the list of known types to Scheme. | ||
func addKnownTypes(scheme *runtime.Scheme) error { | ||
scheme.AddKnownTypes(GroupVersion, | ||
&Network{}, | ||
&NetworkList{}, | ||
&NetworkInterface{}, | ||
&NetworkInterfaceList{}, | ||
) | ||
metav1.AddToGroupVersion(scheme, GroupVersion) | ||
return nil | ||
} | ||
|
||
// Kind takes an unqualified kind and returns back a Group qualified GroupKind | ||
func Kind(kind string) schema.GroupKind { | ||
return GroupVersion.WithKind(kind).GroupKind() | ||
} |
Oops, something went wrong.