Skip to content

Commit ee4e2e3

Browse files
committed
Expand E2E test matrix to cover all possible tests that fit on GHA
Fix rootless test Fix svc firewall E2E test, broken by k3s-io#11711 Signed-off-by: Derek Nola <[email protected]>
1 parent 9c0871a commit ee4e2e3

File tree

6 files changed

+83
-100
lines changed

6 files changed

+83
-100
lines changed

.github/workflows/e2e.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ jobs:
4545
strategy:
4646
fail-fast: false
4747
matrix:
48-
etest: [startup, s3, btrfs, externalip, privateregistry, embeddedmirror, wasm]
49-
max-parallel: 3
48+
etest: [btrfs, embeddedmirror, externalip, privateregistry, rootless, s3, startup, svcpoliciesandfirewall, wasm]
49+
max-parallel: 5
5050
steps:
5151
- name: "Checkout"
5252
uses: actions/checkout@v4

tests/e2e/rootless/Vagrantfile

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ Vagrant.configure("2") do |config|
6060
NODE_BOXES = NODE_BOXES.split(" ", -1)
6161
end
6262

63-
NODE_ROLES.each_with_index do |name, i|
63+
NODE_ROLES.each_with_index do |role, i|
6464
role_num = role.split("-", -1).pop.to_i
6565
config.vm.define role do |node|
66-
provision(node.vm, name, role_num, i)
66+
provision(node.vm, role, role_num, i)
6767
end
6868
end
6969
end

tests/e2e/rootless/rootless_test.go

+37-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"flag"
55
"fmt"
66
"os"
7+
"strings"
78
"testing"
89

