Skip to content

Commit a2a2ab8

Browse files
authored
ci: add fqdn with cilium local redirect policy test (#3543)
* refactor lrp setup * create lrp test case func * add k8 boilerplate for cnp * add lrp fqdn test and yaml * address linter issue * address feedback * address feedback leverages must delete functions during creation changes log.fatal to panic since log fatal will immediately exit, skipping all defers leverages wait for daemonset instead of wait for pods adds retry parameter to exec cmd on pod, adjusting associated calls incorporates exec cmd on pod error into lrp test * add case without explicit dns server remove checking for answer string as it only appears in non authoritative dns responses * improve debug message * adjust test domain name
1 parent 311bb58 commit a2a2ab8

File tree

11 files changed

+273
-64
lines changed

11 files changed

+273
-64
lines changed

Diff for: test/integration/lrp/lrp_fqdn_test.go

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//go:build lrp
2+
3+
package lrp
4+
5+
import (
6+
"context"
7+
"testing"
8+
9+
"github.com/Azure/azure-container-networking/test/internal/kubernetes"
10+
ciliumClientset "github.com/cilium/cilium/pkg/k8s/client/clientset/versioned"
11+
"github.com/stretchr/testify/require"
12+
)
13+
14+
var (
15+
fqdnCNPPath = ciliumManifestsDir + "fqdn-cnp.yaml"
16+
enableFQDNFlag = "enable-l7-proxy"
17+
)
18+
19+
// TestLRPFQDN tests if the local redirect policy in a cilium cluster is functioning with a
20+
// FQDN Cilium Network Policy. As such, enable-l7-proxy should be enabled in the config
21+
// The test assumes the current kubeconfig points to a cluster with cilium, cns,
22+
// and kube-dns already installed. The lrp feature flag should also be enabled in the cilium config
23+
// Does not check if cluster is in a stable state
24+
// Resources created are automatically cleaned up
25+
// From the lrp folder, run: go test ./ -v -tags "lrp" -run ^TestLRPFQDN$
26+
func TestLRPFQDN(t *testing.T) {
27+
ctx := context.Background()
28+
29+
selectedPod, cleanupFn := setupLRP(t, ctx)
30+
defer cleanupFn()
31+
require.NotNil(t, selectedPod)
32+
33+
cs := kubernetes.MustGetClientset()
34+
config := kubernetes.MustGetRestConfig()
35+
ciliumCS, err := ciliumClientset.NewForConfig(config)
36+
require.NoError(t, err)
37+
38+
// ensure enable l7 proxy flag is enabled
39+
ciliumCM, err := kubernetes.GetConfigmap(ctx, cs, kubeSystemNamespace, ciliumConfigmapName)
40+
require.NoError(t, err)
41+
require.Equal(t, "true", ciliumCM.Data[enableFQDNFlag], "enable-l7-proxy not set to true in cilium-config")
42+
43+
_, cleanupCNP := kubernetes.MustSetupCNP(ctx, ciliumCS, fqdnCNPPath)
44+
defer cleanupCNP()
45+
46+
tests := []struct {
47+
name string
48+
command []string
49+
expectedMsgContains string
50+
expectedErrMsgContains string
51+
shouldError bool
52+
countIncreases bool
53+
}{
54+
{
55+
name: "nslookup google succeeds",
56+
command: []string{"nslookup", "www.google.com", "10.0.0.10"},
57+
countIncreases: true,
58+
shouldError: false,
59+
},
60+
{
61+
name: "nslookup google succeeds without explicit dns server",
62+
command: []string{"nslookup", "www.google.com"},
63+
countIncreases: true,
64+
shouldError: false,
65+
},
66+
{
67+
name: "wget google succeeds",
68+
command: []string{"wget", "-O", "index.html", "www.google.com", "--timeout=5"},
69+
expectedErrMsgContains: "saved",
70+
countIncreases: true,
71+
shouldError: false,
72+
},
73+
{
74+
name: "nslookup cloudflare succeeds",
75+
command: []string{"nslookup", "www.cloudflare.com", "10.0.0.10"},
76+
countIncreases: true,
77+
shouldError: false,
78+
},
79+
{
80+
name: "wget cloudflare fails but dns succeeds",
81+
command: []string{"wget", "-O", "index.html", "www.cloudflare.com", "--timeout=5"},
82+
expectedErrMsgContains: "timed out",
83+
countIncreases: true,
84+
shouldError: true,
85+
},
86+
{
87+
name: "nslookup example fails",
88+
command: []string{"nslookup", "www.example.com", "10.0.0.10"},
89+
expectedMsgContains: "REFUSED",
90+
countIncreases: false,
91+
shouldError: true,
92+
},
93+
{
94+
// won't be able to nslookup, let alone query the website
95+
name: "wget example fails",
96+
command: []string{"wget", "-O", "index.html", "www.example.com", "--timeout=5"},
97+
expectedErrMsgContains: "bad address",
98+
countIncreases: false,
99+
shouldError: true,
100+
},
101+
}
102+
for _, tt := range tests {
103+
tt := tt
104+
t.Run(tt.name, func(t *testing.T) {
105+
testLRPCase(t, ctx, *selectedPod, tt.command, tt.expectedMsgContains, tt.expectedErrMsgContains, tt.shouldError, tt.countIncreases)
106+
})
107+
}
108+
}

Diff for: test/integration/lrp/lrp_test.go

+74-32
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/pkg/errors"
1818
"github.com/stretchr/testify/require"
1919
"golang.org/x/exp/rand"
20+
corev1 "k8s.io/api/core/v1"
2021
)
2122

