// TODO: skip errors flag func RmData(do *definitions.Do) (err error) { if len(do.Operations.Args) == 0 { do.Operations.Args = []string{do.Name} } for _, name := range do.Operations.Args { do.Name = name if util.IsDataContainer(do.Name, do.Operations.ContainerNumber) { log.WithField("=>", do.Name).Info("Removing data container") srv := definitions.BlankServiceDefinition() srv.Operations.SrvContainerName = util.ContainersName("data", do.Name, do.Operations.ContainerNumber) if err = perform.DockerRemove(srv.Service, srv.Operations, false, do.Volumes); err != nil { log.Errorf("Error removing %s: %v", do.Name, err) return err } } else { err = fmt.Errorf("I cannot find that data container for %s. Please check the data container name you sent me.", do.Name) log.Error(err) return err } if do.RmHF { log.WithField("=>", do.Name).Warn("Removing host directory") if err = os.RemoveAll(filepath.Join(DataContainersPath, do.Name)); err != nil { return err } } } do.Result = "success" return err }
// Return container links. For sake of simplicity, don't expose // anything else. func Links(name string, t string, n int) []string { container, err := util.DockerClient.InspectContainer(util.ContainersName(t, name, n)) if err != nil { return []string{} } return container.HostConfig.Links }
// links and mounts for service dependencies func connectToAService(srv *definitions.Service, ops *definitions.Operation, typ, name, internalName string, link, mount bool) { log.WithFields(log.Fields{ "=>": srv.Name, "type": typ, "name": name, "internal name": internalName, "link": link, "volumes from": mount, }).Debug("Connecting to service") containerName := util.ContainersName(typ, name, ops.ContainerNumber) if link { newLink := containerName + ":" + internalName srv.Links = append(srv.Links, newLink) } if mount { // Automagically mount VolumesFrom for serviceDeps so they can // easily pass files back and forth. note that this is opinionated // and will mount as read-write. we can revisit this if read-only // mounting required for specific use cases newVol := containerName + ":rw" srv.VolumesFrom = append(srv.VolumesFrom, newVol) } }
func RmData(do *definitions.Do) error { if util.IsDataContainer(do.Name, do.Operations.ContainerNumber) { logger.Infoln("Removing data container " + do.Name) srv := definitions.BlankServiceDefinition() srv.Operations.SrvContainerName = util.ContainersName("data", do.Name, do.Operations.ContainerNumber) err := perform.DockerRemove(srv.Service, srv.Operations, false) if err != nil { return err } } else { return fmt.Errorf("I cannot find that data container. Please check the data container name you sent me.") } if do.RmHF { logger.Println("Removing host folder " + do.Name) err := os.RemoveAll(path.Join(DataContainersPath, do.Name)) if err != nil { return err } } do.Result = "success" return nil }
// Remove a container of some name, type, and number. func RemoveContainer(name string, t string, n int) error { opts := docker.RemoveContainerOptions{ ID: util.ContainersName(t, name, n), RemoveVolumes: true, Force: true, } if err := util.DockerClient.RemoveContainer(opts); err != nil { return err } return nil }
func InspectData(do *definitions.Do) error { if util.IsDataContainer(do.Name, do.Operations.ContainerNumber) { log.WithField("=>", do.Name).Info("Inspecting data container") srv := definitions.BlankServiceDefinition() srv.Operations.SrvContainerName = util.ContainersName(definitions.TypeData, do.Name, do.Operations.ContainerNumber) err := perform.DockerInspect(srv.Service, srv.Operations, do.Operations.Args[0]) if err != nil { return err } } else { return fmt.Errorf("I cannot find that data container. Please check the data container name you sent me.") } do.Result = "success" return nil }
// links and mounts for service dependencies func connectToAService(srv *definitions.Service, ops *definitions.Operation, typ, name, internalName string, link, mount bool) { logger.Debugf("Connecting service %s to %s %s (%s) with link (%v) and volumes-from (%v)\n", srv.Name, typ, name, internalName, link, mount) containerName := util.ContainersName(typ, name, ops.ContainerNumber) if link { newLink := containerName + ":" + internalName srv.Links = append(srv.Links, newLink) } if mount { // Automagically mount VolumesFrom for serviceDeps so they can // easily pass files back and forth. note that this is opinionated // and will mount as read-write. we can revisit this if read-only // mounting required for specific use cases newVol := containerName + ":rw" srv.VolumesFrom = append(srv.VolumesFrom, newVol) } }
func RenameData(do *definitions.Do) error { logger.Infof("Renaming Data =>\t\t%s:%s\n", do.Name, do.NewName) logger.Debugf("\twith ContainerNumber =>\t%d\n", do.Operations.ContainerNumber) if util.IsDataContainer(do.Name, do.Operations.ContainerNumber) { srv := definitions.BlankServiceDefinition() srv.Operations.SrvContainerName = util.ContainersName("data", do.Name, do.Operations.ContainerNumber) err := perform.DockerRename(srv.Service, srv.Operations, do.Name, do.NewName) if err != nil { return err } } else { return fmt.Errorf("I cannot find that data container. Please check the data container name you sent me.") } do.Result = "success" return nil }
//------------------------------------------------------------------------ func startChain(do *definitions.Do, exec bool) error { chain, err := loaders.LoadChainDefinition(do.Name, false, do.Operations.ContainerNumber) if err != nil { logger.Errorln("Cannot start a chain I cannot find.") do.Result = "no file" return nil } if chain.Name == "" { logger.Errorln("Cannot start a chain without a name.") do.Result = "no name" return nil } // boot the dependencies (eg. keys) if err := bootDependencies(chain, do); err != nil { return err } chain.Service.Command = loaders.ErisChainStart util.Merge(chain.Operations, do.Operations) chain.Service.Environment = append(chain.Service.Environment, "CHAIN_ID="+chain.ChainID) chain.Service.Environment = append(chain.Service.Environment, do.Env...) if do.Run { chain.Service.Environment = append(chain.Service.Environment, "ERISDB_API=true") } chain.Service.Links = append(chain.Service.Links, do.Links...) logger.Infof("StartChainRaw to DockerRunService =>\t%s\n", chain.Service.Name) logger.Debugf("\twith ChainID =>\t\t%v\n", chain.ChainID) logger.Debugf("\twith Environment =>\t%v\n", chain.Service.Environment) logger.Debugf("\twith AllPortsPublshd =>\t%v\n", chain.Operations.PublishAllPorts) if exec { if do.Image != "" { chain.Service.Image = do.Image } chain.Operations.Args = do.Operations.Args logger.Debugf("\twith Args =>\t\t%v:%v\n", chain.Operations.Args, chain.Operations.Interactive) // This override is necessary because erisdb uses an entryPoint and // the perform package will respect the images entryPoint if it // exists. chain.Service.EntryPoint = "" chain.Service.Command = "" // there is literally never a reason not to randomize the ports. chain.Operations.PublishAllPorts = true // always link the chain to the exec container when doing chains exec // so that there is never any problems with sending info to the service (chain) container chain.Service.Links = append(chain.Service.Links, fmt.Sprintf("%s:%s", util.ContainersName("chain", chain.Name, 1), "chain")) err = perform.DockerExecService(chain.Service, chain.Operations) } else { err = perform.DockerRunService(chain.Service, chain.Operations) } if err != nil { do.Result = "error" return err } return nil }
// DockerRename renames the container by removing and recreating it. The container // is also restarted if it was running before rename. The container ops.SrvContainerName // is renamed to a new name, constructed using a short given newName. // DockerRename returns Docker errors on exit or ErrContainerExists // if the container with the new (long) name exists. // // ops.SrvContainerName - container name // ops.ContainerNumber - container number // ops.ContainerType - container type // ops.Labels - container creation time labels // func DockerRename(ops *def.Operation, newName string) error { longNewName := util.ContainersName(ops.ContainerType, newName, ops.ContainerNumber) logger.Infof("Renaming container =>\t\t%s to %s\n", ops.SrvContainerName, longNewName) logger.Debugln("\tChecking container exist") container, err := util.DockerClient.InspectContainer(ops.SrvContainerName) if err != nil { return err } logger.Debugln("\tChecking new container exist (should fail)") _, err = util.DockerClient.InspectContainer(longNewName) if err == nil { return ErrContainerExists } // Mark if the container's running to restart it later. _, wasRunning := ContainerRunning(ops) if wasRunning { logger.Debugln("\tStopping container") if err := util.DockerClient.StopContainer(container.ID, 5); err != nil { logger.Debugln("\tNot stopped") } } logger.Debugln("\tRemoving container") removeOpts := docker.RemoveContainerOptions{ ID: container.ID, RemoveVolumes: true, Force: true, } if err := util.DockerClient.RemoveContainer(removeOpts); err != nil { return err } logger.Debugln("\tCreating the new container") createOpts := docker.CreateContainerOptions{ Name: longNewName, Config: container.Config, HostConfig: container.HostConfig, } // If VolumesFrom contains links to non-existent containers, remove them. var newVolumesFrom []string for _, name := range createOpts.HostConfig.VolumesFrom { _, err = util.DockerClient.InspectContainer(name) if err != nil { continue } name = strings.TrimSuffix(name, ":ro") name = strings.TrimSuffix(name, ":rw") newVolumesFrom = append(newVolumesFrom, name) } createOpts.HostConfig.VolumesFrom = newVolumesFrom // Rename labels. createOpts.Config.Labels = util.Labels(newName, ops) newContainer, err := util.DockerClient.CreateContainer(createOpts) if err != nil { logger.Debugln("Not created") return err } // Was running before remove. if wasRunning { err := util.DockerClient.StartContainer(newContainer.ID, createOpts.HostConfig) if err != nil { logger.Debugln("Not restarted") } } logger.Infoln("Container renamed") return nil }