Skip to content

Commit

Permalink
finish bringing DNS back, with search domains
Browse files Browse the repository at this point in the history
TODO cleanup, reword, rebase, add details

Signed-off-by: Alex Suraci <alex@dagger.io>
  • Loading branch information
vito committed Jul 18, 2023
1 parent 7ba54d0 commit 291ed0b
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 48 deletions.
124 changes: 87 additions & 37 deletions cmd/shim/main.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package main

import (
"bufio"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"log"
Expand Down Expand Up @@ -426,44 +428,45 @@ func setupBundle() int {
}

// collect service IPs first so they can be used for service aliases below
var searchDomain string
var searchDomains []string
for _, env := range spec.Process.Env {
if strings.HasPrefix(env, "_DAGGER_SEARCH_DOMAIN=") {
_, val, _ := strings.Cut(env, "=")
searchDomain = val
searchDomains = strings.Fields(val)
}
}

log.Println("!!! SEARCH DOMAIN", searchDomain)
if searchDomain == "" {
for _, env := range spec.Process.Env {
log.Println("!!! NO SEARCH DOMAIN", env)
}
}
log.Println("!!! BUNDLE DIR", bundleDir)
log.Println("!!! SEARCH DOMAINS", searchDomains)

var hostsFilePath string
var resolvFilePath string
for _, mnt := range spec.Mounts {
if mnt.Destination == "/etc/hosts" {
for i, mnt := range spec.Mounts {
switch mnt.Destination {
case "/etc/hosts":
hostsFilePath = mnt.Source
log.Println("!!! HOST FILE PATH", hostsFilePath)
}
if mnt.Destination == "/etc/resolv.conf" {
resolvFilePath = mnt.Source
}
}
case "/etc/resolv.conf":
if len(searchDomains) == 0 {
break
}

if resolvFilePath != "" {
log.Println("!!! RESOLV FILE PATH", resolvFilePath)
cat := exec.Command("cat", resolvFilePath)
cat.Stdout = os.Stdout
cat.Stderr = os.Stderr
if err := cat.Run(); err != nil {
panic(err)
newResolvPath := filepath.Join(bundleDir, "resolv.conf")

log.Println("!!! UPDATING RESOLV FILE PATH", mnt.Source, newResolvPath)

newResolv, err := os.Create(newResolvPath)
if err != nil {
panic(err)
}

if err := replaceSearch(io.MultiWriter(newResolv, os.Stderr), mnt.Source, searchDomains); err != nil {
panic(err)
}

if err := newResolv.Close(); err != nil {
panic(err)
}

spec.Mounts[i].Source = newResolvPath
}
} else {
log.Println("!!! NO RESOLV FILE PATH")
}

keepEnv := []string{}
Expand All @@ -487,7 +490,7 @@ func setupBundle() int {
// NB: don't keep this env var, it's only for the bundling step
// keepEnv = append(keepEnv, env)

if err := appendHostAlias(hostsFilePath, env, searchDomain); err != nil {
if err := appendHostAlias(hostsFilePath, env, searchDomains); err != nil {
fmt.Fprintln(os.Stderr, "host alias:", err)
return 1
}
Expand Down Expand Up @@ -558,28 +561,44 @@ func setupBundle() int {

const aliasPrefix = "_DAGGER_HOSTNAME_ALIAS_"

func appendHostAlias(hostsFilePath string, env string, searchDomain string) error {
func appendHostAlias(hostsFilePath string, env string, searchDomains []string) error {
alias, target, ok := strings.Cut(strings.TrimPrefix(env, aliasPrefix), "=")
if !ok {
return fmt.Errorf("malformed host alias: %s", env)
}

if searchDomain != "" {
target += "." + searchDomain
}
var ips []net.IP
var errs error
for _, domain := range append([]string{""}, searchDomains...) {
qualified := target

ip, err := net.LookupIP(target)
if err != nil {
return err
if domain != "" {
qualified += "." + domain
}

var err error
ips, err = net.LookupIP(qualified)
log.Println("!!! LOOKUP", qualified, ips)
if err == nil {
errs = nil // ignore prior failures
break
}

errs = errors.Join(errs, err)
}
if errs != nil {
return errs
}

hostsFile, err := os.OpenFile(hostsFilePath, os.O_APPEND|os.O_WRONLY, 0o777)
if err != nil {
return err
}

if _, err := fmt.Fprintf(hostsFile, "\n%s\t%s\n", ip, alias); err != nil {
return err
for _, ip := range ips {
if _, err := fmt.Fprintf(hostsFile, "\n%s\t%s\n", ip, alias); err != nil {
return err
}
}

return hostsFile.Close()
Expand Down Expand Up @@ -676,3 +695,34 @@ func runWithNesting(ctx context.Context, cmd *exec.Cmd) error {
}
return nil
}

func replaceSearch(dst io.Writer, resolv string, searchDomains []string) error {
src, err := os.Open(resolv)
if err != nil {
return nil
}
defer src.Close()

srcScan := bufio.NewScanner(src)

var replaced bool
for srcScan.Scan() {
if !strings.HasPrefix(srcScan.Text(), "search") {
fmt.Fprintln(dst, srcScan.Text())
continue
}

oldDomains := strings.Fields(srcScan.Text())[1:]

newDomains := append([]string{}, searchDomains...)
newDomains = append(newDomains, oldDomains...)
fmt.Fprintln(dst, "search", strings.Join(newDomains, " "))
replaced = true
}

if !replaced {
fmt.Fprintln(dst, "search", strings.Join(searchDomains, " "))
}

return nil
}
1 change: 1 addition & 0 deletions core/schema/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ func (s *gitSchema) tree(ctx *router.Context, parent gitRef, args gitTreeArgs) (
var svcs core.ServiceBindings
if parent.Repository.ServiceHost != nil {
svcs = core.ServiceBindings{*parent.Repository.ServiceHost: nil}
opts = append(opts, llb.SearchDomains{core.ServicesDomain()})
}
st := llb.Git(parent.Repository.URL, parent.Name, opts...)
return core.NewDirectorySt(ctx, st, "", parent.Repository.Pipeline, s.platform, svcs)
Expand Down
2 changes: 1 addition & 1 deletion core/schema/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (s *httpSchema) http(ctx *router.Context, parent *core.Query, args httpArgs
// of following more optimized cache codepaths.
// Do a hash encode to prevent conflicts with use of `/` in the URL while also not hitting max filename limits
filename := digest.FromString(args.URL).Encoded()
st := llb.HTTP(args.URL, llb.Filename(filename))
st := llb.HTTP(args.URL, llb.Filename(filename), llb.SearchDomains{core.ServicesDomain()})

svcs := core.ServiceBindings{}
if args.ExperimentalServiceHost != nil {
Expand Down
16 changes: 11 additions & 5 deletions core/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,16 @@ import (
// that fetches the DNS search domain for the current session.
const ServicesSearchDomainSecret = "internal:services-search-domain"

// SessionDomain returns the DNS search domain for the given
// gateway session.
func SessionDomain(gw bkgw.Client) string {
return hostHashStr(gw.BuildOpts().SessionID)
var servicesDomain string
var servicesDomainOnce = &sync.Once{}

// ServicesDomain is a session-global domain suffix appended to every service's
// hostname. It is randomly generated on the first call.
func ServicesDomain() string {
servicesDomainOnce.Do(func() {
servicesDomain = hostHashStr(identity.NewID())
})
return servicesDomain
}

type Service struct {
Expand Down Expand Up @@ -215,7 +221,7 @@ func (svc *Service) Start(ctx context.Context, gw bkgw.Client, progSock *Socket)
cfg := ctr.Config

// search domain for reaching other services
searchDomain := SessionDomain(gw)
searchDomain := ServicesDomain()

env := []string{
"_DAGGER_SEARCH_DOMAIN=" + searchDomain,
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ require (
github.com/containerd/containerd v1.7.2
github.com/containerd/fuse-overlayfs-snapshotter v1.0.2
github.com/containerd/stargz-snapshotter v0.14.3
github.com/containernetworking/cni v1.1.2 // indirect
github.com/containernetworking/cni v1.1.2
github.com/coreos/go-systemd/v22 v22.5.0
github.com/dagger/graphql v0.0.0-20230601100125-137fc3a90735
github.com/dagger/graphql-go-tools v0.0.0-20230418214324-32c52f390881
Expand Down Expand Up @@ -264,4 +264,4 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
)

replace github.com/moby/buildkit => github.com/vito/buildkit v0.10.1-0.20230619145505-65140a79ce5e
replace github.com/moby/buildkit => github.com/vito/buildkit v0.10.1-0.20230619215640-f5303ca0cc88
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1941,8 +1941,8 @@ github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmF
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/vito/buildkit v0.10.1-0.20230619145505-65140a79ce5e h1:iTXsq321mPCGuv1Nu9xIO/+p9ZRNiKVx+MpLPQKxlYM=
github.com/vito/buildkit v0.10.1-0.20230619145505-65140a79ce5e/go.mod h1:6Y1HYDrxg3sY5gBY2FVaEvQpswBj3g/ck7aKYCjOkk0=
github.com/vito/buildkit v0.10.1-0.20230619215640-f5303ca0cc88 h1:O+hzsUp/nhvODSnM/MW8AAJfyFuiPPm3Z8MWKELW7ZE=
github.com/vito/buildkit v0.10.1-0.20230619215640-f5303ca0cc88/go.mod h1:6Y1HYDrxg3sY5gBY2FVaEvQpswBj3g/ck7aKYCjOkk0=
github.com/vito/progrock v0.7.1-0.20230628234355-c8ce2c2e3c24 h1:E6NeGFp8/YGYHnWtwzP5lrphxXLmoKsoAvdwuIkUTOk=
github.com/vito/progrock v0.7.1-0.20230628234355-c8ce2c2e3c24/go.mod h1:YjiMvY2X47zc9H5je8w4V59cTSrV2d0vQPwJOB5TLH8=
github.com/vito/vt100 v0.1.2 h1:gRhKJ/shHTRfMHg+Wc5ExHJzV6HHZqyQIAL52x4EUmA=
Expand Down
2 changes: 1 addition & 1 deletion secret/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (store *Store) AddSecret(_ context.Context, name, plaintext string) (core.S
// In all other cases, a SecretID is expected.
func (store *Store) GetSecret(ctx context.Context, idOrName string) ([]byte, error) {
if idOrName == core.ServicesSearchDomainSecret {
return []byte(core.SessionDomain(store.gw)), nil
return []byte(core.ServicesDomain()), nil
}

var name string
Expand Down

0 comments on commit 291ed0b

Please sign in to comment.