// 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 }
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 }
// ImportData does what it says. It imports from a host's Source to a Dest // in a data container. It returns an error. // // do.Name - name of the data container to use (required) // do.Operations.ContainerNumber - container number (optional) // do.Source - directory which should be imported (required) // do.Destination - directory to _unload_ the payload into (required) // func ImportData(do *definitions.Do) error { log.WithFields(log.Fields{ "from": do.Source, "to": do.Destination, }).Debug("Importing") if util.IsDataContainer(do.Name, do.Operations.ContainerNumber) { srv := PretendToBeAService(do.Name, do.Operations.ContainerNumber) service, exists := perform.ContainerExists(srv.Operations) if !exists { return fmt.Errorf("There is no data container for that service.") } if err := checkErisContainerRoot(do, "import"); err != nil { return err } containerName := util.DataContainersName(do.Name, do.Operations.ContainerNumber) os.Chdir(do.Source) reader, err := util.Tar(do.Source, 0) if err != nil { return err } defer reader.Close() opts := docker.UploadToContainerOptions{ InputStream: reader, Path: do.Destination, NoOverwriteDirNonDir: true, } log.WithField("=>", containerName).Info("Copying into container") log.WithField("path", do.Source).Debug() if err := util.DockerClient.UploadToContainer(service.ID, opts); err != nil { return err } doChown := definitions.NowDo() doChown.Operations.DataContainerName = containerName doChown.Operations.ContainerType = "data" doChown.Operations.ContainerNumber = do.Operations.ContainerNumber //required b/c `docker cp` (UploadToContainer) goes in as root doChown.Operations.Args = []string{"chown", "--recursive", "eris", do.Destination} _, err = perform.DockerRunData(doChown.Operations, nil) if err != nil { return fmt.Errorf("Error changing owner: %v\n", err) } } else { log.WithField("name", do.Name).Info("Data container does not exist.") ops := loaders.LoadDataDefinition(do.Name, do.Operations.ContainerNumber) if err := perform.DockerCreateData(ops); err != nil { return fmt.Errorf("Error creating data container %v.", err) } return ImportData(do) } do.Result = "success" return nil }
func ImportData(do *definitions.Do) error { if util.IsDataContainer(do.Name, do.Operations.ContainerNumber) { srv := PretendToBeAService(do.Name, do.Operations.ContainerNumber) service, exists := perform.ContainerExists(srv.Operations) if !exists { return fmt.Errorf("There is no data container for that service.") } containerName := util.DataContainersName(do.Name, do.Operations.ContainerNumber) logger.Debugf("Importing FROM =>\t\t%s\n", do.Source) os.Chdir(do.Source) logger.Debugf("Importing TO =>\t\t\t%s\n", do.Destination) reader, err := util.Tar(do.Source, 0) if err != nil { return err } defer reader.Close() opts := docker.UploadToContainerOptions{ InputStream: reader, Path: do.Destination, NoOverwriteDirNonDir: true, } logger.Infof("Copying into Cont. ID =>\t%s\n", service.ID) logger.Debugf("\tPath =>\t\t\t%s\n", do.Source) if err := util.DockerClient.UploadToContainer(service.ID, opts); err != nil { return err } doChown := definitions.NowDo() doChown.Operations.DataContainerName = containerName doChown.Operations.ContainerType = "data" doChown.Operations.ContainerNumber = 1 doChown.Operations.Args = []string{"chown", "--recursive", "eris", do.Destination} _, err = perform.DockerRunData(doChown.Operations, nil) if err != nil { return fmt.Errorf("Error changing owner: %v\n", err) } } else { ops := loaders.LoadDataDefinition(do.Name, do.Operations.ContainerNumber) if err := perform.DockerCreateData(ops); err != nil { return fmt.Errorf("Error creating data container %v.", err) } return ImportData(do) } do.Result = "success" return nil }
func ExecData(do *definitions.Do) error { if util.IsDataContainer(do.Name, do.Operations.ContainerNumber) { do.Name = util.DataContainersName(do.Name, do.Operations.ContainerNumber) logger.Infoln("Running exec on container with volumes from data container " + do.Name) if err := perform.DockerRunVolumesFromContainer(do.Name, do.Interactive, do.Args); 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 RegisterChain(do *definitions.Do) error { // do.Name is mandatory if do.Name == "" { return fmt.Errorf("RegisterChain requires a chainame") } etcbChain := do.ChainID do.ChainID = do.Name // NOTE: registration expects you to have the data container if !util.IsDataContainer(do.Name, do.Operations.ContainerNumber) { return fmt.Errorf("Registration requires you to have a data container for the chain. Could not find data for %s", do.Name) } chain, err := loaders.LoadChainDefinition(do.Name, false, do.Operations.ContainerNumber) if err != nil { return err } log.WithField("image", chain.Service.Image).Debug("Chain loaded") // set chainid and other vars envVars := []string{ fmt.Sprintf("CHAIN_ID=%s", do.ChainID), // of the etcb chain fmt.Sprintf("PUBKEY=%s", do.Pubkey), // pubkey to register chain with fmt.Sprintf("ETCB_CHAIN_ID=%s", etcbChain), // chain id of the etcb chain fmt.Sprintf("NODE_ADDR=%s", do.Gateway), // etcb node to send the register tx to fmt.Sprintf("NEW_P2P_SEEDS=%s", do.Operations.Args[0]), // seeds to register for the chain // TODO: deal with multi seed (needs support in tendermint) } envVars = append(envVars, do.Env...) log.WithFields(log.Fields{ "environment": envVars, "links": do.Links, }).Debug("Registering chain with") chain.Service.Environment = append(chain.Service.Environment, envVars...) chain.Service.Links = append(chain.Service.Links, do.Links...) if err := bootDependencies(chain, do); err != nil { return err } log.WithFields(log.Fields{ "=>": chain.Service.Name, "image": chain.Service.Image, }).Debug("Performing chain container start") chain.Operations = loaders.LoadDataDefinition(chain.Service.Name, do.Operations.ContainerNumber) chain.Operations.Args = []string{loaders.ErisChainRegister} _, err = perform.DockerRunData(chain.Operations, chain.Service) return err }
func ExecData(do *definitions.Do) error { if util.IsDataContainer(do.Name, do.Operations.ContainerNumber) { log.WithField("=>", do.Operations.DataContainerName).Info("Executing data container") ops := loaders.LoadDataDefinition(do.Name, do.Operations.ContainerNumber) util.Merge(ops, do.Operations) if err := perform.DockerExecData(ops, nil); err != nil { return err } } else { return fmt.Errorf("The marmots cannot find that data container.\nPlease check the name of the data container with [eris data ls].") } do.Result = "success" 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 }
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) { ops := loaders.LoadDataDefinition(do.Name, do.Operations.ContainerNumber) util.Merge(ops, do.Operations) err := perform.DockerRename(ops, 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 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 RenameData(do *definitions.Do) error { log.WithFields(log.Fields{ "from": fmt.Sprintf("%s:%d", do.Name, do.Operations.ContainerNumber), "to": fmt.Sprintf("%s:%d", do.NewName, do.Operations.ContainerNumber), }).Info("Renaming data container") if util.IsDataContainer(do.Name, do.Operations.ContainerNumber) { ops := loaders.LoadDataDefinition(do.Name, do.Operations.ContainerNumber) util.Merge(ops, do.Operations) err := perform.DockerRename(ops, 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 ImportData(do *definitions.Do) error { if util.IsDataContainer(do.Name, do.Operations.ContainerNumber) { containerName := util.DataContainersName(do.Name, do.Operations.ContainerNumber) importPath := filepath.Join(DataContainersPath, do.Name) // temp until docker cp works both ways. logger.Debugf("Importing FROM =>\t\t%s\n", importPath) os.Chdir(importPath) // TODO [eb]: deal with hardcoded user // TODO [csk]: drop the whole damn cmd call // use go's tar lib to make a tarball of the directory // read the tar file into an io.Reader // start a container with its Stdin open, connect to an io.Writer // connect them up with io.Pipe // this will free us from any quirks that the cli has if do.Path != "" { do.Path = do.Path } else { do.Path = "/home/eris/.eris" } logger.Debugf("Importing TO =>\t\t\t%s\n", do.Path) cmd := "tar chf - . | docker run -i --rm --volumes-from " + containerName + " --user eris eris/data tar xf - -C " + do.Path _, err := pipes.RunString(cmd) if err != nil { cmd := "tar chf - . | docker run -i --volumes-from " + containerName + " --user eris eris/data tar xf - -C " + do.Path _, e2 := pipes.RunString(cmd) if e2 != nil { return fmt.Errorf("Could not import the data container.\nTried with docker --rm =>\t%v\nTried without docker --rm =>\t%v", err, e2) } } } else { if err := perform.DockerCreateDataContainer(do.Name, do.Operations.ContainerNumber); err != nil { return fmt.Errorf("Error creating data container %v.", err) } return ImportData(do) } do.Result = "success" return nil }
//export from: do.Source(in container), to: do.Destination(on host) func ExportData(do *definitions.Do) error { if util.IsDataContainer(do.Name, do.Operations.ContainerNumber) { log.WithField("=>", do.Name).Info("Exporting data container") // we want to export to a temp directory. exportPath, err := ioutil.TempDir(os.TempDir(), do.Name) // TODO: do.Operations.ContainerNumber ? defer os.Remove(exportPath) if err != nil { return err } containerName := util.DataContainersName(do.Name, do.Operations.ContainerNumber) srv := PretendToBeAService(do.Name, do.Operations.ContainerNumber) service, exists := perform.ContainerExists(srv.Operations) if !exists { return fmt.Errorf("There is no data container for that service.") } reader, writer := io.Pipe() defer reader.Close() if err := checkErisContainerRoot(do, "export"); err != nil { return err } opts := docker.DownloadFromContainerOptions{ OutputStream: writer, Path: do.Source, } go func() { log.WithField("=>", containerName).Info("Copying out of container") log.WithField("path", do.Source).Debug() IfExit(util.DockerClient.DownloadFromContainer(service.ID, opts)) // TODO: be smarter about catching this error writer.Close() }() log.WithField("=>", exportPath).Debug("Untarring package from container") if err = util.Untar(reader, do.Name, exportPath); err != nil { return err } // now if docker dumps to exportPath/.eris we should remove // move everything from .eris to exportPath if err := moveOutOfDirAndRmDir(filepath.Join(exportPath, ".eris"), exportPath); err != nil { return err } // finally remove everything in the data directory and move // the temp contents there if _, err := os.Stat(do.Destination); os.IsNotExist(err) { if e2 := os.MkdirAll(do.Destination, 0755); e2 != nil { return fmt.Errorf("Error:\tThe marmots could neither find, nor had access to make the directory: (%s)\n", do.Destination) } } if err := moveOutOfDirAndRmDir(exportPath, do.Destination); 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 ExportData(do *definitions.Do) error { if util.IsDataContainer(do.Name, do.Operations.ContainerNumber) { logger.Infoln("Exporting data container", do.Name) exportPath := filepath.Join(DataContainersPath, do.Name) // TODO: do.Operations.ContainerNumber ? srv := PretendToBeAService(do.Name, do.Operations.ContainerNumber) service, exists := perform.ContainerExists(srv.Operations) if !exists { return fmt.Errorf("There is no data container for that service.") } logger.Infoln("Service ID: " + service.ID) cont, err := util.DockerClient.InspectContainer(service.ID) if err != nil { return err } reader, writer := io.Pipe() if do.Path != "" { do.Path = do.Path } else { do.Path = "/home/eris/.eris" } opts := docker.CopyFromContainerOptions{ OutputStream: writer, Container: service.ID, Resource: do.Path, } go func() { IfExit(util.DockerClient.CopyFromContainer(opts)) writer.Close() }() err = util.Untar(reader, do.Name, exportPath) if err != nil { return err } // docker actually exports to a `_data` folder for volumes // this section of the function moves whatever docker dumps // into exportPath/_data into export. ranging through the // volumes is probably overkill as we could just assume // that it *was* `_data` but in case docker changes later // we'll just keep it for now. os.Chdir(exportPath) var unTarDestination string for k, v := range cont.Volumes { if k == "/home/eris/.eris" { unTarDestination = filepath.Base(v) } } if err := moveOutOfDirAndRmDir(filepath.Join(exportPath, unTarDestination), exportPath); err != nil { return err } // now if docker dumps to exportPath/.eris we should remove // move everything from .eris to exportPath if err := moveOutOfDirAndRmDir(filepath.Join(exportPath, ".eris"), exportPath); 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 }
// the main function for setting up a chain container // handles both "new" and "fetch" - most of the differentiating logic is in the container func setupChain(do *definitions.Do, cmd string) (err error) { // XXX: if do.Name is unique, we can safely assume (and we probably should) that do.Operations.ContainerNumber = 1 // do.Name is mandatory if do.Name == "" { return fmt.Errorf("setupChain requires a chainame") } containerName := util.ChainContainersName(do.Name, do.Operations.ContainerNumber) if do.ChainID == "" { do.ChainID = do.Name } //if given path does not exist, see if its a reference to something in ~/.eris/chains/chainName if do.Path != "" { src, err := os.Stat(do.Path) if err != nil || !src.IsDir() { log.WithField("path", do.Path).Info("Path does not exist or not a directory") log.WithField("path", "$HOME/.eris/chains/"+do.Path).Info("Trying") do.Path, err = util.ChainsPathChecker(do.Path) if err != nil { return err } } } else if do.GenesisFile == "" && do.CSV == "" && len(do.ConfigOpts) == 0 { // NOTE: this expects you to have ~/.eris/chains/default/ (ie. to have run `eris init`) do.Path, err = util.ChainsPathChecker("default") if err != nil { return err } } // ensure/create data container if util.IsDataContainer(do.Name, do.Operations.ContainerNumber) { log.WithField("=>", do.Name).Debug("Chain data container already exists") } else { ops := loaders.LoadDataDefinition(do.Name, do.Operations.ContainerNumber) if err := perform.DockerCreateData(ops); err != nil { return fmt.Errorf("Error creating data container =>\t%v", err) } } log.WithField("=>", do.Name).Debug("Chain data container built") // if something goes wrong, cleanup defer func() { if err != nil { log.Infof("Error on setting up chain: %v", err) log.Info("Cleaning up") if err2 := RmChain(do); err2 != nil { // maybe be less dramatic err = fmt.Errorf("Tragic! Our marmots encountered an error during setupChain for %s.\nThey also failed to cleanup after themselves (remove containers) due to another error.\nFirst error =>\t\t\t%v\nCleanup error =>\t\t%v\n", containerName, err, err2) } } }() // copy do.Path, do.GenesisFile, do.ConfigFile, do.Priv, do.CSV into container containerDst := filepath.Join("chains", do.Name) // path in container dst := filepath.Join(DataContainersPath, do.Name, containerDst) // path on host // TODO: deal with do.Operations.ContainerNumbers ....! // we probably need to update Import log.WithFields(log.Fields{ "container path": containerDst, "local path": dst, }).Debug() if err = os.MkdirAll(dst, 0700); err != nil { return fmt.Errorf("Error making data directory: %v", err) } // we accept two csvs: one for validators, one for accounts // if there's only one, its for validators and accounts var csvFiles []string var csvPaths string if do.CSV != "" { csvFiles = strings.Split(do.CSV, ",") if len(csvFiles) > 1 { csvPath1 := fmt.Sprintf("%s/%s/%s/%s", ErisContainerRoot, "chains", do.ChainID, "validators.csv") csvPath2 := fmt.Sprintf("%s/%s/%s/%s", ErisContainerRoot, "chains", do.ChainID, "accounts.csv") csvPaths = fmt.Sprintf("%s,%s", csvPath1, csvPath2) } else { csvPaths = fmt.Sprintf("%s/%s/%s/%s", ErisContainerRoot, "chains", do.ChainID, "genesis.csv") } } filesToCopy := []stringPair{ {do.Path, ""}, {do.GenesisFile, "genesis.json"}, {do.ConfigFile, "config.toml"}, {do.Priv, "priv_validator.json"}, } if len(csvFiles) == 1 { filesToCopy = append(filesToCopy, stringPair{csvFiles[0], "genesis.csv"}) } else if len(csvFiles) > 1 { filesToCopy = append(filesToCopy, stringPair{csvFiles[0], "validators.csv"}) filesToCopy = append(filesToCopy, stringPair{csvFiles[1], "accounts.csv"}) } log.Info("Copying chain files into the correct location") if err := copyFiles(dst, filesToCopy); err != nil { return err } // copy from host to container log.WithFields(log.Fields{ "from": dst, "to": containerDst, }).Debug("Copying files into data container") importDo := definitions.NowDo() importDo.Name = do.Name importDo.Operations = do.Operations importDo.Destination = ErisContainerRoot importDo.Source = filepath.Join(DataContainersPath, do.Name) if err = data.ImportData(importDo); err != nil { return err } chain := loaders.MockChainDefinition(do.Name, do.ChainID, false, do.Operations.ContainerNumber) //set maintainer info chain.Maintainer.Name, chain.Maintainer.Email, err = config.GitConfigUser() if err != nil { log.Debug(err.Error()) } // write the chain definition file ... fileName := filepath.Join(ChainsPath, do.Name) + ".toml" if _, err = os.Stat(fileName); err != nil { if err = WriteChainDefinitionFile(chain, fileName); err != nil { return fmt.Errorf("error writing chain definition to file: %v", err) } } chain, err = loaders.LoadChainDefinition(do.Name, false, do.Operations.ContainerNumber) if err != nil { return err } log.WithField("image", chain.Service.Image).Debug("Chain loaded") chain.Operations.PublishAllPorts = do.Operations.PublishAllPorts // TODO: remove this and marshall into struct from cli directly // cmd should be "new" or "install" chain.Service.Command = cmd // write the list of <key>:<value> config options as flags buf := new(bytes.Buffer) for _, cv := range do.ConfigOpts { spl := strings.Split(cv, "=") if len(spl) != 2 { return fmt.Errorf("Config options should be <key>=<value> pairs. Got %s", cv) } buf.WriteString(fmt.Sprintf(" --%s=%s", spl[0], spl[1])) } configOpts := buf.String() // set chainid and other vars envVars := []string{ fmt.Sprintf("CHAIN_ID=%s", do.ChainID), fmt.Sprintf("CONTAINER_NAME=%s", containerName), fmt.Sprintf("CSV=%v", csvPaths), // for mintgen fmt.Sprintf("CONFIG_OPTS=%s", configOpts), // for config.toml fmt.Sprintf("NODE_ADDR=%s", do.Gateway), // etcb host fmt.Sprintf("DOCKER_FIX=%s", " "), // https://github.com/docker/docker/issues/14203 } envVars = append(envVars, do.Env...) if do.Run { // run erisdb instead of tendermint envVars = append(envVars, "ERISDB_API=true") } log.WithFields(log.Fields{ "environment": envVars, "links": do.Links, }).Debug() chain.Service.Environment = append(chain.Service.Environment, envVars...) chain.Service.Links = append(chain.Service.Links, do.Links...) // TODO: if do.N > 1 ... chain.Operations.DataContainerName = util.DataContainersName(do.Name, do.Operations.ContainerNumber) if err := bootDependencies(chain, do); err != nil { return err } log.WithFields(log.Fields{ "=>": chain.Service.Name, "image": chain.Service.Image, }).Debug("Performing chain container start") err = perform.DockerRunService(chain.Service, chain.Operations) // this err is caught in the defer above return }
func ExportData(do *definitions.Do) error { if util.IsDataContainer(do.Name, do.Operations.ContainerNumber) { dVer, err := util.DockerClientVersion() if err != nil { return err } logger.Infoln("Exporting data container", do.Name) // we want to export to a temp directory. exportPath, err := ioutil.TempDir(os.TempDir(), do.Name) // TODO: do.Operations.ContainerNumber ? defer os.Remove(exportPath) if err != nil { return err } srv := PretendToBeAService(do.Name, do.Operations.ContainerNumber) service, exists := perform.ContainerExists(srv.Operations) if !exists { return fmt.Errorf("There is no data container for that service.") } cont, err := util.DockerClient.InspectContainer(service.ID) if err != nil { return err } reader, writer := io.Pipe() defer reader.Close() if do.Path != "" { do.Path = do.Path } else { do.Path = "/home/eris/.eris" } opts := docker.CopyFromContainerOptions{ OutputStream: writer, Container: service.ID, Resource: do.Path, } go func() { logger.Infof("Copying out of Cont. ID =>\t%s\n", service.ID) logger.Debugf("\tPath =>\t\t\t%s\n", do.Path) IfExit(util.DockerClient.CopyFromContainer(opts)) writer.Close() }() logger.Debugf("Untarring Package from Cont =>\t%s\n", exportPath) if err = util.Untar(reader, do.Name, exportPath); err != nil { return err } // docker actually exports to a `_data` folder for volumes // this section of the function moves whatever docker dumps // into exportPath/_data into export. ranging through the // volumes is probably overkill as we could just assume // that it *was* `_data` but in case docker changes later // we'll just keep it for now. this is specific to 1.7 and // below. For 1.8 we do not need to do this. os.Chdir(exportPath) var unTarDestination string for k, v := range cont.Volumes { if k == do.Path { unTarDestination = filepath.Base(v) } } logger.Debugf("Untarring to =>\t\t\t%s:%s\n", exportPath, unTarDestination) if dVer <= 1.7 { if err := moveOutOfDirAndRmDir(filepath.Join(exportPath, unTarDestination), exportPath); err != nil { return err } } // now if docker dumps to exportPath/.eris we should remove // move everything from .eris to exportPath if err := moveOutOfDirAndRmDir(filepath.Join(exportPath, ".eris"), exportPath); err != nil { return err } // finally remove everything in the data directory and move // the temp contents there prevDir := filepath.Join(DataContainersPath, do.Name) if _, err := os.Stat(prevDir); os.IsNotExist(err) { if e2 := os.MkdirAll(prevDir, 0666); e2 != nil { return fmt.Errorf("Error:\tThe marmots could neither find, nor had access to make the directory: (%s)\n", prevDir) } } ClearDir(prevDir) if err := moveOutOfDirAndRmDir(exportPath, prevDir); 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 }