diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index e138566af..81577263b 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -56,7 +56,7 @@ jobs: - name: Test run: | - sudo -s -u ${USER} bash -c 'make test' + sudo -s -u ${USER} bash -c 'make test-linux' - uses: actions/upload-artifact@v4 if: always() diff --git a/Makefile b/Makefile index 5df2f8bc8..c4af851fd 100644 --- a/Makefile +++ b/Makefile @@ -67,6 +67,6 @@ cross: $(TOOLS_BINDIR)/makefat test-companion: GOOS=linux go build -ldflags "$(LDFLAGS)" -o bin/test-companion ./cmd/test-companion -.PHONY: test -test: gvproxy test-companion - go test -timeout 20m -v ./... +.PHONY: test-linux +test-linux: gvproxy test-companion + go test -timeout 20m -v ./test-qemu diff --git a/test-qemu/basic_test.go b/test-qemu/basic_test.go new file mode 100644 index 000000000..e30e0c50e --- /dev/null +++ b/test-qemu/basic_test.go @@ -0,0 +1,45 @@ +package e2eqemu + +import ( + "github.com/containers/gvisor-tap-vsock/pkg/types" + e2e "github.com/containers/gvisor-tap-vsock/test" + "github.com/onsi/ginkgo" + "github.com/onsi/gomega" +) + +var _ = ginkgo.Describe("connectivity with qemu", func() { + e2e.BasicConnectivityTests(e2e.BasicTestProps{ + SSHExec: sshExec, + }) +}) + +var _ = ginkgo.Describe("dns with qemu", func() { + e2e.BasicDNSTests(e2e.BasicTestProps{ + SSHExec: sshExec, + Sock: sock, + }) +}) + +var _ = ginkgo.Describe("command-line format", func() { + ginkgo.It("should convert Command to command line format", func() { + command := types.NewGvproxyCommand() + command.AddEndpoint("unix:///tmp/network.sock") + command.Debug = true + command.AddQemuSocket("tcp://0.0.0.0:1234") + command.PidFile = "~/gv-pidfile.txt" + command.LogFile = "~/gv.log" + command.AddForwardUser("demouser") + + cmd := command.ToCmdline() + gomega.Expect(cmd).To(gomega.Equal([]string{ + "-listen", "unix:///tmp/network.sock", + "-debug", + "-mtu", "1500", + "-ssh-port", "2222", + "-listen-qemu", "tcp://0.0.0.0:1234", + "-forward-user", "demouser", + "-pid-file", "~/gv-pidfile.txt", + "-log-file", "~/gv.log", + })) + }) +}) diff --git a/test/efi_darwin_arm64_test.go b/test-qemu/efi_darwin_arm64_test.go similarity index 98% rename from test/efi_darwin_arm64_test.go rename to test-qemu/efi_darwin_arm64_test.go index affc35bb9..539acae86 100644 --- a/test/efi_darwin_arm64_test.go +++ b/test-qemu/efi_darwin_arm64_test.go @@ -1,4 +1,4 @@ -package e2e +package e2eqemu import ( "fmt" diff --git a/test/efi_generic.go b/test-qemu/efi_generic.go similarity index 83% rename from test/efi_generic.go rename to test-qemu/efi_generic.go index c1106595f..a5899ef53 100644 --- a/test/efi_generic.go +++ b/test-qemu/efi_generic.go @@ -1,6 +1,6 @@ //go:build !(darwin && arm64) -package e2e +package e2eqemu func efiArgs() (string, error) { return "", nil diff --git a/test/port_forwarding_test.go b/test-qemu/port_forwarding_test.go similarity index 90% rename from test/port_forwarding_test.go rename to test-qemu/port_forwarding_test.go index 2e32e8f1a..a21570940 100644 --- a/test/port_forwarding_test.go +++ b/test-qemu/port_forwarding_test.go @@ -1,4 +1,4 @@ -package e2e +package e2eqemu import ( "context" @@ -59,6 +59,36 @@ var _ = ginkgo.Describe("port forwarding", func() { gomega.Expect(string(out)).To(gomega.ContainSubstring("Hello from the host")) }) + ginkgo.It("should reach a http server on the host", func() { + ln, err := net.Listen("tcp", "127.0.0.1:9090") + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + defer ln.Close() + + mux := http.NewServeMux() + mux.HandleFunc("/", func(writer http.ResponseWriter, _ *http.Request) { + _, _ = writer.Write([]byte("Hello from the host")) + }) + go func() { + s := &http.Server{ + Handler: mux, + ReadTimeout: 10 * time.Second, + WriteTimeout: 10 * time.Second, + } + err := s.Serve(ln) + if err != nil { + log.Error(err) + } + }() + + out, err := sshExec("curl http://host.containers.internal:9090") + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + gomega.Expect(string(out)).To(gomega.ContainSubstring("Hello from the host")) + + out, err = sshExec("curl http://host.docker.internal:9090") + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + gomega.Expect(string(out)).To(gomega.ContainSubstring("Hello from the host")) + }) + ginkgo.It("should reach a http server in the VM using dynamic port forwarding", func() { _, err := net.Dial("tcp", "127.0.0.1:9090") gomega.Expect(err).Should(gomega.HaveOccurred()) diff --git a/test/suite_test.go b/test-qemu/suite_test.go similarity index 89% rename from test/suite_test.go rename to test-qemu/suite_test.go index 67534dbb1..b25ddfa9b 100644 --- a/test/suite_test.go +++ b/test-qemu/suite_test.go @@ -1,4 +1,4 @@ -package e2e +package e2eqemu import ( "flag" @@ -13,9 +13,10 @@ import ( "testing" "time" + e2e_utils "github.com/containers/gvisor-tap-vsock/test-utils" + "github.com/onsi/ginkgo" "github.com/onsi/gomega" - "github.com/pkg/errors" log "github.com/sirupsen/logrus" ) @@ -63,15 +64,15 @@ func init() { var _ = ginkgo.BeforeSuite(func() { gomega.Expect(os.MkdirAll(filepath.Join(tmpDir, "disks"), os.ModePerm)).Should(gomega.Succeed()) - downloader, err := NewFcosDownloader(filepath.Join(tmpDir, "disks")) + downloader, err := e2e_utils.NewFcosDownloader(filepath.Join(tmpDir, "disks")) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) - qemuImage, err := downloader.DownloadImage() + qemuImage, err := downloader.DownloadImage("qemu", "qcow2.xz") gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) - publicKey, err := createSSHKeys() + publicKey, err := e2e_utils.CreateSSHKeys(publicKeyFile, privateKeyFile) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) - err = CreateIgnition(ignFile, publicKey, ignitionUser, ignitionPasswordHash) + err = e2e_utils.CreateIgnition(ignFile, publicKey, ignitionUser, ignitionPasswordHash) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) outer: @@ -154,7 +155,7 @@ outer: }) func qemuExecutable() string { - qemuBinaries := []string{"qemu-kvm", fmt.Sprintf("qemu-system-%s", coreosArch())} + qemuBinaries := []string{"qemu-kvm", fmt.Sprintf("qemu-system-%s", e2e_utils.CoreosArch())} for _, binary := range qemuBinaries { path, err := exec.LookPath(binary) if err == nil && path != "" { @@ -182,26 +183,6 @@ func qemuArgs() string { return fmt.Sprintf("-machine %s,accel=%s:tcg -smp 4 -cpu host ", machine, accel) } -func createSSHKeys() (string, error) { - _ = os.Remove(publicKeyFile) - _ = os.Remove(privateKeyFile) - err := exec.Command("ssh-keygen", "-N", "", "-t", "ed25519", "-f", privateKeyFile).Run() - if err != nil { - return "", errors.Wrap(err, "Could not generate ssh keys") - } - - return readPublicKey() -} - -func readPublicKey() (string, error) { - publicKey, err := os.ReadFile(publicKeyFile) - if err != nil { - return "", nil - } - - return strings.TrimSpace(string(publicKey)), nil -} - func scp(src, dst string) error { sshCmd := exec.Command("scp", "-o", "UserKnownHostsFile=/dev/null", diff --git a/test/fcos.go b/test-utils/fcos.go similarity index 84% rename from test/fcos.go rename to test-utils/fcos.go index 97df8c639..a59e97be5 100644 --- a/test/fcos.go +++ b/test-utils/fcos.go @@ -1,4 +1,4 @@ -package e2e +package e2eutils import ( "os" @@ -27,6 +27,11 @@ type fcosDownloadInfo struct { Sha256Sum string } +type ArtifactFormat struct { + Artifact string + Format string +} + func NewFcosDownloader(dataDir string) (*FcosDownload, error) { return &FcosDownload{ DataDir: dataDir, @@ -38,14 +43,13 @@ func imageName(info *fcosDownloadInfo) string { return urlSplit[len(urlSplit)-1] } -func (downloader *FcosDownload) DownloadImage() (string, error) { - info, err := getFCOSDownload() +func (downloader *FcosDownload) DownloadImage(artifactType string, formatType string) (string, error) { + info, err := getFCOSDownload(artifactType, formatType) if err != nil { return "", err } compressedImage := filepath.Join(downloader.DataDir, imageName(info)) - uncompressedImage := strings.TrimSuffix(filepath.Join(filepath.Dir(compressedImage), imageName(info)), ".xz") // check if the latest image is already present ok, err := downloader.updateAvailable(info, compressedImage) @@ -58,12 +62,13 @@ func (downloader *FcosDownload) DownloadImage() (string, error) { } } + uncompressedImage := "" + if uncompressedImage, err = Decompress(compressedImage); err != nil { + return "", err + } if _, err := os.Stat(uncompressedImage); err == nil { return uncompressedImage, nil } - if err := Decompress(compressedImage, uncompressedImage); err != nil { - return "", err - } return uncompressedImage, nil } @@ -91,7 +96,7 @@ func (downloader *FcosDownload) updateAvailable(info *fcosDownloadInfo, compress // as of 2024-05-28, these are the 4 architectures available in // curl https://builds.coreos.fedoraproject.org/streams/next.json -func coreosArch() string { +func CoreosArch() string { switch runtime.GOARCH { case "amd64": return "x86_64" @@ -107,7 +112,7 @@ func coreosArch() string { // This should get Exported and stay put as it will apply to all fcos downloads // getFCOS parses fedoraCoreOS's stream and returns the image download URL and the release version -func getFCOSDownload() (*fcosDownloadInfo, error) { +func getFCOSDownload(artifactType string, formatType string) (*fcosDownloadInfo, error) { streamurl := fedoracoreos.GetStreamURL(fedoracoreos.StreamNext) resp, err := http.Get(streamurl.String()) if err != nil { @@ -127,7 +132,7 @@ func getFCOSDownload() (*fcosDownloadInfo, error) { if err := json.Unmarshal(body, &fcosstable); err != nil { return nil, err } - arch, ok := fcosstable.Architectures[coreosArch()] + arch, ok := fcosstable.Architectures[CoreosArch()] if !ok { return nil, fmt.Errorf("unable to pull VM image: no targetArch in stream") } @@ -135,19 +140,19 @@ func getFCOSDownload() (*fcosDownloadInfo, error) { if artifacts == nil { return nil, fmt.Errorf("unable to pull VM image: no artifact in stream") } - qemu, ok := artifacts["qemu"] + artifact, ok := artifacts[artifactType] if !ok { return nil, fmt.Errorf("unable to pull VM image: no qemu artifact in stream") } - formats := qemu.Formats + formats := artifact.Formats if formats == nil { return nil, fmt.Errorf("unable to pull VM image: no formats in stream") } - qcow, ok := formats["qcow2.xz"] + format, ok := formats[formatType] if !ok { return nil, fmt.Errorf("unable to pull VM image: no qcow2.xz format in stream") } - disk := qcow.Disk + disk := format.Disk if disk == nil { return nil, fmt.Errorf("unable to pull VM image: no disk in stream") } diff --git a/test/ignition.go b/test-utils/ignition.go similarity index 99% rename from test/ignition.go rename to test-utils/ignition.go index a9dcbff13..4c7aae05b 100644 --- a/test/ignition.go +++ b/test-utils/ignition.go @@ -1,4 +1,4 @@ -package e2e +package e2eutils import ( "encoding/json" diff --git a/test/ignition_schema.go b/test-utils/ignition_schema.go similarity index 99% rename from test/ignition_schema.go rename to test-utils/ignition_schema.go index 5fb9d7518..e0dfe86fd 100644 --- a/test/ignition_schema.go +++ b/test-utils/ignition_schema.go @@ -1,4 +1,4 @@ -package e2e +package e2eutils // Taken from https://github.com/coreos/ignition/blob/master/config/v3_2/types/schema.go diff --git a/test/pull.go b/test-utils/pull.go similarity index 55% rename from test/pull.go rename to test-utils/pull.go index f1fa23603..819c052e2 100644 --- a/test/pull.go +++ b/test-utils/pull.go @@ -1,6 +1,7 @@ -package e2e +package e2eutils import ( + "compress/gzip" "fmt" "io" "net/http" @@ -48,18 +49,37 @@ func DownloadVMImage(downloadURL string, localImagePath string) error { return nil } -func Decompress(localPath, uncompressedPath string) error { +func Decompress(localPath string) (string, error) { + uncompressedPath := "" + if strings.HasSuffix(localPath, ".xz") { + uncompressedPath = strings.TrimSuffix(localPath, ".xz") + } else if strings.HasSuffix(localPath, ".gz") { + uncompressedPath = strings.TrimSuffix(localPath, ".gz") + } + + if uncompressedPath == "" { + return "", fmt.Errorf("unsupported compression for %s", localPath) + } + + // we remove the uncompressed file if already exists. Maybe it has been used earlier and can affect the tests result + os.Remove(uncompressedPath) + uncompressedFileWriter, err := os.OpenFile(uncompressedPath, os.O_CREATE|os.O_RDWR, 0600) if err != nil { - return err + return "", err } - if !strings.HasSuffix(localPath, ".xz") { - return fmt.Errorf("unsupported compression for %s", localPath) + fmt.Printf("Extracting %s\n", localPath) + if strings.HasSuffix(localPath, ".xz") { + err = decompressXZ(localPath, uncompressedFileWriter) + } else { + err = decompressGZ(localPath, uncompressedFileWriter) } - fmt.Printf("Extracting %s\n", localPath) - return decompressXZ(localPath, uncompressedFileWriter) + if err != nil { + return "", err + } + return uncompressedPath, nil } // Will error out if file without .xz already exists @@ -79,3 +99,30 @@ func decompressXZ(src string, output io.Writer) error { }() return cmd.Run() } + +func decompressGZ(src string, output io.Writer) error { + file, err := os.Open(src) + if err != nil { + return err + } + defer file.Close() + + // Create a gzip reader + reader, err := gzip.NewReader(file) + if err != nil { + return err + } + defer reader.Close() + + for { + _, err := io.CopyN(output, reader, 1024) + if err != nil { + if err == io.EOF { + break + } + return err + } + } + + return nil +} diff --git a/test-utils/ssh.go b/test-utils/ssh.go new file mode 100644 index 000000000..51cf00bc6 --- /dev/null +++ b/test-utils/ssh.go @@ -0,0 +1,29 @@ +package e2eutils + +import ( + "os" + "os/exec" + "strings" + + "github.com/pkg/errors" +) + +func CreateSSHKeys(publicKeyFile, privateKeyFile string) (string, error) { + _ = os.Remove(publicKeyFile) + _ = os.Remove(privateKeyFile) + err := exec.Command("ssh-keygen", "-N", "", "-t", "ed25519", "-f", privateKeyFile).Run() + if err != nil { + return "", errors.Wrap(err, "Could not generate ssh keys") + } + + return readPublicKey(publicKeyFile) +} + +func readPublicKey(publicKeyFile string) (string, error) { + publicKey, err := os.ReadFile(publicKeyFile) + if err != nil { + return "", nil + } + + return strings.TrimSpace(string(publicKey)), nil +} diff --git a/test/basic_test.go b/test/basic_tests.go similarity index 75% rename from test/basic_test.go rename to test/basic_tests.go index 4b9d354c3..fec6d2777 100644 --- a/test/basic_test.go +++ b/test/basic_tests.go @@ -6,14 +6,20 @@ import ( "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" ) -var _ = ginkgo.Describe("connectivity", func() { +type BasicTestProps struct { + SSHExec func(cmd ...string) ([]byte, error) + Sock string +} + +func BasicConnectivityTests(props BasicTestProps) { ginkgo.It("should configure the interface", func() { - out, err := sshExec("ifconfig $(route | grep '^default' | grep -o '[^ ]*$')") + 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")) @@ -22,72 +28,72 @@ var _ = ginkgo.Describe("connectivity", func() { }) ginkgo.It("should configure the default route", func() { - out, err := sshExec("ip route show") + 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 := sshExec("cat /etc/resolv.conf") + 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 := sshExec("ping -c2 192.168.127.2") + 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 := sshExec("ping -c2 192.168.127.1") + 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")) }) -}) +} -var _ = ginkgo.Describe("dns", func() { +func BasicDNSTests(props BasicTestProps) { ginkgo.It("should resolve redhat.com", func() { - out, err := sshExec("nslookup redhat.com") + 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 := sshExec("nslookup -query=cname docs.crc.dev") + 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 := sshExec("nslookup -query=mx crc.dev") + 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 := sshExec("nslookup -query=ns wikipedia.org") + 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 := sshExec("nslookup -query=srv _imaps._tcp.crc.dev") + 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 := sshExec("nslookup -query=txt crc.dev") + 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 := sshExec("nslookup gateway.containers.internal") + 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 := sshExec("nslookup host.containers.internal") + 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")) }) @@ -96,7 +102,7 @@ var _ = ginkgo.Describe("dns", func() { client := gvproxyclient.New(&http.Client{ Transport: &http.Transport{ DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { - return net.Dial("unix", sock) + return net.Dial("unix", props.Sock) }, }, }, "http://base") @@ -111,7 +117,7 @@ var _ = ginkgo.Describe("dns", func() { }) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) - out, err := sshExec("nslookup test.dynamic.internal") + 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")) @@ -121,7 +127,7 @@ var _ = ginkgo.Describe("dns", func() { client := gvproxyclient.New(&http.Client{ Transport: &http.Transport{ DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { - return net.Dial("unix", sock) + return net.Dial("unix", props.Sock) }, }, }, "http://base") @@ -147,7 +153,7 @@ var _ = ginkgo.Describe("dns", func() { }) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) - out, err := sshExec("nslookup test.dynamic.internal") + 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")) @@ -157,7 +163,7 @@ var _ = ginkgo.Describe("dns", func() { client := gvproxyclient.New(&http.Client{ Transport: &http.Transport{ DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { - return net.Dial("unix", sock) + return net.Dial("unix", props.Sock) }, }, }, "http://base") @@ -174,7 +180,7 @@ var _ = ginkgo.Describe("dns", func() { }, }, }) - out, err := sshExec("nslookup test.dynamic.internal") + 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")) @@ -187,36 +193,12 @@ var _ = ginkgo.Describe("dns", func() { }, }, }) - out, err = sshExec("nslookup *.dynamic.testing") + 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 = sshExec("nslookup gateway.testing") + 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")) }) -}) - -var _ = ginkgo.Describe("command-line format", func() { - ginkgo.It("should convert Command to command line format", func() { - command := types.NewGvproxyCommand() - command.AddEndpoint("unix:///tmp/network.sock") - command.Debug = true - command.AddQemuSocket("tcp://0.0.0.0:1234") - command.PidFile = "~/gv-pidfile.txt" - command.LogFile = "~/gv.log" - command.AddForwardUser("demouser") - - cmd := command.ToCmdline() - gomega.Expect(cmd).To(gomega.Equal([]string{ - "-listen", "unix:///tmp/network.sock", - "-debug", - "-mtu", "1500", - "-ssh-port", "2222", - "-listen-qemu", "tcp://0.0.0.0:1234", - "-forward-user", "demouser", - "-pid-file", "~/gv-pidfile.txt", - "-log-file", "~/gv.log", - })) - }) -}) +}