Files
gvisor-tap-vsock/test/basic_tests.go
Christophe Fergeau 976f29d2d4 Add go API for /services/dhcp/leases
Signed-off-by: Christophe Fergeau <cfergeau@redhat.com>
2025-09-24 16:46:33 +02:00

222 lines
7.7 KiB
Go

package e2e
import (
"context"
"net"
"net/http"
gvproxyclient "github.com/containers/gvisor-tap-vsock/pkg/client"
"github.com/containers/gvisor-tap-vsock/pkg/types"
"github.com/onsi/ginkgo"
"github.com/onsi/gomega"
)
type BasicTestProps struct {
SSHExec func(cmd ...string) ([]byte, error)
Sock string
}
func BasicConnectivityTests(props BasicTestProps) {
ginkgo.It("should configure the interface", func() {
out, err := props.SSHExec("ifconfig $(route | grep '^default' | grep -o '[^ ]*$')")
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(string(out)).To(gomega.ContainSubstring("mtu 1500"))
gomega.Expect(string(out)).To(gomega.ContainSubstring("inet 192.168.127.2"))
gomega.Expect(string(out)).To(gomega.ContainSubstring("netmask 255.255.255.0"))
gomega.Expect(string(out)).To(gomega.ContainSubstring("broadcast 192.168.127.255"))
})
ginkgo.It("should configure the default route", func() {
out, err := props.SSHExec("ip route show")
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(string(out)).To(gomega.MatchRegexp(`default via 192\.168\.127\.1 dev (.*?) proto dhcp (src 192\.168\.127\.2 )?metric 100`))
})
ginkgo.It("should configure dns settings", func() {
out, err := props.SSHExec("cat /etc/resolv.conf")
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(string(out)).To(gomega.ContainSubstring("nameserver 192.168.127.1"))
})
ginkgo.It("should ping the tap device", func() {
out, err := props.SSHExec("ping -c2 192.168.127.2")
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(string(out)).To(gomega.ContainSubstring("2 packets transmitted, 2 received, 0% packet loss"))
})
ginkgo.It("should ping the gateway", func() {
out, err := props.SSHExec("ping -c2 192.168.127.1")
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(string(out)).To(gomega.ContainSubstring("2 packets transmitted, 2 received, 0% packet loss"))
})
}
func BasicDHCPTests(props BasicTestProps) {
ginkgo.It("should return DHCP leases", func() {
client := gvproxyclient.New(&http.Client{
Transport: &http.Transport{
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
return net.Dial("unix", props.Sock)
},
},
}, "http://base")
leases, err := client.ListDHCPLeases()
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(leases).Should(gomega.HaveKeyWithValue("192.168.127.1", "5a:94:ef:e4:0c:dd"))
gomega.Expect(leases).Should(gomega.HaveKeyWithValue("192.168.127.2", "5a:94:ef:e4:0c:ee"))
})
}
func BasicDNSTests(props BasicTestProps) {
ginkgo.It("should resolve redhat.com", func() {
out, err := props.SSHExec("nslookup redhat.com")
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(string(out)).To(gomega.ContainSubstring("Address: 52.200.142.250"))
})
ginkgo.It("should resolve CNAME record for docs.crc.dev", func() {
out, err := props.SSHExec("nslookup -query=cname docs.crc.dev")
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(string(out)).To(gomega.ContainSubstring("docs.crc.dev canonical name = webredir.gandi.net."))
})
ginkgo.It("should resolve MX record for crc.dev", func() {
out, err := props.SSHExec("nslookup -query=mx crc.dev")
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(string(out)).To(gomega.ContainSubstring("crc.dev mail exchanger = 10 spool.mail.gandi.net."))
})
ginkgo.It("should resolve NS record for wikipedia.org", func() {
out, err := props.SSHExec("nslookup -query=ns wikipedia.org")
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(string(out)).To(gomega.ContainSubstring("wikipedia.org nameserver = ns0.wikimedia.org."))
})
ginkgo.It("should resolve IMAPS SRV record for crc.dev", func() {
out, err := props.SSHExec("nslookup -query=srv _imaps._tcp.crc.dev")
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(string(out)).To(gomega.ContainSubstring(`_imaps._tcp.crc.dev service = 0 1 993 mail.gandi.net.`))
})
ginkgo.It("should resolve TXT for crc.dev", func() {
out, err := props.SSHExec("nslookup -query=txt crc.dev")
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(string(out)).To(gomega.ContainSubstring(`text = "v=spf1`))
})
ginkgo.It("should resolve gateway.containers.internal", func() {
out, err := props.SSHExec("nslookup gateway.containers.internal")
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(string(out)).To(gomega.ContainSubstring("Address: 192.168.127.1"))
})
ginkgo.It("should resolve host.containers.internal", func() {
out, err := props.SSHExec("nslookup host.containers.internal")
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(string(out)).To(gomega.ContainSubstring("Address: 192.168.127.254"))
})
ginkgo.It("should resolve dynamically added dns entry test.dynamic.internal", func() {
client := gvproxyclient.New(&http.Client{
Transport: &http.Transport{
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
return net.Dial("unix", props.Sock)
},
},
}, "http://base")
err := client.AddDNS(&types.Zone{
Name: "dynamic.internal.",
Records: []types.Record{
{
Name: "test",
IP: net.ParseIP("192.168.127.254"),
},
},
})
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
out, err := props.SSHExec("nslookup test.dynamic.internal")
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(string(out)).To(gomega.ContainSubstring("Address: 192.168.127.254"))
})
ginkgo.It("should resolve recently added dns entry test.dynamic.internal", func() {
client := gvproxyclient.New(&http.Client{
Transport: &http.Transport{
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
return net.Dial("unix", props.Sock)
},
},
}, "http://base")
err := client.AddDNS(&types.Zone{
Name: "dynamic.internal.",
Records: []types.Record{
{
Name: "test",
IP: net.ParseIP("192.168.127.254"),
},
},
})
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
err = client.AddDNS(&types.Zone{
Name: "dynamic.internal.",
Records: []types.Record{
{
Name: "test",
IP: net.ParseIP("192.168.127.253"),
},
},
})
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
out, err := props.SSHExec("nslookup test.dynamic.internal")
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(string(out)).To(gomega.ContainSubstring("Address: 192.168.127.253"))
})
ginkgo.It("should retain order of existing zone", func() {
client := gvproxyclient.New(&http.Client{
Transport: &http.Transport{
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
return net.Dial("unix", props.Sock)
},
},
}, "http://base")
_ = client.AddDNS(&types.Zone{
Name: "dynamic.testing.",
DefaultIP: net.ParseIP("192.168.127.2"),
})
_ = client.AddDNS(&types.Zone{
Name: "testing.",
Records: []types.Record{
{
Name: "host",
IP: net.ParseIP("192.168.127.3"),
},
},
})
out, err := props.SSHExec("nslookup test.dynamic.internal")
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(string(out)).To(gomega.ContainSubstring("Address: 192.168.127.2"))
_ = client.AddDNS(&types.Zone{
Name: "testing.",
Records: []types.Record{
{
Name: "gateway",
IP: net.ParseIP("192.168.127.1"),
},
},
})
out, err = props.SSHExec("nslookup *.dynamic.testing")
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(string(out)).To(gomega.ContainSubstring("Address: 192.168.127.2"))
out, err = props.SSHExec("nslookup gateway.testing")
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(string(out)).To(gomega.ContainSubstring("Address: 192.168.127.1"))
})
}