Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package dockertest
- import (
- "bytes"
- "fmt"
- "log"
- "net"
- "os"
- "os/exec"
- "strings"
- "time"
- "github.com/fsouza/go-dockerclient"
- )
- // StartMysql starts new docker container with MySQL running.
- //
- // It returns dsn, defer function and error if any.
- func StartMysql() (string, func(), error) {
- client, err := docker.NewClientFromEnv()
- if err != nil {
- return "", nil, err
- }
- c, err := client.CreateContainer(CreateOptions())
- if err != nil {
- return "", nil, err
- }
- deferFn := func() {
- if err := client.RemoveContainer(docker.RemoveContainerOptions{
- ID: c.ID,
- Force: true,
- }); err != nil {
- log.Println("cannot remove container: %v", err)
- }
- }
- // VM IP is the IP of DockerMachine VM, if running (used in non-Linux OSes)
- vm_ip := strings.TrimSpace(DockerMachineIP())
- var nonLinux bool = (vm_ip != "")
- err = client.StartContainer(c.ID, StartOptions(nonLinux))
- if err != nil {
- deferFn()
- return "", nil, err
- }
- // wait for container to wake up
- if err := waitStarted(client, c.ID, 5*time.Second); err != nil {
- deferFn()
- return "", nil, err
- }
- if c, err = client.InspectContainer(c.ID); err != nil {
- deferFn()
- return "", nil, err
- }
- // determine IP address for MySQL
- ip := ""
- if vm_ip != "" {
- ip = vm_ip
- } else if c.NetworkSettings != nil {
- ip = strings.TrimSpace(c.NetworkSettings.IPAddress)
- }
- // wait MySQL to wake up
- if err := waitReachable(ip+":3306", 5*time.Second); err != nil {
- deferFn()
- return "", nil, err
- }
- return dsn(ip), deferFn, nil
- }
- // dsn returns valid dsn to be used with mysql driver for the given ip.
- func dsn(ip string) string {
- return fmt.Sprintf("root:@tcp(%s:3306)/mydb", ip)
- }
- func CreateOptions() docker.CreateContainerOptions {
- ports := make(map[docker.Port]struct{})
- ports["3306"] = struct{}{}
- opts := docker.CreateContainerOptions{
- Config: &docker.Config{
- Image: "mydb_test",
- ExposedPorts: ports,
- },
- }
- return opts
- }
- func StartOptions(bindPorts bool) *docker.HostConfig {
- port_binds := make(map[docker.Port][]docker.PortBinding)
- if bindPorts {
- port_binds["3306"] = []docker.PortBinding{
- docker.PortBinding{HostPort: "3306"},
- }
- }
- conf := docker.HostConfig{
- PortBindings: port_binds,
- }
- return &conf
- }
- // waitReachable waits for hostport to became reachable for the maxWait time.
- func waitReachable(hostport string, maxWait time.Duration) error {
- done := time.Now().Add(maxWait)
- for time.Now().Before(done) {
- c, err := net.Dial("tcp", hostport)
- if err == nil {
- c.Close()
- return nil
- }
- time.Sleep(100 * time.Millisecond)
- }
- return fmt.Errorf("cannot connect %v for %v", hostport, maxWait)
- }
- // waitStarted waits for container to start for the maxWait time.
- func waitStarted(client *docker.Client, id string, maxWait time.Duration) error {
- done := time.Now().Add(maxWait)
- for time.Now().Before(done) {
- c, err := client.InspectContainer(id)
- if err != nil {
- break
- }
- if c.State.Running {
- return nil
- }
- time.Sleep(100 * time.Millisecond)
- }
- return fmt.Errorf("cannot start container %s for %v", id, maxWait)
- }
- // DockerMachineIP returns IP of docker-machine or boot2docker VM instance.
- //
- // If docker-machine or boot2docker is running and has IP, it will be used to
- // connect to dockerized services (MySQL, etc).
- //
- // Basically, it adds support for MacOS X and Windows.
- func DockerMachineIP() string {
- // Docker-machine is a modern solution for docker in MacOS X.
- // Try to detect it, with fallback to boot2docker
- var dockerMachine bool
- machine := os.Getenv("DOCKER_MACHINE_NAME")
- if machine != "" {
- dockerMachine = true
- }
- var buf bytes.Buffer
- var cmd *exec.Cmd
- if dockerMachine {
- cmd = exec.Command("docker-machine", "ip", machine)
- } else {
- cmd = exec.Command("boot2docker", "ip")
- }
- cmd.Stdout = &buf
- if err := cmd.Run(); err != nil {
- // ignore error, as it's perfectly OK on Linux
- return ""
- }
- return buf.String()
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement