github.com/tommi2day/tnscli@v0.0.0-20240401211958-338fc0647b73/cmd/dns_docker_test.go (about)

     1  package cmd
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  	"os"
     8  	"time"
     9  
    10  	"github.com/tommi2day/tnscli/test"
    11  
    12  	"github.com/tommi2day/gomodules/common"
    13  	"github.com/tommi2day/gomodules/dblib"
    14  
    15  	"github.com/ory/dockertest/v3"
    16  	"github.com/ory/dockertest/v3/docker"
    17  )
    18  
    19  const DNScontainerTimeout = 10
    20  const networkName = "dblib-dnsnetwork"
    21  
    22  var dnscontainerName string
    23  var dnsContainer *dockertest.Resource
    24  var dnsnetwork *dockertest.Network
    25  var networkCreated = false
    26  var dnsserver = ""
    27  var dnsport = 0
    28  
    29  // prepareDNSContainer create a Bind9 Docker Container
    30  func prepareDNSContainer() (container *dockertest.Resource, err error) {
    31  	if os.Getenv("SKIP_DNS") != "" {
    32  		err = fmt.Errorf("skipping DNS Container in CI environment")
    33  		return
    34  	}
    35  	dnscontainerName = os.Getenv("DNS_CONTAINER_NAME")
    36  	if dnscontainerName == "" {
    37  		dnscontainerName = "tnscli-bind9"
    38  	}
    39  	var pool *dockertest.Pool
    40  	pool, err = common.GetDockerPool()
    41  	if err != nil {
    42  		return
    43  	}
    44  
    45  	networks, err := pool.NetworksByName(networkName)
    46  	if err != nil || len(networks) == 0 {
    47  		dnsnetwork, err = pool.CreateNetwork(networkName, func(options *docker.CreateNetworkOptions) {
    48  			options.Name = networkName
    49  			options.CheckDuplicate = true
    50  			options.IPAM = &docker.IPAMOptions{
    51  				Driver: "default",
    52  				Config: []docker.IPAMConfig{{
    53  					Subnet:  "172.24.0.0/16",
    54  					Gateway: "172.24.0.1",
    55  				}},
    56  			}
    57  			options.EnableIPv6 = false
    58  			// options.Internal = true
    59  		})
    60  		if err != nil {
    61  			err = fmt.Errorf("could not create Network: %s:%s", networkName, err)
    62  			return
    63  		}
    64  		networkCreated = true
    65  	} else {
    66  		dnsnetwork = &networks[0]
    67  	}
    68  
    69  	vendorImagePrefix := os.Getenv("VENDOR_IMAGE_PREFIX")
    70  
    71  	fmt.Printf("Try to build and start docker container  %s\n", dnscontainerName)
    72  	buildArgs := []docker.BuildArg{
    73  		{
    74  			Name:  "VENDOR_IMAGE_PREFIX",
    75  			Value: vendorImagePrefix,
    76  		},
    77  		{
    78  			Name:  "BIND9_VERSION",
    79  			Value: "9.18",
    80  		},
    81  	}
    82  	container, err = pool.BuildAndRunWithBuildOptions(
    83  		&dockertest.BuildOptions{
    84  			BuildArgs:  buildArgs,
    85  			ContextDir: test.TestDir + "/docker/dns",
    86  			Dockerfile: "Dockerfile",
    87  		},
    88  		&dockertest.RunOptions{
    89  			Hostname:     dnscontainerName,
    90  			Name:         dnscontainerName,
    91  			Networks:     []*dockertest.Network{dnsnetwork},
    92  			ExposedPorts: []string{"53/tcp", "53/udp", "953/tcp"},
    93  		}, func(config *docker.HostConfig) {
    94  			// set AutoRemove to true so that stopped container goes away by itself
    95  			config.AutoRemove = true
    96  			config.RestartPolicy = docker.RestartPolicy{Name: "no"}
    97  		})
    98  
    99  	if err != nil {
   100  		err = fmt.Errorf("error starting dns docker container: %v", err)
   101  		return
   102  	}
   103  	// ip := container.Container.NetworkSettings.Networks[networkName].IPAddress
   104  	ip := container.GetIPInNetwork(dnsnetwork)
   105  	if ip != "172.24.0.2" {
   106  		err = fmt.Errorf("internal ip not as expected: %s", ip)
   107  		return
   108  	}
   109  	pool.MaxWait = DNScontainerTimeout * time.Second
   110  	dnsserver, dnsport = common.GetContainerHostAndPort(container, "53/tcp")
   111  	fmt.Printf("Wait to successfully connect to DNS to %s:%d (max %ds)...\n", dnsserver, dnsport, DNScontainerTimeout)
   112  	start := time.Now()
   113  	var c net.Conn
   114  	if err = pool.Retry(func() error {
   115  		c, err = net.Dial("tcp", fmt.Sprintf("%s:%d", dnsserver, dnsport))
   116  		if err != nil {
   117  			fmt.Printf("Err:%s\n", err)
   118  		}
   119  		return err
   120  	}); err != nil {
   121  		fmt.Printf("Could not connect to DNS Container: %d", err)
   122  		return
   123  	}
   124  	_ = c.Close()
   125  
   126  	// wait 5s to init container
   127  	time.Sleep(5 * time.Second)
   128  	elapsed := time.Since(start)
   129  	fmt.Printf("DNS Container is available after %s\n", elapsed.Round(time.Millisecond))
   130  	// test dns
   131  	r := dblib.SetResolver(dnsserver, dnsport, true)
   132  	ips, e := r.LookupHost(context.Background(), racaddr)
   133  	if e != nil || len(ips) == 0 {
   134  		fmt.Printf("Could not resolve DNS with %s: %v", racaddr, e)
   135  		return
   136  	}
   137  	fmt.Println("DNS Container is ready, host", racaddr, "resolved to", ips[0])
   138  	err = nil
   139  	return
   140  }
   141  
   142  func destroyDNSContainer(container *dockertest.Resource) {
   143  	common.DestroyDockerContainer(container)
   144  	if networkCreated {
   145  		_ = dnsnetwork.Close()
   146  	}
   147  }