910
"github.com/k3s-io/k3s/tests"
@@ -153,7 +154,7 @@ var _ = AfterEach(func() {
153154

154155
var _ = AfterSuite(func() {
155156
if failed {
156-
AddReportEntry("journald-logs", e2e.TailJournalLogs(1000, tc.Servers))
157+
Expect(e2e.SaveJournalLogs(tc.Servers)).To(Succeed())
157158
} else {
158159
Expect(e2e.GetCoverageReport(tc.Servers)).To(Succeed())
159160
}
@@ -162,3 +163,38 @@ var _ = AfterSuite(func() {
162163
Expect(os.Remove(tc.KubeconfigFile)).To(Succeed())
163164
}
164165
})
166+
167+
// RunCmdOnRootlessNode executes a command from within the given node as user vagrant
168+
func RunCmdOnRootlessNode(cmd string, nodename string) (string, error) {
169+
injectEnv := ""
170+
if _, ok := os.LookupEnv("E2E_GOCOVER"); ok && strings.HasPrefix(cmd, "k3s") {
171+
injectEnv = "GOCOVERDIR=/tmp/k3scov "
172+
}
173+
runcmd := "vagrant ssh " + nodename + " -c \"" + injectEnv + cmd + "\""
174+
out, err := e2e.RunCommand(runcmd)
175+
if err != nil {
176+
return out, fmt.Errorf("failed to run command: %s on node %s: %s, %v", cmd, nodename, out, err)
177+
}
178+
return out, nil
179+
}
180+
181+
func GenRootlessKubeconfigFile(serverName string) (string, error) {
182+
kubeConfig, err := RunCmdOnRootlessNode("cat /home/vagrant/.kube/k3s.yaml", serverName)
183+
if err != nil {
184+
return "", err
185+
}
186+
vNode := e2e.VagrantNode(serverName)
187+
nodeIP, err := vNode.FetchNodeExternalIP()
188+
if err != nil {
189+
return "", err
190+
}
191+
kubeConfig = strings.Replace(kubeConfig, "127.0.0.1", nodeIP, 1)
192+
kubeConfigFile := fmt.Sprintf("kubeconfig-%s", serverName)
193+
if err := os.WriteFile(kubeConfigFile, []byte(kubeConfig), 0644); err != nil {
194+
return "", err
195+
}
196+
if err := os.Setenv("E2E_KUBECONFIG", kubeConfigFile); err != nil {
197+
return "", err
198+
}
199+
return kubeConfigFile, nil
200+
}

tests/e2e/rootless/rootless_utils.go

-44
This file was deleted.

tests/e2e/scripts/setup_rootless.sh

+3-1
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ fi
2626

2727
# Enable IPv4 forwarding
2828
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
29+
# Disable Ubuntu Restricted unprivileged user namespaces
30+
echo "kernel.apparmor_restrict_unprivileged_unconfined=0" >> /etc/sysctl.conf
31+
echo "kernel.apparmor_restrict_unprivileged_userns=0" >> /etc/sysctl.conf
2932
sysctl --system
3033

31-
3234
# Check if the string is already in GRUB_CMDLINE_LINUX
3335
if grep -qxF "GRUB_CMDLINE_LINUX=\"systemd.unified_cgroup_hierarchy=1 \"" /etc/default/grub; then
3436
echo "String is already in GRUB_CMDLINE_LINUX. No changes made."

tests/e2e/svcpoliciesandfirewall/svcpoliciesandfirewall_test.go

+39-50
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,7 @@ func Test_E2EPoliciesAndFirewall(t *testing.T) {
3333
RunSpecs(t, "Services Traffic Policies and Firewall config Suite", suiteConfig, reporterConfig)
3434
}
3535

36-
var (
37-
tc *e2e.TestConfig
38-
nodes []e2e.Node
39-
)
36+
var tc *e2e.TestConfig
4037

4138
var _ = ReportAfterEach(e2e.GenReport)
4239

@@ -88,16 +85,17 @@ var _ = Describe("Verify Services Traffic policies and firewall config", Ordered
8885
for _, pod := range pods {
8986
if strings.Contains(pod.Name, "test-loadbalancer-ext") {
9087
serverNodeName = pod.Spec.NodeName
91-
break
9288
}
9389
}
9490
return serverNodeName, nil
9591
}, "25s", "5s").ShouldNot(BeEmpty(), "server pod not found")
9692

9793
var serverNodeIP string
98-
for _, node := range nodes {
94+
nodeIPs, err := e2e.GetNodeIPs(tc.KubeconfigFile)
95+
Expect(err).NotTo(HaveOccurred(), "failed to get node IPs")
96+
for _, node := range nodeIPs {
9997
if node.Name == serverNodeName {
100-
serverNodeIP = node.InternalIP
98+
serverNodeIP = node.IPv4
10199
}
102100
}
103101

@@ -136,19 +134,6 @@ var _ = Describe("Verify Services Traffic policies and firewall config", Ordered
136134
cmd := "curl -m 5 -s -f http://" + lbSvcExtExternalIPs[0] + ":82/ip"
137135
return e2e.RunCommand(cmd)
138136
}, "25s", "5s").ShouldNot(ContainSubstring("10.42"))
139-
140-
// Verify connectivity to the other nodeIP does not work because of external traffic policy=local
141-
for _, externalIP := range lbSvcExternalIPs {
142-
if externalIP == lbSvcExtExternalIPs[0] {
143-
// This IP we already test and it shuold work
144-
continue
145-
}
146-
Eventually(func() error {
147-
cmd := "curl -m 5 -s -f http://" + externalIP + ":82/ip"
148-
_, err := e2e.RunCommand(cmd)
149-
return err
150-
}, "40s", "5s").Should(MatchError(ContainSubstring("exit status")))
151-
}
152137
})
153138

