1
0
mirror of https://github.com/containrrr/watchtower.git synced 2024-12-15 09:14:13 +02:00
watchtower/container/container.go

155 lines
4.5 KiB
Go
Raw Normal View History

2015-07-21 18:04:41 +02:00
package container
import (
"fmt"
"strings"
"github.com/samalba/dockerclient"
)
2015-07-23 00:52:22 +02:00
const (
watchtowerLabel = "com.centurylinklabs.watchtower"
signalLabel = "com.centurylinklabs.watchtower.stop-signal"
)
2015-08-01 00:23:17 +02:00
// NewContainer returns a new Container instance instantiated with the
// specified ContainerInfo and ImageInfo structs.
2015-07-21 21:37:18 +02:00
func NewContainer(containerInfo *dockerclient.ContainerInfo, imageInfo *dockerclient.ImageInfo) *Container {
return &Container{
containerInfo: containerInfo,
imageInfo: imageInfo,
}
}
2015-08-01 00:23:17 +02:00
// Container represents a running Docker container.
type Container struct {
Stale bool
containerInfo *dockerclient.ContainerInfo
imageInfo *dockerclient.ImageInfo
}
2015-08-01 00:23:17 +02:00
// ID returns the Docker container ID.
2015-07-23 00:52:22 +02:00
func (c Container) ID() string {
return c.containerInfo.Id
}
2015-08-01 00:23:17 +02:00
// Name returns the Docker container name.
func (c Container) Name() string {
return c.containerInfo.Name
}
2015-08-01 00:23:17 +02:00
// ImageID returns the ID of the Docker image that was used to start the
// container.
func (c Container) ImageID() string {
return c.imageInfo.Id
}
2015-08-01 00:23:17 +02:00
// ImageName returns the name of the Docker image that was used to start the
// container. If the original image was specified without a particular tag, the
// "latest" tag is assumed.
2015-07-23 00:52:22 +02:00
func (c Container) ImageName() string {
imageName := c.containerInfo.Config.Image
if !strings.Contains(imageName, ":") {
imageName = fmt.Sprintf("%s:latest", imageName)
}
return imageName
}
2015-08-01 00:23:17 +02:00
// Links returns a list containing the names of all the containers to which
// this container is linked.
func (c Container) Links() []string {
2015-07-21 23:40:22 +02:00
var links []string
if (c.containerInfo != nil) && (c.containerInfo.HostConfig != nil) {
for _, link := range c.containerInfo.HostConfig.Links {
name := strings.Split(link, ":")[0]
links = append(links, name)
}
}
return links
}
2015-08-01 00:23:17 +02:00
// IsWatchtower returns a boolean flag indicating whether or not the current
// container is the watchtower container itself. The watchtower container is
// identified by the presence of the "com.centurylinklabs.watchtower" label in
// the container metadata.
2015-07-21 00:54:18 +02:00
func (c Container) IsWatchtower() bool {
2015-07-23 00:52:22 +02:00
val, ok := c.containerInfo.Config.Labels[watchtowerLabel]
2015-07-21 00:54:18 +02:00
return ok && val == "true"
}
2015-08-01 00:23:17 +02:00
// StopSignal returns the custom stop signal (if any) that is encoded in the
// container's metadata. If the container has not specified a custom stop
// signal, the empty string "" is returned.
2015-07-23 00:52:22 +02:00
func (c Container) StopSignal() string {
if val, ok := c.containerInfo.Config.Labels[signalLabel]; ok {
return val
}
return ""
}
// Ideally, we'd just be able to take the ContainerConfig from the old container
// and use it as the starting point for creating the new container; however,
// the ContainerConfig that comes back from the Inspect call merges the default
// configuration (the stuff specified in the metadata for the image itself)
// with the overridden configuration (the stuff that you might specify as part
// of the "docker run"). In order to avoid unintentionally overriding the
// defaults in the new image we need to separate the override options from the
// default options. To do this we have to compare the ContainerConfig for the
// running container with the ContainerConfig from the image that container was
// started from. This function returns a ContainerConfig which contains just
// the options overridden at runtime.
func (c Container) runtimeConfig() *dockerclient.ContainerConfig {
config := c.containerInfo.Config
imageConfig := c.imageInfo.Config
if config.WorkingDir == imageConfig.WorkingDir {
config.WorkingDir = ""
}
if config.User == imageConfig.User {
config.User = ""
}
if sliceEqual(config.Cmd, imageConfig.Cmd) {
2015-07-21 00:54:18 +02:00
config.Cmd = nil
}
if sliceEqual(config.Entrypoint, imageConfig.Entrypoint) {
2015-07-21 00:54:18 +02:00
config.Entrypoint = nil
}
config.Env = sliceSubtract(config.Env, imageConfig.Env)
config.Labels = stringMapSubtract(config.Labels, imageConfig.Labels)
config.Volumes = structMapSubtract(config.Volumes, imageConfig.Volumes)
config.ExposedPorts = structMapSubtract(config.ExposedPorts, imageConfig.ExposedPorts)
2015-07-21 23:40:22 +02:00
for p := range c.containerInfo.HostConfig.PortBindings {
config.ExposedPorts[p] = struct{}{}
}
return config
}
// Any links in the HostConfig need to be re-written before they can be
// re-submitted to the Docker create API.
func (c Container) hostConfig() *dockerclient.HostConfig {
hostConfig := c.containerInfo.HostConfig
for i, link := range hostConfig.Links {
name := link[0:strings.Index(link, ":")]
alias := link[strings.LastIndex(link, "/"):]
hostConfig.Links[i] = fmt.Sprintf("%s:%s", name, alias)
}
return hostConfig
}