package docker import ( "errors" "strings" "bitbucket.org/robert2206/automation/modules/settings" docker "github.com/fsouza/go-dockerclient" ) var ( // errorContainerRemove is a dispatched error when container cannot be removed errorContainerRemove = errors.New("container cannot be removed") // errorContainerNotFound is a error dispatched when container cannot be found errorContainerNotFound = errors.New("container cannot be found") ) // Image represent a docker image type Image struct { ID string Tag string Size int64 } // Network represent a network ip used by docker type Network struct { ID string IP string } // Port represent a port user by docker container type Port struct { IP string Type string PublicPort int64 PrivatePort int64 } // Container represent docker container type Container struct { ID string Name string Image string State string Ports []*Port Networks map[string]*Network } // Create a container func Create(name string, image string) (*Container, error) { cli, err := getDockerClient() if err != nil { return nil, err } ctr, err := cli.CreateContainer(docker.CreateContainerOptions{ Name: name, Config: &docker.Config{ Image: image, Memory: 102400, MemorySwap: 102400, }, }) if err != nil { return nil, err } return &Container{ ID: ctr.ID, Name: ctr.Name, Image: ctr.Image, State: ctr.State.Status, }, nil } // Remove a container func Remove(idOrName string) error { cli, err := getDockerClient() if err != nil { return err } ctr := GetContainer(idOrName) if ctr == nil { return errorContainerRemove } return cli.RemoveContainer(docker.RemoveContainerOptions{ ID: ctr.ID, RemoveVolumes: true, }) } // Start container func Start(idOrName string) error { cli, err := getClientFor(idOrName) if err != nil { return err } return cli.StartContainer(idOrName, nil) } // Restart container func Restart(idOrName string) error { cli, err := getClientFor(idOrName) if err != nil { return err } return cli.RestartContainer(idOrName, 3) } // Stop container func Stop(idOrName string) error { cli, err := getClientFor(idOrName) if err != nil { return err } return cli.StopContainer(idOrName, 3) } // GetAllImages returns all docker images func GetAllImages() ([]*Image, error) { cli, err := getDockerClient() if err != nil { return nil, err } imgs, err := cli.ListImages(docker.ListImagesOptions{ All: true, }) if err != nil { return nil, err } results := make([]*Image, len(imgs)) for i, img := range imgs { results[i] = &Image{ ID: img.ID, Tag: img.RepoTags[0], Size: img.Size, } } return results, nil } // GetAllContainers returns all docker containers func GetAllContainers() ([]*Container, error) { cli, err := getDockerClient() if err != nil { return nil, err } ctrs, err := cli.ListContainers(docker.ListContainersOptions{ All: true, }) if err != nil { return nil, err } results := make([]*Container, len(ctrs)) for i, ctr := range ctrs { results[i] = &Container{ ID: ctr.ID, Name: ctr.Names[0], Image: ctr.Image, State: ctr.State, Ports: func() []*Port { prts := make([]*Port, len(ctr.Ports)) for j, prt := range ctr.Ports { prts[j] = &Port{ IP: prt.IP, Type: prt.Type, PublicPort: prt.PublicPort, PrivatePort: prt.PrivatePort, } } return prts }(), Networks: func() map[string]*Network { netws := make(map[string]*Network, len(ctr.Networks.Networks)) for k, netw := range ctr.Networks.Networks { netws[k] = &Network{ ID: netw.NetworkID, IP: netw.IPAddress, } } return netws }(), } } return results, nil } // GetContainer return container matched by id or name func GetContainer(idOrName string) *Container { ctrs, err := GetAllContainers() if err != nil { return nil } return func() *Container { for _, ctr := range ctrs { if ctr.ID == idOrName || ctr.Name == idOrName { return ctr } } return nil }() } // GetAllPublicPorts get all public exposed ports func GetAllPublicPorts() ([]int64, error) { ctrs, err := GetAllContainers() if err != nil { return nil, err } return func() []int64 { var prts []int64 for _, ctr := range ctrs { for _, ptr := range ctr.Ports { prts = append(prts, ptr.PublicPort) } } return prts }(), nil } // GetNetwork get network used by container func GetNetwork(idOrName string) (map[string]Network, error) { ctr := GetContainer(idOrName) if ctr == nil { return nil, errorContainerNotFound } return nil, nil } // GetPrivateIP get private ip used by container func GetPrivateIP(idOrName string) { } func getClientFor(idOrName string) (*docker.Client, error) { err := checkIdOrName(idOrName) if err != nil { return nil, err } cli, err := getDockerClient() if err != nil { return nil, err } return cli, nil } func checkIdOrName(idOrName string) error { if len(strings.TrimSpace(idOrName)) == 0 { return errors.New("container id or name not provided") } return nil } func getDockerClient() (*docker.Client, error) { endpoint := settings.Ctx.DockerSockDir if strings.HasSuffix(endpoint, ".sock") { endpoint = strings.Join([]string{"unix:", endpoint}, "/") } return docker.NewClient(endpoint) }