// Images returns a list of all the named images in the local repository func Images() ([]*Image, error) { dc, err := dockerclient.NewClient(dockerep) if err != nil { return nil, err } imgs, err := dc.ListImages(false) if err != nil { return nil, err } re := regexp.MustCompile("<none>:<none>") resp := []*Image{} for _, img := range imgs { for _, repotag := range img.RepoTags { if len(re.FindString(repotag)) > 0 { continue } iid, err := commons.ParseImageID(repotag) if err != nil { return resp, err } resp = append(resp, &Image{img.ID, *iid}) } } return resp, nil }
// Stop stops the container specified by the id. If the container can't be stopped before the timeout // expires an error is returned. func (c *Container) Stop(timeout time.Duration) error { dc, err := dockerclient.NewClient(dockerep) if err != nil { return err } return dc.StopContainer(c.ID, uint(timeout.Seconds())) }
// Inspect returns information about the container specified by id. func (c *Container) Inspect() (*dockerclient.Container, error) { dc, err := dockerclient.NewClient(dockerep) if err != nil { return nil, err } return dc.InspectContainer(c.ID) }
// Delete remove the image from the local repository func (img *Image) Delete() error { dc, err := dockerclient.NewClient(dockerep) if err != nil { return err } return dc.RemoveImage(img.ID.String()) }
// Export writes the contents of the container's filesystem as a tar archive to outfile. func (c *Container) Export(outfile *os.File) error { dc, err := dockerclient.NewClient(dockerep) if err != nil { return err } return dc.ExportContainer(dockerclient.ExportContainerOptions{c.ID, outfile}) }
// Kill sends a SIGKILL signal to the container. If the container is not started // no action is taken. func (c *Container) Kill() error { dc, err := dockerclient.NewClient(dockerep) if err != nil { return err } return dc.KillContainer(dockerclient.KillContainerOptions{ID: c.ID, Signal: dockerclient.SIGKILL}) }
// Delete removes the container. func (c *Container) Delete(volumes bool) error { dc, err := dockerclient.NewClient(dockerep) if err != nil { return err } return dc.RemoveContainer(dockerclient.RemoveContainerOptions{ID: c.ID, RemoveVolumes: volumes}) }
// Commit creates a new Image from the containers changes. func (c *Container) Commit(iidstr string) (*Image, error) { dc, err := dockerclient.NewClient(dockerep) if err != nil { return nil, err } iid, err := commons.ParseImageID(iidstr) if err != nil { return nil, err } img, err := dc.CommitContainer( dockerclient.CommitContainerOptions{ Container: c.ID, Repository: iid.BaseName(), }) if err != nil { glog.V(1).Infof("unable to commit container %s: %v", c.ID, err) return nil, err } if useRegistry { err = pushImage(iid.BaseName(), iid.Registry(), iid.Tag) } return &Image{img.ID, *iid}, err }
func InspectImage(uuid string) (*dockerclient.Image, error) { dc, err := dockerclient.NewClient(dockerep) if err != nil { return nil, err } return dc.InspectImage(uuid) }
// ImportImage creates a new image in the local repository from a file system archive. func ImportImage(repotag, filename string) error { dc, err := dockerclient.NewClient(dockerep) if err != nil { return err } glog.V(1).Infof("importing image %s from %s", repotag, filename) f, err := os.Open(filename) if err != nil { return err } defer f.Close() iid, err := commons.ParseImageID(repotag) if err != nil { return err } opts := dockerclient.ImportImageOptions{ Repository: iid.BaseName(), Source: "-", InputStream: f, Tag: iid.Tag, } if err = dc.ImportImage(opts); err != nil { glog.V(1).Infof("unable to import %s: %v", repotag, err) return err } return err }
// Opens a connection to docker if not already connected func (a *api) connectDocker() (*dockerclient.Client, error) { if a.docker == nil { const DockerEndpoint string = "unix:///var/run/docker.sock" var err error if a.docker, err = dockerclient.NewClient(DockerEndpoint); err != nil { return nil, fmt.Errorf("could not create a client to docker: %s", err) } } return a.docker, nil }
// FindContainer looks up a container using its id or name. func FindContainer(id string) (*Container, error) { dc, err := dockerclient.NewClient(dockerep) if err != nil { return nil, err } ctr, err := dc.InspectContainer(id) if err != nil { if _, ok := err.(*dockerclient.NoSuchContainer); ok { return nil, ErrNoSuchContainer } return nil, err } return &Container{ctr, dockerclient.HostConfig{}}, nil }
// init starts up the kernel loop that is responsible for handling all the API calls // in a goroutine. func init() { trues := []string{"1", "true", "t", "yes"} if v := strings.ToLower(os.Getenv(sdr)); v != "" { for _, t := range trues { if v == t { useRegistry = true } } } client, err := dockerclient.NewClient(dockerep) if err != nil { panic(fmt.Sprintf("can't create Docker client: %v", err)) } go kernel(client, done) }
// Containers retrieves a list of all the Docker containers. func Containers() ([]*Container, error) { dc, err := dockerclient.NewClient(dockerep) if err != nil { return nil, err } apictrs, err := dc.ListContainers(dockerclient.ListContainersOptions{All: true}) if err != nil { return nil, err } resp := []*Container{} for _, apictr := range apictrs { ctr, err := dc.InspectContainer(apictr.ID) if err != nil { continue } resp = append(resp, &Container{ctr, dockerclient.HostConfig{}}) } return resp, nil }
// Start uses the information provided in the container definition cd to start a new Docker // container. If a container can't be started before the timeout expires an error is returned. func (c *Container) Start(timeout time.Duration) error { if c.State.Running != false { return nil } dc, err := dockerclient.NewClient(dockerep) if err != nil { return err } args := struct { id string hostConfig *dockerclient.HostConfig }{c.ID, &c.HostConfig} // check to see if the container is already running ctr, err := dc.InspectContainer(args.id) if err != nil { glog.V(1).Infof("unable to inspect container %s prior to starting it: %v", args.id, err) return err } if ctr.State.Running { return ErrAlreadyStarted } glog.V(2).Infof("starting container %s: %+v", args.id, args.hostConfig) err = dc.StartContainer(args.id, args.hostConfig) if err != nil { glog.V(2).Infof("unable to start %s: %v", args.id, err) return err } glog.V(2).Infof("update container %s state post start", args.id) ctr, err = dc.InspectContainer(args.id) if err != nil { glog.V(2).Infof("failed to update container %s state post start: %v", args.id, err) return err } c.Container = ctr return nil }
func pullImage(repo, registry, tag string) error { dc, err := dockerclient.NewClient(dockerep) if err != nil { return err } glog.V(2).Info("pulling image: ", repo) opts := dockerclient.PullImageOptions{ Repository: repo, Registry: registry, Tag: tag, } // FIXME: Need to populate AuthConfiguration (eventually) err = dc.PullImage(opts, dockerclient.AuthConfiguration{}) if err != nil { glog.V(2).Infof("failed to pull %s: %v", repo, err) return err } return nil }
// Tag tags an image in the local repository func (img *Image) Tag(tag string) (*Image, error) { iid, err := commons.ParseImageID(tag) if err != nil { return nil, err } dc, err := dockerclient.NewClient(dockerep) if err != nil { return nil, err } args := struct { uuid string name string repo string registry string tag string }{img.UUID, img.ID.String(), iid.BaseName(), iid.Registry(), iid.Tag} glog.V(1).Infof("tagging image %s as: %s", args.repo, args.tag) opts := dockerclient.TagImageOptions{Repo: args.repo, Tag: args.tag, Force: true} err = dc.TagImage(args.name, opts) if err != nil { glog.V(1).Infof("unable to tag image %s: %v", args.repo, err) return nil, err } if useRegistry { pushImage(args.repo, args.registry, args.tag) } iid, err = commons.ParseImageID(fmt.Sprintf("%s:%s", args.repo, args.tag)) if err != nil { return nil, err } return &Image{args.uuid, *iid}, nil }
// Wait blocks until the container stops or the timeout expires and then returns its exit code. func (c *Container) Wait(timeout time.Duration) (int, error) { dc, err := dockerclient.NewClient(dockerep) if err != nil { return -127, err } type waitResult struct { rc int err error } errc := make(chan waitResult, 1) go func() { rc, err := dc.WaitContainer(c.ID) errc <- waitResult{rc, err} }() select { case <-time.After(timeout): case result := <-errc: return result.rc, result.err } return -127, ErrRequestTimeout }
func pushImage(repo, registry, tag string) error { dc, err := dockerclient.NewClient(dockerep) if err != nil { return err } glog.V(0).Infof("pushing image from repo: %s to registry: %s with tag: %s", repo, registry, tag) opts := dockerclient.PushImageOptions{ Name: repo, Registry: registry, Tag: tag, } // FIXME: Need to populate AuthConfiguration (eventually) err = dc.PushImage(opts, dockerclient.AuthConfiguration{}) if err != nil { glog.V(2).Infof("failed to push %s: %v", repo, err) return err } glog.V(0).Infof("finished pushing image from repo: %s to registry: %s with tag: %s", repo, registry, tag) return nil }
"github.com/control-center/serviced/commons" "github.com/control-center/serviced/commons/docker" "github.com/control-center/serviced/dao" "github.com/control-center/serviced/datastore" "github.com/control-center/serviced/domain/service" "github.com/control-center/serviced/domain/servicedefinition" "github.com/control-center/serviced/domain/servicetemplate" "github.com/control-center/serviced/isvcs" ) type reloadLogstashContainer func(ctx datastore.Context, f *Facade) error var LogstashContainerReloader reloadLogstashContainer = reloadLogstashContainerImpl var getDockerClient = func() (*dockerclient.Client, error) { return dockerclient.NewClient("unix:///var/run/docker.sock") } //AddServiceTemplate adds a service template to the system. Returns the id of the template added func (f *Facade) AddServiceTemplate(ctx datastore.Context, serviceTemplate servicetemplate.ServiceTemplate) (string, error) { hash, err := serviceTemplate.Hash() if err != nil { return "", err } serviceTemplate.ID = hash if st, _ := f.templateStore.Get(ctx, hash); st != nil { // This id already exists in the system glog.Infof("Not replacing existing template %s", hash) return hash, nil }
// NewContainer creates a new container and returns its id. The supplied create action, if // any, will be executed on successful creation of the container. If a start action is specified // it will be executed after the container has been started. Note, if the start parameter is // false the container won't be started and the start action will not be executed. func NewContainer(cd *ContainerDefinition, start bool, timeout time.Duration, oncreate ContainerActionFunc, onstart ContainerActionFunc) (*Container, error) { args := struct { containerOptions *dockerclient.CreateContainerOptions hostConfig *dockerclient.HostConfig start bool createaction ContainerActionFunc startaction ContainerActionFunc }{&cd.CreateContainerOptions, &cd.HostConfig, start, oncreate, onstart} timeoutc := time.After(timeout) dc, err := dockerclient.NewClient(dockerep) if err != nil { return nil, err } em, err := dc.MonitorEvents() if err != nil { return nil, fmt.Errorf("can't monitor Docker events: %v", err) } iid, err := commons.ParseImageID(args.containerOptions.Config.Image) if err != nil { return nil, err } if useRegistry { if err := PullImage(iid.String()); err != nil { glog.V(2).Infof("Unable to pull image %s: %v", iid.String(), err) if _, err2 := lookupImage(iid.String()); err2 != nil { return nil, err2 } } } glog.V(2).Infof("creating container: %#v", *args.containerOptions) ctr, err := dc.CreateContainer(*args.containerOptions) switch { case err == dockerclient.ErrNoSuchImage: if err := PullImage(iid.String()); err != nil { glog.V(2).Infof("Unable to pull image %s: %v", iid.String(), err) return nil, err } ctr, err = dc.CreateContainer(*args.containerOptions) if err != nil { glog.V(2).Infof("container creation failed %+v: %v", *args.containerOptions, err) return nil, err } case err != nil: glog.V(2).Infof("container creation failed %+v: %v", *args.containerOptions, err) return nil, err } glog.V(2).Infof("created container: %+v", *ctr) if args.createaction != nil { args.createaction(ctr.ID) } if args.start { ss, err := em.Subscribe(ctr.ID) if err != nil { return nil, err } sc := make(chan struct{}) ss.Handle(Start, func(e dockerclient.Event) error { if args.startaction != nil { args.startaction(ctr.ID) } glog.V(2).Infof("handling event: %+v for %s", e, ctr.ID) close(sc) return nil }) defer ss.Cancel() glog.V(2).Infof("post creation start of %s: %+v", ctr.ID, args.hostConfig) err = dc.StartContainer(ctr.ID, args.hostConfig) if err != nil { glog.V(1).Infof("post creation start of %s failed: %v", ctr.ID, err) return nil, err } glog.V(2).Infof("======= wait for %s to start =======", ctr.ID) attempts := 0 WaitForContainerStart: for { select { case <-timeoutc: glog.V(2).Infof("timeout starting container") return nil, fmt.Errorf("docker timeout starting container after %s", timeout) case <-sc: glog.V(2).Infof("update container %s state post start", ctr.ID) ctrID := ctr.ID ctr, err = dc.InspectContainer(ctrID) if err != nil { glog.V(1).Infof("failed to update container %s state post start: %v", ctrID, err) return nil, err } glog.V(2).Infof("container %s is started", ctr.ID) break WaitForContainerStart case <-time.After(5 * time.Second): nctr, err := dc.InspectContainer(ctr.ID) if err != nil { glog.V(2).Infof("can't inspect container %s: %v", ctr.ID, err) return nil, err } ctr = nctr switch { case !ctr.State.Running && attempts > maxStartAttempts: glog.V(2).Infof("timed out starting container") return nil, fmt.Errorf("timed out starting container: %s", ctr.ID) case !ctr.State.Running: attempts = attempts + 1 continue WaitForContainerStart default: glog.V(2).Infof("container %s is running", ctr.ID) break WaitForContainerStart } } } } return &Container{ctr, cd.HostConfig}, nil }