Skip to content

Commit 6b7f053

Browse files
authored
feat(macOS): Support host DNS aliases for macos (runfinch#1085)
This change adds: 1) `host.finch.internal` 2) `host.docker.internal` as DNS names that are aliased to the host's loopback address. This allows service and containers inside the VM to connect to services bound to the host's loopback device. Signed-off-by: Kern Walster <walster@amazon.com>
1 parent 78012ca commit 6b7f053

File tree

6 files changed

+146
-19
lines changed

6 files changed

+146
-19
lines changed

e2e/vm/soci_remote_test.go

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ package vm
88
import (
99
"fmt"
1010
"os"
11-
"os/exec"
12-
"path/filepath"
1311
"runtime"
1412
"strings"
1513

@@ -31,29 +29,15 @@ const (
3129
var testSoci = func(o *option.Option, installed bool) {
3230
ginkgo.Describe("SOCI", func() {
3331
var limactlO *option.Option
34-
var fpath, realFinchPath, limactlPath, limaHomePathEnv, wd, vmType string
32+
var vmType string
3533
var err error
3634
var port int
3735

3836
ginkgo.BeforeEach(func() {
3937
// Find lima paths. limactl is used to shell into the Finch VM and verify
4038
// mounted snapshots match the expected SOCI snapshotter behavior.
41-
if installed {
42-
fpath, err = exec.LookPath("finch")
43-
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
44-
realFinchPath, err = filepath.EvalSymlinks(fpath)
45-
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
46-
limactlPath = filepath.Join(realFinchPath, "../../lima/bin/limactl")
47-
limaHomePathEnv = "LIMA_HOME=" + filepath.Join(realFinchPath, "../../lima/data")
48-
} else {
49-
wd, err = os.Getwd()
50-
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
51-
limactlPath = filepath.Join(wd, "../../_output/lima/bin/limactl")
52-
limaHomePathEnv = "LIMA_HOME=" + filepath.Join(wd, "../../_output/lima/data")
53-
}
5439

55-
limactlO, err = option.New([]string{limactlPath},
56-
option.Env([]string{limaHomePathEnv}))
40+
limactlO, err = limaCtlOpt(installed)
5741
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
5842
if runtime.GOOS == "windows" {
5943
vmType = "wsl2"

e2e/vm/vm_darwin_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ func TestVM(t *testing.T) {
7070
testSupportBundle(o)
7171
testCredHelper(o, *e2e.Installed, *e2e.Registry)
7272
testSoci(o, *e2e.Installed)
73+
testVMNetwork(o, *e2e.Installed)
7374
})
7475

7576
gomega.RegisterFailHandler(ginkgo.Fail)

e2e/vm/vm_network_test.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
//go:build darwin
5+
6+
package vm
7+
8+
import (
9+
"context"
10+
"fmt"
11+
"net/http"
12+
"time"
13+
14+
"github.com/onsi/ginkgo/v2"
15+
"github.com/onsi/gomega"
16+
"github.com/onsi/gomega/gbytes"
17+
"github.com/runfinch/common-tests/command"
18+
"github.com/runfinch/common-tests/option"
19+
"golang.org/x/sync/errgroup"
20+
)
21+
22+
const (
23+
addr = "localhost"
24+
port = "8888"
25+
responseBody = "ack"
26+
finchHost = "host.finch.internal"
27+
dockerHost = "host.docker.internal"
28+
)
29+
30+
func hostWithPort(host, port string) string {
31+
return fmt.Sprintf("%s:%s", host, port)
32+
}
33+
34+
func vmDNSValidationCommand(host, port string) []string {
35+
// The finch rootfs has curl but not wget
36+
return []string{
37+
"shell",
38+
"finch",
39+
"curl",
40+
"--silent",
41+
"--connect-timeout", "1",
42+
hostWithPort(host, port),
43+
}
44+
}
45+
46+
func containerDNSValidationCommand(host, port string) []string {
47+
// The container rootfs has wget, but not curl
48+
return []string{
49+
"run",
50+
"public.ecr.aws/docker/library/alpine:latest",
51+
"wget",
52+
"-O", "-", // output to stdout
53+
"-q", // quiet
54+
"-T", "1", // read timeout
55+
hostWithPort(host, port),
56+
}
57+
}
58+
59+
func testVMNetwork(finchO *option.Option, installed bool) {
60+
limaCtlO, err := limaCtlOpt(installed)
61+
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
62+
eg, _ := errgroup.WithContext(context.Background())
63+
var srv *http.Server
64+
ginkgo.Describe("vm networking", func() {
65+
ginkgo.BeforeEach(func() {
66+
srv = &http.Server{
67+
Addr: hostWithPort(addr, port),
68+
ReadHeaderTimeout: 1 * time.Second,
69+
Handler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
70+
_, err := w.Write([]byte(responseBody))
71+
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
72+
}),
73+
}
74+
eg.Go(srv.ListenAndServe)
75+
})
76+
ginkgo.AfterEach(func() {
77+
err := srv.Shutdown(context.Background())
78+
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
79+
err = eg.Wait()
80+
gomega.Expect(err).To(gomega.MatchError(http.ErrServerClosed))
81+
})
82+
ginkgo.It("should resolve host.finch.internal in the vm", func() {
83+
out := command.New(limaCtlO, vmDNSValidationCommand(finchHost, port)...).WithStdout(gbytes.NewBuffer()).Run().Out
84+
gomega.Expect(out).To(gbytes.Say(responseBody))
85+
})
86+
ginkgo.It("should resolve host.docker.internal in the vm", func() {
87+
out := command.New(limaCtlO, vmDNSValidationCommand(dockerHost, port)...).WithStdout(gbytes.NewBuffer()).Run().Out
88+
gomega.Expect(out).To(gbytes.Say(responseBody))
89+
})
90+
ginkgo.It("should resolve host.finch.internal in a container", func() {
91+
out := command.New(finchO, containerDNSValidationCommand(finchHost, port)...).WithStdout(gbytes.NewBuffer()).Run().Out
92+
gomega.Expect(out).To(gbytes.Say(responseBody))
93+
})
94+
ginkgo.It("should resolve host.docker.internal in a container", func() {
95+
out := command.New(finchO, containerDNSValidationCommand(dockerHost, port)...).WithStdout(gbytes.NewBuffer()).Run().Out
96+
gomega.Expect(out).To(gbytes.Say(responseBody))
97+
})
98+
})
99+
}

e2e/vm/vm_util_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
//go:build darwin || windows
5+
6+
package vm
7+
8+
import (
9+
"os"
10+
"os/exec"
11+
"path/filepath"
12+
13+
"github.com/runfinch/common-tests/option"
14+
)
15+
16+
func limaCtlOpt(installed bool) (*option.Option, error) {
17+
var limactlPath, limaHomePathEnv string
18+
if installed {
19+
fpath, err := exec.LookPath("finch")
20+
if err != nil {
21+
return nil, err
22+
}
23+
realFinchPath, err := filepath.EvalSymlinks(fpath)
24+
if err != nil {
25+
return nil, err
26+
}
27+
limactlPath = filepath.Join(realFinchPath, "../../lima/bin/limactl")
28+
limaHomePathEnv = "LIMA_HOME=" + filepath.Join(realFinchPath, "../../lima/data")
29+
} else {
30+
wd, err := os.Getwd()
31+
if err != nil {
32+
return nil, err
33+
}
34+
limactlPath = filepath.Join(wd, "../../_output/lima/bin/limactl")
35+
limaHomePathEnv = "LIMA_HOME=" + filepath.Join(wd, "../../_output/lima/data")
36+
}
37+
return option.New([]string{limactlPath}, option.Env([]string{limaHomePathEnv}))
38+
}

finch.yaml.d/mac.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,8 @@ firmware:
3939

4040
video:
4141
display: "none"
42+
43+
hostResolver:
44+
hosts:
45+
host.finch.internal: host.lima.internal
46+
host.docker.internal: host.lima.internal

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ require (
2525
github.com/xorcare/pointer v1.2.2
2626
golang.org/x/crypto v0.27.0
2727
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
28+
golang.org/x/sync v0.8.0
2829
golang.org/x/tools v0.25.0
2930
gopkg.in/yaml.v3 v3.0.1
3031
k8s.io/apimachinery v0.31.1
@@ -71,7 +72,6 @@ require (
7172
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
7273
github.com/yusufpapurcu/wmi v1.2.4 // indirect
7374
golang.org/x/image v0.18.0 // indirect
74-
golang.org/x/sync v0.8.0 // indirect
7575
google.golang.org/genproto/googleapis/rpc v0.0.0-20240805194559-2c9e96a0b5d4 // indirect
7676
google.golang.org/grpc v1.66.0 // indirect
7777
google.golang.org/protobuf v1.34.2 // indirect

0 commit comments

Comments
 (0)