2223
const (
@@ -46,15 +47,22 @@ var (
4647
clientPath = ciliumManifestsDir + "client-ds.yaml"
4748
)
4849

49-
// TestLRP tests if the local redirect policy in a cilium cluster is functioning
50-
// The test assumes the current kubeconfig points to a cluster with cilium (1.16+), cns,
51-
// and kube-dns already installed. The lrp feature flag should be enabled in the cilium config
52-
// Resources created are automatically cleaned up
53-
// From the lrp folder, run: go test ./lrp_test.go -v -tags "lrp" -run ^TestLRP$
54-
func TestLRP(t *testing.T) {
55-
config := kubernetes.MustGetRestConfig()
56-
ctx := context.Background()
50+
func setupLRP(t *testing.T, ctx context.Context) (*corev1.Pod, func()) {
51+
var cleanUpFns []func()
52+
success := false
53+
cleanupFn := func() {
54+
for len(cleanUpFns) > 0 {
55+
cleanUpFns[len(cleanUpFns)-1]()
56+
cleanUpFns = cleanUpFns[:len(cleanUpFns)-1]
57+
}
58+
}
59+
defer func() {
60+
if !success {
61+
cleanupFn()
62+
}
63+
}()
5764

65+
config := kubernetes.MustGetRestConfig()
5866
cs := kubernetes.MustGetClientset()
5967

6068
ciliumCS, err := ciliumClientset.NewForConfig(config)
@@ -90,14 +98,14 @@ func TestLRP(t *testing.T) {
9098

9199
// deploy node local dns preqreqs and pods
92100
_, cleanupConfigMap := kubernetes.MustSetupConfigMap(ctx, cs, nodeLocalDNSConfigMapPath)
93-
defer cleanupConfigMap()
101+
cleanUpFns = append(cleanUpFns, cleanupConfigMap)
94102
_, cleanupServiceAccount := kubernetes.MustSetupServiceAccount(ctx, cs, nodeLocalDNSServiceAccountPath)
95-
defer cleanupServiceAccount()
103+
cleanUpFns = append(cleanUpFns, cleanupServiceAccount)
96104
_, cleanupService := kubernetes.MustSetupService(ctx, cs, nodeLocalDNSServicePath)
97-
defer cleanupService()
105+
cleanUpFns = append(cleanUpFns, cleanupService)
98106
nodeLocalDNSDS, cleanupNodeLocalDNS := kubernetes.MustSetupDaemonset(ctx, cs, tempNodeLocalDNSDaemonsetPath)
99-
defer cleanupNodeLocalDNS()
100-
err = kubernetes.WaitForPodsRunning(ctx, cs, nodeLocalDNSDS.Namespace, nodeLocalDNSLabelSelector)
107+
cleanUpFns = append(cleanUpFns, cleanupNodeLocalDNS)
108+
kubernetes.WaitForPodDaemonset(ctx, cs, nodeLocalDNSDS.Namespace, nodeLocalDNSDS.Name, nodeLocalDNSLabelSelector)
101109
require.NoError(t, err)
102110
// select a local dns pod after they start running
103111
pods, err := kubernetes.GetPodsByNode(ctx, cs, nodeLocalDNSDS.Namespace, nodeLocalDNSLabelSelector, selectedNode)
@@ -106,19 +114,19 @@ func TestLRP(t *testing.T) {
106114

107115
// deploy lrp
108116
_, cleanupLRP := kubernetes.MustSetupLRP(ctx, ciliumCS, lrpPath)
109-
defer cleanupLRP()
117+
cleanUpFns = append(cleanUpFns, cleanupLRP)
110118

111119
// create client pods
112120
clientDS, cleanupClient := kubernetes.MustSetupDaemonset(ctx, cs, clientPath)
113-
defer cleanupClient()
114-
err = kubernetes.WaitForPodsRunning(ctx, cs, clientDS.Namespace, clientLabelSelector)
121+
cleanUpFns = append(cleanUpFns, cleanupClient)
122+
kubernetes.WaitForPodDaemonset(ctx, cs, clientDS.Namespace, clientDS.Name, clientLabelSelector)
115123
require.NoError(t, err)
116124
// select a client pod after they start running
117125
clientPods, err := kubernetes.GetPodsByNode(ctx, cs, clientDS.Namespace, clientLabelSelector, selectedNode)
118126
require.NoError(t, err)
119-
selectedClientPod := TakeOne(clientPods.Items).Name
127+
selectedClientPod := TakeOne(clientPods.Items)
120128

121-
t.Logf("Selected node: %s, node local dns pod: %s, client pod: %s\n", selectedNode, selectedLocalDNSPod, selectedClientPod)
129+
t.Logf("Selected node: %s, node local dns pod: %s, client pod: %s\n", selectedNode, selectedLocalDNSPod, selectedClientPod.Name)
122130

123131
// port forward to local dns pod on same node (separate thread)
124132
pf, err := k8s.NewPortForwarder(config, k8s.PortForwardingOpts{
@@ -130,17 +138,27 @@ func TestLRP(t *testing.T) {
130138
require.NoError(t, err)
131139
pctx := context.Background()
132140
portForwardCtx, cancel := context.WithTimeout(pctx, (retryAttempts+1)*retryDelay)
133-
defer cancel()
141+
cleanUpFns = append(cleanUpFns, cancel)
134142

135143
err = defaultRetrier.Do(portForwardCtx, func() error {
136144
t.Logf("attempting port forward to a pod with label %s, in namespace %s...", nodeLocalDNSLabelSelector, nodeLocalDNSDS.Namespace)
137145
return errors.Wrap(pf.Forward(portForwardCtx), "could not start port forward")
138146
})
139147
require.NoError(t, err, "could not start port forward within %d", (retryAttempts+1)*retryDelay)
140-
defer pf.Stop()
148+
cleanUpFns = append(cleanUpFns, pf.Stop)
141149

142150
t.Log("started port forward")
143151

152+
success = true
153+
return &selectedClientPod, cleanupFn
154+
}
155+
156+
func testLRPCase(t *testing.T, ctx context.Context, clientPod corev1.Pod, clientCmd []string, expectResponse, expectErrMsg string,
157+
shouldError, countShouldIncrease bool) {
158+
159+
config := kubernetes.MustGetRestConfig()
160+
cs := kubernetes.MustGetClientset()
161+
144162
// labels for target lrp metric
145163
metricLabels := map[string]string{
146164
"family": "1",
@@ -153,24 +171,48 @@ func TestLRP(t *testing.T) {
153171
beforeMetric, err := prometheus.GetMetric(promAddress, coreDNSRequestCountTotal, metricLabels)
154172
require.NoError(t, err)
155173

156-
t.Log("calling nslookup from client")
157-
// nslookup to 10.0.0.10 (coredns)
158-
val, err := kubernetes.ExecCmdOnPod(ctx, cs, clientDS.Namespace, selectedClientPod, clientContainer, []string{
159-
"nslookup", "google.com", "10.0.0.10",
160-
}, config)
161-
require.NoError(t, err, string(val))
162-
// can connect
163-
require.Contains(t, string(val), "Server:")
174+
t.Log("calling command from client")
175+
176+
val, errMsg, err := kubernetes.ExecCmdOnPod(ctx, cs, clientPod.Namespace, clientPod.Name, clientContainer, clientCmd, config, false)
177+
if shouldError {
178+
require.Error(t, err, "stdout: %s, stderr: %s", string(val), string(errMsg))
179+
} else {
180+
require.NoError(t, err, "stdout: %s, stderr: %s", string(val), string(errMsg))
181+
}
182+
183+
require.Contains(t, string(val), expectResponse)
184+
require.Contains(t, string(errMsg), expectErrMsg)
164185

165186
// in case there is time to propagate
166-
time.Sleep(1 * time.Second)
187+
time.Sleep(500 * time.Millisecond)
167188

168-
// curl again and see count increases
189+
// curl again and see count diff
169190
afterMetric, err := prometheus.GetMetric(promAddress, coreDNSRequestCountTotal, metricLabels)
170191
require.NoError(t, err)
171192

172-
// count should go up
173-
require.Greater(t, afterMetric.GetCounter().GetValue(), beforeMetric.GetCounter().GetValue(), "dns metric count did not increase after nslookup")
193+
if countShouldIncrease {
194+
require.Greater(t, afterMetric.GetCounter().GetValue(), beforeMetric.GetCounter().GetValue(), "dns metric count did not increase after command")
195+
} else {
196+
require.Equal(t, afterMetric.GetCounter().GetValue(), beforeMetric.GetCounter().GetValue(), "dns metric count increased after command")
197+
}
198+
}
199+
200+
// TestLRP tests if the local redirect policy in a cilium cluster is functioning
201+
// The test assumes the current kubeconfig points to a cluster with cilium (1.16+), cns,
202+
// and kube-dns already installed. The lrp feature flag should be enabled in the cilium config
203+
// Does not check if cluster is in a stable state
204+
// Resources created are automatically cleaned up
205+
// From the lrp folder, run: go test ./ -v -tags "lrp" -run ^TestLRP$
206+
func TestLRP(t *testing.T) {
207+
ctx := context.Background()
208+
209+
selectedPod, cleanupFn := setupLRP(t, ctx)
210+
defer cleanupFn()
211+
require.NotNil(t, selectedPod)
212+
213+
testLRPCase(t, ctx, *selectedPod, []string{
214+
"nslookup", "google.com", "10.0.0.10",
215+
}, "", "", false, true)
174216
}
175217

176218
// TakeOne takes one item from the slice randomly; if empty, it returns the empty value for the type

Diff for: test/integration/manifests/cilium/lrp/fqdn-cnp.yaml

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
apiVersion: "cilium.io/v2"
2+
kind: CiliumNetworkPolicy
3+
metadata:
4+
name: "to-fqdn"
5+
namespace: "default"
6+
spec:
7+
endpointSelector:
8+
matchLabels:
9+
lrp-test: "true"
10+
egress:
11+
- toEndpoints:
12+
- matchLabels:
13+
"k8s:io.kubernetes.pod.namespace": kube-system
14+
"k8s:k8s-app": node-local-dns
15+
toPorts:
16+
- ports:
17+
- port: "53"
18+
protocol: UDP
19+
rules:
20+
dns:
21+
- matchPattern: "*.google.com"
22+
- matchPattern: "*.cloudflare.com"
23+
- toFQDNs:
24+
- matchPattern: "*.google.com"

Diff for: test/internal/datapath/datapath_win.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ var ipv6PrefixPolicy = []string{"powershell", "-c", "curl.exe", "-6", "-v", "www
1919

2020
func podTest(ctx context.Context, clientset *kubernetes.Clientset, srcPod *apiv1.Pod, cmd []string, rc *restclient.Config, passFunc func(string) error) error {
2121
logrus.Infof("podTest() - %v %v", srcPod.Name, cmd)
22-
output, err := acnk8s.ExecCmdOnPod(ctx, clientset, srcPod.Namespace, srcPod.Name, "", cmd, rc)
22+
output, _, err := acnk8s.ExecCmdOnPod(ctx, clientset, srcPod.Namespace, srcPod.Name, "", cmd, rc, true)
2323
if err != nil {
2424
return errors.Wrapf(err, "failed to execute command on pod: %v", srcPod.Name)
2525
}

0 commit comments

Comments
 (0)