From f0ce177e80077eb167dd17febe4b9a6c157c5684 Mon Sep 17 00:00:00 2001 From: Sarvesh Rangnekar Date: Wed, 30 Mar 2022 19:39:00 -0700 Subject: [PATCH] Introduce APIs to support multiple ClusterCIDRs (#108290) * Introduce networking/v1alpha1 api, ClusterCIDRConfig type Introduce networking/v1alpha1 api group. Add `ClusterCIDRConfig` type to networking/v1alpha1 api group, this type will enable the NodeIPAM controller to support multiple ClusterCIDRs. * Change ClusterCIDRConfig.NodeSelector type in api * Fix review comments for API * Update ClusterCIDRConfig API Spec Introduce PerNodeHostBits field, remove PerNodeMaskSize Kubernetes-commit: b9792a9daef4d978c5c30b6d10cbcdfa77a9b6ac --- go.mod | 8 ++--- go.sum | 8 ++--- pkg/describe/describe.go | 59 ++++++++++++++++++++++++++++++++++ pkg/describe/describe_test.go | 60 +++++++++++++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index b8689edb7..4f8bd17f2 100644 --- a/go.mod +++ b/go.mod @@ -31,10 +31,10 @@ require ( github.com/stretchr/testify v1.7.0 golang.org/x/sys v0.0.0-20220209214540-3681064d5158 gopkg.in/yaml.v2 v2.4.0 - k8s.io/api v0.0.0-20220330051021-b754a94214be + k8s.io/api v0.0.0-20220331051217-290a349b5385 k8s.io/apimachinery v0.0.0-20220330050810-6550efdb7444 k8s.io/cli-runtime v0.0.0-20220330053550-ef25b13feca8 - k8s.io/client-go v0.0.0-20220330131325-488e9bb0516e + k8s.io/client-go v0.0.0-20220331051643-092a109b2b10 k8s.io/component-base v0.0.0-20220330051900-ffc9c87ab39a k8s.io/component-helpers v0.0.0-20220330052013-855d491da0b6 k8s.io/klog/v2 v2.60.1 @@ -48,10 +48,10 @@ require ( ) replace ( - k8s.io/api => k8s.io/api v0.0.0-20220330051021-b754a94214be + k8s.io/api => k8s.io/api v0.0.0-20220331051217-290a349b5385 k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20220330050810-6550efdb7444 k8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20220330053550-ef25b13feca8 - k8s.io/client-go => k8s.io/client-go v0.0.0-20220330131325-488e9bb0516e + k8s.io/client-go => k8s.io/client-go v0.0.0-20220331051643-092a109b2b10 k8s.io/code-generator => k8s.io/code-generator v0.0.0-20220330050606-8f17de063761 k8s.io/component-base => k8s.io/component-base v0.0.0-20220330051900-ffc9c87ab39a k8s.io/component-helpers => k8s.io/component-helpers v0.0.0-20220330052013-855d491da0b6 diff --git a/go.sum b/go.sum index e291cdd72..0acfa696a 100644 --- a/go.sum +++ b/go.sum @@ -878,14 +878,14 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.0.0-20220330051021-b754a94214be h1:UnXBdsSVy3e2Y6cyf9rVmzn0wPXyoUuGIZAM43vdTj0= -k8s.io/api v0.0.0-20220330051021-b754a94214be/go.mod h1:gL+2VXubbVTH6gK18uLau2gxoDmu43bdiQmz5TTa3zw= +k8s.io/api v0.0.0-20220331051217-290a349b5385 h1:f+qAtGb6ikFhuwOgV62s33+xw7QCi0hrywLfkBtCVRw= +k8s.io/api v0.0.0-20220331051217-290a349b5385/go.mod h1:69QWTzqWVlGn0rU+x3dmk3WAsUQHmeQwIBWMbK1ZEyE= k8s.io/apimachinery v0.0.0-20220330050810-6550efdb7444 h1:whQmS3GtF822OUer+LPJnMFKn6kPfuJOCM/3xUuATIY= k8s.io/apimachinery v0.0.0-20220330050810-6550efdb7444/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= k8s.io/cli-runtime v0.0.0-20220330053550-ef25b13feca8 h1:ZbBnGPg/KemzGqilVYDFeTKsFfWPiwmB+bG4JtFQi9Q= k8s.io/cli-runtime v0.0.0-20220330053550-ef25b13feca8/go.mod h1:7rS4pOeS253kcv+ZA4KJZmQV16OU/VC+Kr0xt/TRMbc= -k8s.io/client-go v0.0.0-20220330131325-488e9bb0516e h1:rIU8KoyZl3WD7wEqtp37qivKd7ED8wQgjePnmGSm+oQ= -k8s.io/client-go v0.0.0-20220330131325-488e9bb0516e/go.mod h1:iaMnUMdlvGla4qhCYBfA4n7/uh5g7IktUuIeFmbk/lY= +k8s.io/client-go v0.0.0-20220331051643-092a109b2b10 h1:+HZfIcTvYmLQzSP2aDvzBMl1e1kbtJv2j8q/CJ1hz98= +k8s.io/client-go v0.0.0-20220331051643-092a109b2b10/go.mod h1:5KZ2g659eywPk2o9iKo72HhEqqiuTWOrlVyB03peN7k= k8s.io/code-generator v0.0.0-20220330050606-8f17de063761/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= k8s.io/component-base v0.0.0-20220330051900-ffc9c87ab39a h1:5GgsJwT9dZE4ta+/a+DDXa2FB0f7ZkmwqJbFE6CHZHo= k8s.io/component-base v0.0.0-20220330051900-ffc9c87ab39a/go.mod h1:LJBddfwf8ppsSrBEKyFor1D79VOnf+xhBp7/sE+XB/E= diff --git a/pkg/describe/describe.go b/pkg/describe/describe.go index 2a8bf9cc5..d855ef7e9 100644 --- a/pkg/describe/describe.go +++ b/pkg/describe/describe.go @@ -46,6 +46,7 @@ import ( discoveryv1beta1 "k8s.io/api/discovery/v1beta1" extensionsv1beta1 "k8s.io/api/extensions/v1beta1" networkingv1 "k8s.io/api/networking/v1" + networkingv1alpha1 "k8s.io/api/networking/v1alpha1" networkingv1beta1 "k8s.io/api/networking/v1beta1" policyv1 "k8s.io/api/policy/v1" policyv1beta1 "k8s.io/api/policy/v1beta1" @@ -213,6 +214,7 @@ func describerMap(clientConfig *rest.Config) (map[schema.GroupKind]ResourceDescr {Group: networkingv1beta1.GroupName, Kind: "IngressClass"}: &IngressClassDescriber{c}, {Group: networkingv1.GroupName, Kind: "Ingress"}: &IngressDescriber{c}, {Group: networkingv1.GroupName, Kind: "IngressClass"}: &IngressClassDescriber{c}, + {Group: networkingv1alpha1.GroupName, Kind: "CusterCIDRConfig"}: &ClusterCIDRConfigDescriber{c}, {Group: batchv1.GroupName, Kind: "Job"}: &JobDescriber{c}, {Group: batchv1.GroupName, Kind: "CronJob"}: &CronJobDescriber{c}, {Group: batchv1beta1.GroupName, Kind: "CronJob"}: &CronJobDescriber{c}, @@ -2819,6 +2821,63 @@ func (i *IngressClassDescriber) describeIngressClassV1(ic *networkingv1.IngressC }) } +// ClusterCIDRConfigDescriber generates information about a ClusterCIDRConfig. +type ClusterCIDRConfigDescriber struct { + client clientset.Interface +} + +func (c *ClusterCIDRConfigDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { + var events *corev1.EventList + + cccV1alpha1, err := c.client.NetworkingV1alpha1().ClusterCIDRConfigs().Get(context.TODO(), name, metav1.GetOptions{}) + if err == nil { + if describerSettings.ShowEvents { + events, _ = searchEvents(c.client.CoreV1(), cccV1alpha1, describerSettings.ChunkSize) + } + return c.describeClusterCIDRConfigV1alpha1(cccV1alpha1, events) + } + return "", err +} + +func (c *ClusterCIDRConfigDescriber) describeClusterCIDRConfigV1alpha1(ccc *networkingv1alpha1.ClusterCIDRConfig, events *corev1.EventList) (string, error) { + return tabbedString(func(out io.Writer) error { + w := NewPrefixWriter(out) + w.Write(LEVEL_0, "Name:\t%v\n", ccc.Name) + printLabelsMultiline(w, "Labels", ccc.Labels) + printAnnotationsMultiline(w, "Annotations", ccc.Annotations) + + w.Write(LEVEL_0, "NodeSelector:\n") + if ccc.Spec.NodeSelector != nil { + w.Write(LEVEL_1, "NodeSelector Terms:") + if len(ccc.Spec.NodeSelector.NodeSelectorTerms) == 0 { + w.WriteLine("") + } else { + w.WriteLine("") + for i, term := range ccc.Spec.NodeSelector.NodeSelectorTerms { + printNodeSelectorTermsMultilineWithIndent(w, LEVEL_2, fmt.Sprintf("Term %v", i), "\t", term.MatchExpressions) + } + } + } + + if ccc.Spec.PerNodeHostBits != 0 { + w.Write(LEVEL_0, "PerNodeHostBits:\t%s\n", fmt.Sprint(ccc.Spec.PerNodeHostBits)) + } + + if ccc.Spec.IPv4CIDR != "" { + w.Write(LEVEL_0, "IPv4CIDR:\t%s\n", ccc.Spec.IPv4CIDR) + } + + if ccc.Spec.IPv6CIDR != "" { + w.Write(LEVEL_0, "IPv6CIDR:\t%s\n", ccc.Spec.IPv6CIDR) + } + + if events != nil { + DescribeEvents(events, w) + } + return nil + }) +} + // ServiceDescriber generates information about a service. type ServiceDescriber struct { clientset.Interface diff --git a/pkg/describe/describe_test.go b/pkg/describe/describe_test.go index 7314feb20..516e083fb 100644 --- a/pkg/describe/describe_test.go +++ b/pkg/describe/describe_test.go @@ -25,6 +25,7 @@ import ( "testing" "time" + "github.com/google/go-cmp/cmp" appsv1 "k8s.io/api/apps/v1" autoscalingv1 "k8s.io/api/autoscaling/v1" autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2" @@ -34,6 +35,7 @@ import ( discoveryv1 "k8s.io/api/discovery/v1" discoveryv1beta1 "k8s.io/api/discovery/v1beta1" networkingv1 "k8s.io/api/networking/v1" + networkingv1alpha1 "k8s.io/api/networking/v1alpha1" networkingv1beta1 "k8s.io/api/networking/v1beta1" policyv1 "k8s.io/api/policy/v1" policyv1beta1 "k8s.io/api/policy/v1beta1" @@ -5233,6 +5235,64 @@ Events: ` + "\n", } } +func TestDescribeClusterCIDRConfig(t *testing.T) { + + testcases := map[string]struct { + input *fake.Clientset + output string + }{ + "ClusterCIDRConfig v1alpha1": { + input: fake.NewSimpleClientset(&networkingv1alpha1.ClusterCIDRConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo.123", + }, + Spec: networkingv1alpha1.ClusterCIDRConfigSpec{ + PerNodeHostBits: int32(8), + IPv4CIDR: "10.1.0.0/16", + IPv6CIDR: "fd00:1:1::/64", + NodeSelector: &corev1.NodeSelector{ + NodeSelectorTerms: []corev1.NodeSelectorTerm{ + { + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Key: "foo", + Operator: "In", + Values: []string{"bar"}}, + }, + }, + }, + }, + }, + }), + + output: `Name: foo.123 +Labels: +Annotations: +NodeSelector: + NodeSelector Terms: + Term 0: foo in [bar] +PerNodeHostBits: 8 +IPv4CIDR: 10.1.0.0/16 +IPv6CIDR: fd00:1:1::/64 +Events: ` + "\n", + }, + } + + for name, tc := range testcases { + t.Run(name, func(t *testing.T) { + c := &describeClient{T: t, Namespace: "foo", Interface: tc.input} + d := ClusterCIDRConfigDescriber{c} + out, err := d.Describe("bar", "foo.123", DescriberSettings{ShowEvents: true}) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if out != tc.output { + t.Errorf("expected :\n%s\nbut got output:\n%s diff:\n%s", tc.output, out, cmp.Diff(tc.output, out)) + } + }) + } +} + func TestControllerRef(t *testing.T) { var replicas int32 = 1 f := fake.NewSimpleClientset(