Repository: linkerd/linkerd2
Pull request #6256 (2021-06-11 20:38:04)

Revert "CI: skip integration tests for markdown updates (#6168)"
This reverts e6f90a04f3eaf4e20d8ceecd09c5b862adfaec9c

We've run into issues such as edits to ADOPTERS.md where CI checks do not run
that are required for all pull requests.

Signed-off-by: Kevin Leimkuhler <kevin@kleimkuhler.com>


Patch:
diff --git a/ADOPTERS.md b/ADOPTERS.md
index 9d244c1bc..5f4d64408 100644
--- a/ADOPTERS.md
+++ b/ADOPTERS.md
@@ -8,6 +8,7 @@
 - [AppddictionStudio](https://appddicitonstudio.com)
 - [Attest](https://www.askattest.com)
 - [Bink](https://bink.com)
+- [Boomin](https://www.boomin.com)
 - [Buoyant](https://buoyant.io)
 - [Candide](https://candidegardening.com)
 - [Celonis](https://celonis.com)
diff --git a/pkg/healthcheck/healthcheck.go b/pkg/healthcheck/healthcheck.go
index e008cad7e..ee9854f9e 100644
--- a/pkg/healthcheck/healthcheck.go
+++ b/pkg/healthcheck/healthcheck.go
@@ -7,6 +7,7 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"net"
 	"sort"
 	"strings"
 	"time"
@@ -763,6 +764,19 @@ func (hc *HealthChecker) allCategories() []*Category {
 						return validateControlPlanePods(hc.controlPlanePods)
 					},
 				},
+				{
+					description: "cluster networks contains all node podCIDRs",
+					hintAnchor:  "l5d-cluster-networks-cidr",
+					check: func(ctx context.Context) error {
+						// We explicitly initialize the config here so that we dont rely on the "l5d-existence-linkerd-config"
+						// check to set the clusterNetworks value, since `linkerd check config` will skip that check.
+						err := hc.InitializeLinkerdGlobalConfig(ctx)
+						if err != nil {
+							return err
+						}
+						return hc.checkClusterNetworks(ctx)
+					},
+				},
 			},
 			false,
 		),
@@ -1867,6 +1881,48 @@ func (hc *HealthChecker) CheckNamespace(ctx context.Context, namespace string, s
 	return nil
 }
 
+func (hc *HealthChecker) checkClusterNetworks(ctx context.Context) error {
+	nodes, err := hc.kubeAPI.GetNodes(ctx)
+	if err != nil {
+		return err
+	}
+	clusterNetworks := strings.Split(hc.linkerdConfig.ClusterNetworks, ",")
+	clusterIPNets := make([]*net.IPNet, len(clusterNetworks))
+	for i, clusterNetwork := range clusterNetworks {
+		_, clusterIPNets[i], err = net.ParseCIDR(clusterNetwork)
+		if err != nil {
+			return err
+		}
+	}
+	var badPodCIDRS []string
+	for _, node := range nodes {
+		podCIDR := node.Spec.PodCIDR
+		podIP, podIPNet, err := net.ParseCIDR(podCIDR)
+		if err != nil {
+			return err
+		}
+		exists := cluterNetworksContainCIDR(clusterIPNets, podIPNet, podIP)
+		if !exists {
+			badPodCIDRS = append(badPodCIDRS, podCIDR)
+		}
+	}
+	if len(badPodCIDRS) > 0 {
+		return fmt.Errorf("node has podCIDR(s) %v which are not contained in the Linkerd clusterNetworks.\n\tTry installing linkerd via --set clusterNetworks=%s", badPodCIDRS, strings.Join(badPodCIDRS, ","))
+	}
+	return nil
+}
+
+func cluterNetworksContainCIDR(clusterIPNets []*net.IPNet, podIPNet *net.IPNet, podIP net.IP) bool {
+	for _, clusterIPNet := range clusterIPNets {
+		clusterIPMaskOnes, _ := clusterIPNet.Mask.Size()
+		podCIDRMaskOnes, _ := podIPNet.Mask.Size()
+		if clusterIPNet.Contains(podIP) && podCIDRMaskOnes >= clusterIPMaskOnes {
+			return true
+		}
+	}
+	return false
+}
+
 func (hc *HealthChecker) expectedRBACNames() []string {
 	return []string{
 		fmt.Sprintf("linkerd-%s-identity", hc.ControlPlaneNamespace),
diff --git a/pkg/k8s/api.go b/pkg/k8s/api.go
index 386db9110..55e1014c2 100644
--- a/pkg/k8s/api.go
+++ b/pkg/k8s/api.go
@@ -147,6 +147,15 @@ func (kubeAPI *KubernetesAPI) NamespaceExists(ctx context.Context, namespace str
 	return ns != nil, nil
 }
 
+// GetNodes returs all the nodes in a cluster.
+func (kubeAPI *KubernetesAPI) GetNodes(ctx context.Context) ([]corev1.Node, error) {
+	nodes, err := kubeAPI.CoreV1().Nodes().List(ctx, metav1.ListOptions{})
+	if err != nil {
+		return nil, err
+	}
+	return nodes.Items, nil
+}
+
 // GetPodsByNamespace returns all pods in a given namespace
 func (kubeAPI *KubernetesAPI) GetPodsByNamespace(ctx context.Context, namespace string) ([]corev1.Pod, error) {
 	podList, err := kubeAPI.CoreV1().Pods(namespace).List(ctx, metav1.ListOptions{})


Test patch:
diff --git a/.github/workflows/integration_tests.yml b/.github/workflows/integration_tests.yml
index dc2db8654..76533f028 100644
--- a/.github/workflows/integration_tests.yml
+++ b/.github/workflows/integration_tests.yml
@@ -1,10 +1,6 @@
 name: Integration tests
 on:
-  pull_request:
-    paths-ignore:
-    - '*.md'
-    - '**/*.md'
-    - 'web/app/package.json'
+  pull_request: {}
   push:
     paths-ignore:
     - '*.md'
@@ -12,7 +8,7 @@ on:
     - 'web/app/package.json'
     branches:
     - main
-permissions: 
+permissions:
   contents: read
 env:
   GH_ANNOTATION: true
diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml
index 0389253ec..c01c59061 100644
--- a/.github/workflows/unit_tests.yml
+++ b/.github/workflows/unit_tests.yml
@@ -1,9 +1,6 @@
 name: Unit tests
 on:
-  pull_request:
-    paths-ignore:
-    - '*.md'
-    - '**/*.md'
+  pull_request: {}
   push:
     paths-ignore:
     - '*.md'
diff --git a/pkg/healthcheck/healthcheck_test.go b/pkg/healthcheck/healthcheck_test.go
index 44933da10..772133e18 100644
--- a/pkg/healthcheck/healthcheck_test.go
+++ b/pkg/healthcheck/healthcheck_test.go
@@ -1204,6 +1204,107 @@ data:
 	}
 }
 
+func TestCheckClusterNetworks(t *testing.T) {
+	var testCases = []struct {
+		checkDescription string
+		k8sConfigs       []string
+		expected         []string
+	}{
+		{
+			checkDescription: "cluster networks contains all node podCIDRs",
+			k8sConfigs: []string{`
+apiVersion: v1
+kind: Namespace
+metadata:
+  name: test-ns
+`,
+				`
+apiVersion: v1
+kind: Node
+metadata:
+  name: linkerd-test-ns-identity
+spec:
+  podCIDR: 90.10.90.24/24
+`,
+				`
+kind: ConfigMap
+apiVersion: v1
+metadata:
+  name: linkerd-config
+  namespace: test-ns
+  labels:
+    linkerd.io/control-plane-ns: test-ns
+data:
+  values: |
+    clusterNetworks: "10.0.0.0/8,100.64.0.0/10,172.16.0.0/12,192.168.0.0/16"
+`,
+			},
+			expected: []string{
+				"linkerd-existence cluster networks contains all node podCIDRs: node has podCIDR(s) [90.10.90.24/24] which are not contained in the Linkerd clusterNetworks.\n\tTry installing linkerd via --set clusterNetworks=90.10.90.24/24",
+			},
+		},
+		{
+			checkDescription: "cluster networks contains all node podCIDRs",
+			k8sConfigs: []string{`
+apiVersion: v1
+kind: Namespace
+metadata:
+  name: test-ns
+`,
+				`
+apiVersion: v1
+kind: Node
+metadata:
+  name: linkerd-test-ns-identity
+spec:
+  podCIDR: 10.0.0.24/24
+`,
+				`
+kind: ConfigMap
+apiVersion: v1
+metadata:
+  name: linkerd-config
+  namespace: test-ns
+  labels:
+    linkerd.io/control-plane-ns: test-ns
+data:
+  values: |
+    clusterNetworks: "10.0.0.0/8,100.64.0.0/10,172.16.0.0/12,192.168.0.0/16"
+`,
+			},
+			expected: []string{
+				"linkerd-existence cluster networks contains all node podCIDRs",
+			},
+		},
+	}
+
+	for i, tc := range testCases {
+		tc := tc // pin
+		t.Run(fmt.Sprintf("%d: returns expected config result", i), func(t *testing.T) {
+			hc := NewHealthChecker(
+				[]CategoryID{},
+				&Options{
+					ControlPlaneNamespace: "test-ns",
+				},
+			)
+
+			var err error
+			hc.kubeAPI, err = k8s.NewFakeAPI(tc.k8sConfigs...)
+			if err != nil {
+				t.Fatalf("Unexpected error: %s", err)
+			}
+
+			obs := newObserver()
+			hc.addCheckAsCategory("linkerd-existence", LinkerdControlPlaneExistenceChecks,
+				tc.checkDescription)
+			hc.RunChecks(obs.resultFn)
+			if !reflect.DeepEqual(obs.results, tc.expected) {
+				t.Fatalf("Expected results\n%s,\nbut got:\n%s", strings.Join(tc.expected, "\n"), strings.Join(obs.results, "\n"))
+			}
+		})
+	}
+}
+
 func proxiesWithCertificates(certificates ...string) []string {
 	result := []string{}
 	for i, certificate := range certificates {
diff --git a/test/integration/testdata/check.cni.golden b/test/integration/testdata/check.cni.golden
index c7c95e380..bcd102a9a 100644
--- a/test/integration/testdata/check.cni.golden
+++ b/test/integration/testdata/check.cni.golden
@@ -18,6 +18,7 @@ linkerd-existence
 √ control plane replica sets are ready
 √ no unschedulable pods
 √ control plane pods are ready
+√ cluster networks contains all node podCIDRs
 
 linkerd-config
 --------------
diff --git a/test/integration/testdata/check.cni.proxy.golden b/test/integration/testdata/check.cni.proxy.golden
index 36d63ea87..185b2c44a 100644
--- a/test/integration/testdata/check.cni.proxy.golden
+++ b/test/integration/testdata/check.cni.proxy.golden
@@ -18,6 +18,7 @@ linkerd-existence
 √ control plane replica sets are ready
 √ no unschedulable pods
 √ control plane pods are ready
+√ cluster networks contains all node podCIDRs
 
 linkerd-config
 --------------
diff --git a/test/integration/testdata/check.golden b/test/integration/testdata/check.golden
index ba54a3a85..44dd0e3f9 100644
--- a/test/integration/testdata/check.golden
+++ b/test/integration/testdata/check.golden
@@ -18,6 +18,7 @@ linkerd-existence
 √ control plane replica sets are ready
 √ no unschedulable pods
 √ control plane pods are ready
+√ cluster networks contains all node podCIDRs
 
 linkerd-config
 --------------
diff --git a/test/integration/testdata/check.multicluster.proxy.golden b/test/integration/testdata/check.multicluster.proxy.golden
index 9fa3a576e..9e512eba2 100644
--- a/test/integration/testdata/check.multicluster.proxy.golden
+++ b/test/integration/testdata/check.multicluster.proxy.golden
@@ -18,6 +18,7 @@ linkerd-existence
 √ control plane replica sets are ready
 √ no unschedulable pods
 √ control plane pods are ready
+√ cluster networks contains all node podCIDRs
 
 linkerd-config
 --------------
diff --git a/test/integration/testdata/check.proxy.golden b/test/integration/testdata/check.proxy.golden
index fccf16c39..58ab20b93 100644
--- a/test/integration/testdata/check.proxy.golden
+++ b/test/integration/testdata/check.proxy.golden
@@ -18,6 +18,7 @@ linkerd-existence
 √ control plane replica sets are ready
 √ no unschedulable pods
 √ control plane pods are ready
+√ cluster networks contains all node podCIDRs
 
 linkerd-config
 --------------