Skip to content

Commit 999432b

Browse files
committed
pkg/cmd: simplify network setup
1 parent de08e5b commit 999432b

File tree

1 file changed

+46
-106
lines changed

1 file changed

+46
-106
lines changed

pkg/cmd/main.go

Lines changed: 46 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -28,30 +28,20 @@ import (
2828

2929
"github.com/adevinta/vulcan-local/pkg/checktypes"
3030
"github.com/adevinta/vulcan-local/pkg/config"
31+
"github.com/adevinta/vulcan-local/pkg/dockerutil"
3132
"github.com/adevinta/vulcan-local/pkg/generator"
3233
"github.com/adevinta/vulcan-local/pkg/gitservice"
3334
"github.com/adevinta/vulcan-local/pkg/reporting"
3435
"github.com/adevinta/vulcan-local/pkg/results"
3536
)
3637

37-
const defaultDockerHost = "host.docker.internal"
38+
const dockerHostname = "host.docker.internal"
3839

39-
var localRegex = regexp.MustCompile(`(?i)\b(localhost|127.0.0.1)\b`)
40-
var dockerHost = ""
41-
var execCommand = exec.Command
42-
43-
func GetFreePort() (int, error) {
44-
addr, err := net.ResolveTCPAddr("tcp", ":0")
45-
if err != nil {
46-
return 0, err
47-
}
48-
l, err := net.ListenTCP("tcp", addr)
49-
if err != nil {
50-
return 0, err
51-
}
52-
defer l.Close()
53-
return l.Addr().(*net.TCPAddr).Port, nil
54-
}
40+
var (
41+
localRegex = regexp.MustCompile(`(?i)\b(localhost|127.0.0.1)\b`)
42+
dockerHost = ""
43+
execCommand = exec.Command
44+
)
5545

5646
func Run(cfg *config.Config, log *logrus.Logger) (int, error) {
5747
var err error
@@ -103,20 +93,10 @@ func Run(cfg *config.Config, log *logrus.Logger) (int, error) {
10393
dockerHost = cli.DaemonHost()
10494
log.Debugf("Using docker host=%s", dockerHost)
10595

106-
agentIP := getAgentIP(cfg.Conf.IfName, log)
107-
if agentIP == "" {
108-
return config.ErrorExitCode, fmt.Errorf("unable to get the agent ip %s", cfg.Conf.IfName)
109-
}
110-
111-
hostIP := getHostIP(log)
112-
if hostIP == "" {
113-
return config.ErrorExitCode, fmt.Errorf("unable to infer host ip")
114-
}
115-
11696
gs := gitservice.New(log)
11797
defer gs.Shutdown()
11898
log.Debug("Generating jobs")
119-
jobs, err := generator.GenerateJobs(cfg, agentIP, hostIP, gs, log)
99+
jobs, err := generator.GenerateJobs(cfg, log)
120100
if err != nil {
121101
return config.ErrorExitCode, fmt.Errorf("unable to generate checks %+v", err)
122102
}
@@ -151,10 +131,15 @@ func Run(cfg *config.Config, log *logrus.Logger) (int, error) {
151131
})
152132
}
153133