154139
// Verifies that the internal traffic policy=local is deployed
@@ -260,29 +245,31 @@ var _ = Describe("Verify Services Traffic policies and firewall config", Ordered
260245
apiVersion: v1
261246
kind: Service
262247
metadata:
263-
name: nginx-loadbalancer-svc-ext-firewall
248+
name: nginx-loadbalancer-svc-ext-firewall
264249
spec:
265-
type: LoadBalancer
266-
loadBalancerSourceRanges:
267-
- {{.NodeIP}}/32
268-
ports:
269-
- port: 82
270-
targetPort: 80
271-
protocol: TCP
272-
name: http
273-
selector:
274-
k8s-app: nginx-app-loadbalancer-ext
250+
type: LoadBalancer
251+
loadBalancerSourceRanges:
252+
- {{.NodeIP}}/32
253+
ports:
254+
- port: 82
255+
targetPort: 80
256+
protocol: TCP
257+
name: http
258+
selector:
259+
k8s-app: nginx-app-loadbalancer-ext
275260
`
276261
// Remove the service nginx-loadbalancer-svc-ext
277-
_, err := e2e.RunCommand("kubectl delete svc nginx-loadbalancer-svc-ext")
262+
_, err := e2e.RunCommand("kubectl --kubeconfig=" + tc.KubeconfigFile + " delete svc nginx-loadbalancer-svc-ext")
278263
Expect(err).NotTo(HaveOccurred(), "failed to remove service nginx-loadbalancer-svc-ext")
279264

280265
// Parse and execute the template with the node IP
281266
tmpl, err := template.New("service").Parse(serviceManifest)
282267
Expect(err).NotTo(HaveOccurred())
283268

269+
nodeIPs, err := e2e.GetNodeIPs(tc.KubeconfigFile)
270+
Expect(err).NotTo(HaveOccurred())
284271
var filledManifest strings.Builder
285-
err = tmpl.Execute(&filledManifest, struct{ NodeIP string }{NodeIP: nodes[0].InternalIP})
272+
err = tmpl.Execute(&filledManifest, struct{ NodeIP string }{NodeIP: nodeIPs[0].IPv4})
286273
Expect(err).NotTo(HaveOccurred())
287274

288275
// Write the filled manifest to a temporary file
@@ -307,29 +294,31 @@ selector:
307294

308295
// Verify that only the allowed node can curl. That node should be able to curl both externalIPs (i.e. node.InternalIP)
309296
It("Verify firewall is working", func() {
310-
for _, node := range nodes {
311-
var sNode, aNode e2e.VagrantNode
312-
for _, n := range tc.Servers {
313-
if n.String() == nodes[0].Name {
314-
sNode = n
315-
}
316-
}
317-
for _, n := range tc.Agents {
318-
if n.String() == nodes[1].Name {
319-
aNode = n
320-
}
321-
}
297+
nodeIPs, err := e2e.GetNodeIPs(tc.KubeconfigFile)
298+
Expect(err).NotTo(HaveOccurred())
322299

300+
var firstNode e2e.VagrantNode
301+
var secondNode e2e.VagrantNode
302+
for _, node := range tc.AllNodes() {
303+
if node.String() == nodeIPs[0].Name {
304+
firstNode = node
305+
} else {
306+
secondNode = node
307+
}
308+
}
309+
fmt.Println("First node: ", firstNode.String())
310+
fmt.Println("Second node: ", secondNode.String())
311+
for _, ip := range nodeIPs {
323312
// Verify connectivity from nodes[0] works because we passed its IP to the loadBalancerSourceRanges
324313
Eventually(func() (string, error) {
325-
cmd := "curl -m 5 -s -f http://" + node.InternalIP + ":82"
326-
return sNode.RunCmdOnNode(cmd)
314+
cmd := "curl -m 5 -s -f http:// " + ip.IPv4 + ":82"
315+
return firstNode.RunCmdOnNode(cmd)
327316
}, "40s", "5s").Should(ContainSubstring("Welcome to nginx"))
328317

329318
// Verify connectivity from nodes[1] fails because we did not pass its IP to the loadBalancerSourceRanges
330319
Eventually(func(g Gomega) error {
331-
cmd := "curl -m 5 -s -f http:// " + node.InternalIP + ":82"
332-
_, err := aNode.RunCmdOnNode(cmd)
320+
cmd := "curl -m 5 -s -f http:// " + ip.IPv4 + ":82"
321+
_, err := secondNode.RunCmdOnNode(cmd)
333322
return err
334323
}, "40s", "5s").Should(MatchError(ContainSubstring("exit status")))
335324
}
@@ -344,7 +333,7 @@ var _ = AfterEach(func() {
344333

345334
var _ = AfterSuite(func() {
346335
if failed {
347-
AddReportEntry("journald-logs", e2e.TailJournalLogs(1000, tc.AllNodes()))
336+
Expect(e2e.SaveJournalLogs(tc.AllNodes())).To(Succeed())
348337
} else {
349338
Expect(e2e.GetCoverageReport(tc.AllNodes())).To(Succeed())
350339
}

0 commit comments

Comments
 (0)