154-
agentPort, err := GetFreePort()
134+
listenAddr, err := getListenAddr(cli)
135+
if err != nil {
136+
return config.ErrorExitCode, fmt.Errorf("could not get listen addr: %w", err)
137+
}
138+
ln, err := net.Listen("tcp", listenAddr)
155139
if err != nil {
156-
return config.ErrorExitCode, fmt.Errorf("unable to get a free port for agent %+v", err)
140+
return config.ErrorExitCode, fmt.Errorf("unable to listen on %v: %w", listenAddr, err)
157141
}
142+
158143
agentConfig := agentconfig.Config{
159144
Agent: agentconfig.AgentConfig{
160145
ConcurrentJobs: cfg.Conf.Concurrency,
@@ -163,8 +148,8 @@ func Run(cfg *config.Config, log *logrus.Logger) (int, error) {
163148
Timeout: 180,
164149
},
165150
API: agentconfig.APIConfig{
166-
Host: agentIP,
167-
Port: fmt.Sprintf(":%d", agentPort),
151+
Host: dockerHostname,
152+
Listener: ln,
168153
},
169154
Check: agentconfig.CheckConfig{
170155
Vars: cfg.Conf.Vars,
@@ -182,7 +167,7 @@ func Run(cfg *config.Config, log *logrus.Logger) (int, error) {
182167
},
183168
}
184169
beforeRun := func(params backend.RunParams, rc *docker.RunConfig) error {
185-
return beforeCheckRun(params, rc, agentIP, gs, hostIP, cfg.Checks, log)
170+
return beforeCheckRun(params, rc, gs, cfg.Checks, log)
186171
}
187172
backend, err := docker.NewBackend(log, agentConfig, beforeRun)
188173
if err != nil {
@@ -262,79 +247,13 @@ func checkDependencies(cfg *config.Config, log agentlog.Logger) error {
262247
return nil
263248
}
264249

265-
func GetInterfaceAddr(ifaceName string) (string, error) {
266-
iface, err := net.InterfaceByName(ifaceName)
267-
if err != nil {
268-
return "", err
269-
}
270-
addrs, err := iface.Addrs()
271-
if err != nil {
272-
return "", err
273-
}
274-
275-
for _, addr := range addrs {
276-
ip, _, err := net.ParseCIDR(addr.String())
277-
if err != nil {
278-
return "", err
279-
}
280-
281-
// Check if it is IPv4.
282-
if ip.To4() != nil {
283-
return ip.To4().String(), nil
284-
}
285-
}
286-
287-
return "", fmt.Errorf("failed to determine Docker agent IP address")
288-
}
289-
290-
func getAgentIP(ifacename string, log agentlog.Logger) string {
291-
ip, err := GetInterfaceAddr(ifacename)
292-
if err == nil {
293-
log.Debugf("Agent address iface=%s ip=%s", ifacename, ip)
294-
return ip
295-
}
296-
297-
os := runtime.GOOS
298-
switch os {
299-
case "darwin":
300-
log.Debugf("Agent address os=%s ip=%s", os, defaultDockerHost)
301-
return defaultDockerHost
302-
case "linux":
303-
// Perhaps the agent is running in a container...
304-
ip, err = GetInterfaceAddr("eth0")
305-
if err == nil {
306-
log.Debugf("Agent address iface=eth0 os=%s ip=%s", os, ip)
307-
return ip
308-
}
309-
}
310-
log.Errorf("Unable to get agent address iface=%s os=%s", ifacename, os)
311-
return ""
312-
}
313-
314-
func getHostIP(l agentlog.Logger) string {
315-
if runtime.GOOS == "darwin" {
316-
return defaultDockerHost
317-
}
318-
319-
cmd := exec.Command("docker", "run", "--rm", "busybox:1.34.1", "sh", "-c", "ip route|awk '/default/ { print $3 }'")
320-
var cmdOut bytes.Buffer
321-
cmd.Stdout = &cmdOut
322-
err := cmd.Run()
323-
if err != nil {
324-
l.Errorf("unable to get Hostip %v %v", err, cmdOut.String())
325-
return ""
326-
}
327-
ip := strings.TrimSuffix(cmdOut.String(), "\n")
328-
l.Debugf("Hostip=%s", ip)
329-
return ip
330-
}
331-
332250
// beforeCheckRun is a hook executed by the agent just before a check is run
333251
// in. it's used to do some extra configuration needed for some checks to run
334252
// properly when they are executed locally.
335-
func beforeCheckRun(params backend.RunParams, rc *docker.RunConfig,
336-
agentIP string, gs gitservice.GitService, hostIP string,
253+
func beforeCheckRun(params backend.RunParams, rc *docker.RunConfig, gs gitservice.GitService,
337254
checks []config.Check, log *logrus.Logger) error {
255+
rc.HostConfig.ExtraHosts = []string{dockerHostname + ":host-gateway"}
256+
338257
newTarget := params.Target
339258
// If the asset type is a DockerImage mount the docker socket in case the image is already there,
340259
// and the check can access it.
@@ -345,8 +264,8 @@ func beforeCheckRun(params backend.RunParams, rc *docker.RunConfig,
345264
// Mount the volume in the standard location.
346265
rc.HostConfig.Binds = append(rc.HostConfig.Binds, fmt.Sprintf("%s:/var/run/docker.sock", dockerVol))
347266
} else {
348-
// for ssh / http / https just set DOCKER_HOST replacing localhost with the docker host IP.
349-
h := localRegex.ReplaceAllString(dockerHost, hostIP)
267+
// for ssh / http / https just set DOCKER_HOST replacing localhost with the docker host hostname.
268+
h := localRegex.ReplaceAllString(dockerHost, dockerHostname)
350269
rc.ContainerConfig.Env = upsertEnv(rc.ContainerConfig.Env, "DOCKER_HOST", h)
351270
}
352271

@@ -364,12 +283,12 @@ func beforeCheckRun(params backend.RunParams, rc *docker.RunConfig,
364283
log.Errorf("Unable to create local git server check %v", err)
365284
return nil
366285
}
367-
newTarget = fmt.Sprintf("http://%s:%d/", agentIP, port)
286+
newTarget = fmt.Sprintf("http://%s:%d/", dockerHostname, port)
368287
}
369288

370289
}
371290

372-
newTarget = localRegex.ReplaceAllString(newTarget, hostIP)
291+
newTarget = localRegex.ReplaceAllString(newTarget, dockerHostname)
373292

374293
if params.Target != newTarget {
375294
check := getCheckByID(checks, params.CheckID)
@@ -398,3 +317,24 @@ func getCheckByID(checks []config.Check, id string) *config.Check {
398317
}
399318
return nil
400319
}
320+
321+
func getListenAddr(cli *client.Client) (string, error) {
322+
if !inLinux() {
323+
return "127.0.0.1:0", nil
324+
}
325+
326+
gws, err := dockerutil.GetGateways(context.Background(), cli, "bridge")
327+
if err != nil {
328+
return "", fmt.Errorf("could not get Docker network gateway: %w", err)
329+
}
330+
if len(gws) != 1 {
331+
return "", fmt.Errorf("unexpected number of gateways: %v", len(gws))
332+
}
333+
334+
listenAddr := gws[0].String() + ":0"
335+
return listenAddr, nil
336+
}
337+
338+
func inLinux() bool {
339+
return runtime.GOOS == "linux"
340+
}

0 commit comments

Comments
 (0)