func readActionDefinition(actionName []string, dropped map[string]string, varNum int) (*viper.Viper, map[string]string, error) { if len(actionName) == 0 { log.WithFields(log.Fields{ "action": actionName, "drop": dropped, "var#": varNum, }).Debug("Failed to load action definition file") return nil, dropped, fmt.Errorf("The marmots could not find the action definition file.\nPlease check your actions with [eris actions ls]") } log.WithField("file", strings.Join(actionName, "_")).Debug("Preparing to read action definition file") log.WithField("drop", dropped).Debug() var actionConf = viper.New() actionConf.AddConfigPath(dir.ActionsPath) actionConf.SetConfigName(strings.Join(actionName, "_")) err := actionConf.ReadInConfig() if err != nil { log.WithField("action", actionName[len(actionName)-1]).Debug("Dropping and retrying") dropped[fmt.Sprintf("$%d", varNum)] = actionName[len(actionName)-1] actionName = actionName[:len(actionName)-1] varNum++ return readActionDefinition(actionName, dropped, varNum) } else { log.Debug("Successfully read action definition file") } return actionConf, dropped, nil }
func TestRmChain(t *testing.T) { testStartChain(t, chainName) do := def.NowDo() do.Operations.Args, do.Rm, do.RmD = []string{"keys"}, true, true log.WithField("=>", do.Name).Info("Removing keys (from tests)") if e := services.KillService(do); e != nil { tests.IfExit(e) } do = def.NowDo() do.Name, do.Rm, do.RmD = chainName, false, false log.WithField("=>", do.Name).Info("Stopping chain (from tests)") if e := KillChain(do); e != nil { tests.IfExit(e) } testExistAndRun(t, chainName, true, false) do = def.NowDo() do.Name = chainName do.RmD = true log.WithField("=>", do.Name).Info("Removing chain (from tests)") if e := RmChain(do); e != nil { tests.IfExit(e) } testExistAndRun(t, chainName, false, false) }
func StartServicesAndChains(do *definitions.Do) error { // start the services and chains doSrvs := definitions.NowDo() if do.Action.Dependencies == nil || len(do.Action.Dependencies.Services) == 0 { log.Debug("No services to start") } else { doSrvs.Operations.Args = do.Action.Dependencies.Services log.WithField("args", doSrvs.Operations.Args).Debug("Starting services") if err := services.StartService(doSrvs); err != nil { return err } } doChns := definitions.NowDo() doChns.Name = do.Action.Chain if doChns.Name == "" { log.Debug("No chain to start") } else { log.WithField("=>", doChns.Name).Debug("Starting chain") if err := chains.StartChain(do); err != nil { return err } } return nil }
// 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 }
// lists the containers running for a chain/service // eventually remotes/actions // existing -> true to ls existing; false to ls running func ListRunningOrExisting(quiet, existing bool, typ string) (result string, err error) { re := "Running" if existing { re = "Existing" } log.WithField("status", strings.ToLower(re)).Debug("Asking Docker to list containers") //gotta go if quiet { if typ == "services" { result = strings.Join(util.ServiceContainerNames(existing), "\n") } if typ == "chains" { result = strings.Join(util.ChainContainerNames(existing), "\n") } } else { if typ == "services" { log.WithField("=>", fmt.Sprintf("service:%v", strings.ToLower(re))).Debug("Printing table") result, _ = PrintTableReport("service", existing, false) //false is for All, dealt with somewhere else } if typ == "chains" { log.WithField("=>", fmt.Sprintf("chain:%v", strings.ToLower(re))).Debugf("Printing table") result, _ = PrintTableReport("chain", existing, false) } } return result, nil }
// DockerStop stops a running ops.SrvContainerName container unforcedly. // timeout is a number of seconds to wait before killing the container process // ungracefully. // It returns Docker errors on exit if not successful. DockerStop doesn't return // an error if the container isn't running. func DockerStop(srv *def.Service, ops *def.Operation, timeout uint) error { // don't limit this to verbose because it takes a few seconds // [zr] unless force sets timeout to 0 (for, eg. stdout) if timeout != 0 { log.WithField("=>", srv.Name).Warn("Stopping (may take a few seconds)") } log.WithFields(log.Fields{ "=>": ops.SrvContainerName, "timeout": timeout, }).Info("Stopping container") _, running := ContainerExists(ops) if running { log.WithField("=>", ops.SrvContainerName).Debug("Container found running") err := stopContainer(ops.SrvContainerName, timeout) if err != nil { return err } } else { log.WithField("=>", ops.SrvContainerName).Debug("Container found not running") } log.WithField("=>", ops.SrvContainerName).Info("Container stopped") return nil }
// ---------------------------------------------------------------------------- // --------------------- Container Core ------------------------------------ // ---------------------------------------------------------------------------- func createContainer(opts docker.CreateContainerOptions) (*docker.Container, error) { dockerContainer, err := util.DockerClient.CreateContainer(opts) if err != nil { if err == docker.ErrNoSuchImage { if os.Getenv("ERIS_PULL_APPROVE") != "true" { var input string log.WithField("image", opts.Config.Image).Warn("The docker image not found locally") fmt.Print("Would you like the marmots to pull it from the repository? (y/n): ") fmt.Scanln(&input) if input == "Y" || input == "y" || input == "YES" || input == "Yes" || input == "yes" { log.Debug("User assented to pull") } else { log.Debug("User refused to pull") return nil, fmt.Errorf("Cannot start a container based on an image you will not let me pull.\n") } } else { log.WithField("image", opts.Config.Image).Warn("The Docker image is not found locally") log.Warn("The marmots are approved to pull it from the repository on your behalf") log.Warn("This could take a few minutes") } if err := pullImage(opts.Config.Image, nil); err != nil { return nil, err } dockerContainer, err = util.DockerClient.CreateContainer(opts) if err != nil { return nil, err } } else { return nil, err } } return dockerContainer, nil }
//[zr] TODO move to testings package func testNumbersExistAndRun(t *testing.T, servName string, containerExist, containerRun int) { log.WithFields(log.Fields{ "=>": servName, "existing#": containerExist, "running#": containerRun, }).Info("Checking number of containers for") log.WithField("=>", servName).Debug("Checking existing containers for") exist := util.HowManyContainersExisting(servName, "service") log.WithField("=>", servName).Debug("Checking running containers for") run := util.HowManyContainersRunning(servName, "service") if exist != containerExist { log.WithFields(log.Fields{ "name": servName, "expected": containerExist, "got": exist, }).Error("Wrong number of existing containers") fatal(t, nil) } if run != containerRun { log.WithFields(log.Fields{ "name": servName, "expected": containerExist, "got": run, }).Error("Wrong number of running containers") fatal(t, nil) } log.Info("All good") }
// DockerExecData runs a data container with volumes-from field set interactively. // // ops.Args - command line parameters // ops.Interactive - if true, set Entrypoint to ops.Args, // if false, set Cmd to ops.Args // // See parameter description for DockerRunData. func DockerExecData(ops *def.Operation, service *def.Service) (err error) { log.WithFields(log.Fields{ "=>": ops.DataContainerName, "args": ops.Args, }).Info("Executing data container") opts := configureVolumesFromContainer(ops, service) log.WithField("image", opts.Config.Image).Info("Data container configured") _, err = createContainer(opts) if err != nil { return err } // Clean up the container. defer func() { log.WithField("=>", opts.Name).Info("Removing data container") if err2 := removeContainer(opts.Name, true, false); err2 != nil { if os.Getenv("CIRCLE_BRANCH") == "" { err = fmt.Errorf("Tragic! Error removing data container after executing (%v): %v", err, err2) } } log.WithField("=>", opts.Name).Info("Data container removed") }() // Start the container. log.WithField("=>", opts.Name).Info("Executing interactive data container") if err = startInteractiveContainer(opts); err != nil { return err } return nil }
func ContainerDisassemble(containerName string) *ContainerName { pop := strings.Split(containerName, "_") if len(pop) < 4 { log.WithField("=>", containerName).Debug("The marmots cannot disassemble container name") return &ContainerName{} } if !(pop[0] == "eris" || pop[0] == "/eris") { log.WithField("=>", containerName).Debug("The marmots cannot disassemble container name") return &ContainerName{} } typ := pop[1] srt := strings.Join(pop[2:len(pop)-1], "_") num, err := strconv.Atoi(pop[len(pop)-1]) if err != nil { log.WithField("=>", containerName).Debug("The marmots cannot disassemble container name") return &ContainerName{} } // remove the leading slash docker adds containerName = strings.Replace(containerName, "/", "", 1) return &ContainerName{ FullName: containerName, DockersName: "/" + containerName, Type: typ, Number: num, ShortName: srt, } }
func TestKillRmService(t *testing.T) { testStartService(t, servName, false) do := def.NowDo() do.Name = servName do.Rm = false do.RmD = false do.Operations.Args = []string{servName} log.WithField("=>", servName).Debug("Stopping service (from tests)") if e := KillService(do); e != nil { log.Error(e) tests.IfExit(e) } testExistAndRun(t, servName, 1, true, false) testNumbersExistAndRun(t, servName, 1, 0) if os.Getenv("TEST_IN_CIRCLE") == "true" { log.Warn("Testing in Circle where we don't have rm privileges. Skipping test") return } do = def.NowDo() do.Name = servName do.Operations.Args = []string{servName} do.File = false do.RmD = true log.WithField("=>", servName).Debug("Removing service (from tests)") if e := RmService(do); e != nil { log.Error(e) tests.IfExit(e) } testExistAndRun(t, servName, 1, false, false) testNumbersExistAndRun(t, servName, 0, 0) }
func ChangeDirectory(to string) { if to == "bin" { erisLoc, err := exec.LookPath("eris") if err != nil { log.Fatalf("Error finding eris binary: %v", err) } err = os.Chdir(filepath.Dir(erisLoc)) if err != nil { log.Fatalf("Error changing directory: %v", err) } log.WithField("dir", erisLoc).Debug("Directory changed to") } else if to == "src" { goPath := os.Getenv("GOPATH") if goPath == "" { log.Fatal("You do not have $GOPATH set. Please make sure this is set and rerun the command.") } dir := filepath.Join(goPath, "src", "github.com", "eris-ltd", "eris-cli") err := os.Chdir(dir) if err != nil { log.Fatalf("Error changing directory: %v") } log.WithField("dir", dir).Debug("Directory changed to") } }
// AutoMagic will return the highest container number which would represent the most recent // container to work on unless newCont == true in which case it would return the highest // container number plus one. func AutoMagic(cNum int, typ string, newCont bool) int { log.WithField("automagic", cNum).Debug() contns := ErisContainersByType(typ, true) contnums := make([]int, len(contns)) for i, c := range contns { contnums[i] = c.Number } // get highest container number g := 0 for _, n := range contnums { if n >= g { g = n } } // ensure outcomes appropriate result := g if newCont { result = g + 1 } if result == 0 { result = 1 } log.WithField("automagic", result).Debug() return result }
func TestRmChain(t *testing.T) { start(t, chainName) do := def.NowDo() do.Operations.Args, do.Rm, do.RmD = []string{"keys"}, true, true if err := services.KillService(do); err != nil { t.Fatalf("expected service to be stopped, got %v", err) } do = def.NowDo() do.Name, do.Rm, do.RmD = chainName, false, false log.WithField("=>", do.Name).Info("Stopping chain (from tests)") if err := KillChain(do); err != nil { t.Fatalf("expected chain to be stopped, got %v", err) } if n := util.HowManyContainersExisting(chainName, def.TypeChain); n != 1 { t.Fatalf("expecting 1 chain containers, got %v", n) } do = def.NowDo() do.Name = chainName do.RmD = true log.WithField("=>", do.Name).Info("Removing chain (from tests)") if err := RmChain(do); err != nil { t.Fatalf("expected chain to be removed, got %v", err) } if n := util.HowManyContainersExisting(chainName, def.TypeChain); n != 0 { t.Fatalf("expecting 0 chain containers, got %v", n) } }
func RenameAction(do *definitions.Do) error { if do.Name == do.NewName { return fmt.Errorf("Cannot rename to same name") } do.Name = strings.Replace(do.Name, " ", "_", -1) do.NewName = strings.Replace(do.NewName, " ", "_", -1) act, _, err := LoadActionDefinition(do.Name) if err != nil { log.WithFields(log.Fields{ "from": do.Name, "to": do.NewName, }).Debug("Failed renaming action") return err } do.Name = strings.Replace(do.Name, " ", "_", -1) log.WithField("file", do.Name).Debug("Finding action definition file") oldFile := util.GetFileByNameAndType("actions", do.Name) if oldFile == "" { return fmt.Errorf("Could not find that action definition file.") } log.WithField("file", oldFile).Debug("Found action definition file") // if !strings.Contains(oldFile, ActionsPath) { // oldFile = filepath.Join(ActionsPath, oldFile) + ".toml" // } var newFile string newNameBase := strings.Replace(strings.Replace(do.NewName, " ", "_", -1), filepath.Ext(do.NewName), "", 1) if newNameBase == do.Name { newFile = strings.Replace(oldFile, filepath.Ext(oldFile), filepath.Ext(do.NewName), 1) } else { newFile = strings.Replace(oldFile, do.Name, do.NewName, 1) newFile = strings.Replace(newFile, " ", "_", -1) } if newFile == oldFile { log.Info("Not renaming the same file") return nil } act.Name = strings.Replace(newNameBase, "_", " ", -1) log.WithFields(log.Fields{ "old": act.Name, "new": newFile, }).Debug("Writing new action definition file") err = WriteActionDefinitionFile(act, newFile) if err != nil { return err } log.WithField("file", oldFile).Debug("Removing old file") os.Remove(oldFile) 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 CheckoutBranch(branch string) { checkoutArgs := []string{"checkout", branch} stdOut, err := exec.Command("git", checkoutArgs...).CombinedOutput() if err != nil { log.WithField("branch", branch).Fatalf("Error checking out branch: %v", string(stdOut)) } log.WithField("branch", branch).Debug("Branch checked-out") }
// start a group of chains or services. catch errors on a channel so we can stop as soon as something goes wrong func StartGroup(group []*definitions.ServiceDefinition) error { log.WithField("services#", len(group)).Debug("Starting services group") for _, srv := range group { log.WithField("=>", srv.Name).Debug("Performing container start") if err := perform.DockerRunService(srv.Service, srv.Operations); err != nil { return fmt.Errorf("StartGroup. Err starting srv =>\t%s:%v\n", srv.Name, err) } } return nil }
func getMachineDeets(machName string) (string, string, error) { var out = new(bytes.Buffer) var out2 = new(bytes.Buffer) noConnectError := fmt.Errorf("Could not evaluate the env vars for the %s docker-machine.\n", machName) dHost, dPath := popHostAndPath() if (dHost != "" && dPath != "") && (machName == "eris" || machName == "default") { return dHost, dPath, nil } // TODO: when go-dockerclient adds machine API endpoints use those instead. log.WithField("machine", machName).Debug("Querying Docker Machine URL") cmd := exec.Command("docker-machine", "url", machName) cmd.Stdout = out if err := cmd.Run(); err != nil { return "", "", fmt.Errorf("%vError:\t%v\n", noConnectError, err) } dHost = strings.TrimSpace(out.String()) log.WithField("host", dHost).Debug() // TODO: when go-dockerclient adds machine API endpoints use those instead. log.WithField("machine", machName).Debug("Querying Docker Machine cert path") cmd2 := exec.Command("docker-machine", "inspect", machName, "--format", "{{.HostOptions.AuthOptions.ServerCertPath}}") cmd2.Stdout = out2 //cmd2.Stderr = os.Stderr if err := cmd2.Run(); err != nil { return "", "", fmt.Errorf("%vError:\t%v\n", noConnectError, err) } dPath = out2.String() dPath = strings.Replace(dPath, "'", "", -1) dPath = filepath.Dir(dPath) log.WithField("cert path", dPath).Debug() if dPath == "" || dHost == "" { return "", "", noConnectError } log.Info("Querying host and user have access to the right files for TLS connection to Docker") if err := checkKeysAndCerts(dPath); err != nil { return "", "", err } log.Debug("Certificate files look good") // technically, do not *have* to do this, but it will make repetitive tasks faster log.Debug("Setting environment variables for quick future development") os.Setenv("DOCKER_HOST", dHost) os.Setenv("DOCKER_CERT_PATH", dPath) os.Setenv("DOCKER_TLS_VERIFY", "1") os.Setenv("DOCKER_MACHINE_NAME", machName) log.WithField("machine", machName).Debug("Finished getting machine details") return dHost, dPath, nil }
func FindChainContainer(name string, number int, running bool) *ContainerName { for _, srv := range ChainContainers(running) { if srv.ShortName == name { if srv.Number == number { log.WithField("match", fmt.Sprintf("%s:%d", srv.ShortName, srv.Number)).Debug("Found chain container") return srv } } } log.WithField("=>", fmt.Sprintf("%s:%d", name, number)).Info("Could not find chain container") return nil }
func FindDataContainer(name string, number int) *ContainerName { for _, srv := range DataContainers() { if srv.ShortName == name { if srv.Number == number { log.WithField("match", fmt.Sprintf("%s:%d", srv.ShortName, srv.Number)).Debug("Found data container") return srv } } } log.WithField("=>", fmt.Sprintf("%s:%d", name, number)).Info("Could not find data container") return nil }
func PerformCommand(action *definitions.Action, actionVars []string, quiet bool) error { log.WithField("action", action.Name).Info("Performing action") dir, err := os.Getwd() if err != nil { return err } log.WithField("directory", dir).Debug() // pull actionVars (first given from command line) and // combine with the environment variables (given in the // action definition files) and finally combine with // the hosts os.Environ() to provide the full set of // variables to be consumed during the steps phase. for k, v := range action.Environment { actionVars = append(actionVars, fmt.Sprintf("%s=%s", k, v)) } for _, v := range actionVars { log.WithField("variable", v).Debug() } actionVars = append(os.Environ(), actionVars...) for n, step := range action.Steps { cmd := exec.Command("sh", "-c", step) if runtime.GOOS == "windows" { cmd = exec.Command("cmd", "/c", step) } cmd.Env = actionVars cmd.Dir = dir log.WithField("=>", strings.Join(cmd.Args, " ")).Debugf("Performing step %d", n+1) prev, err := cmd.Output() if err != nil { return fmt.Errorf("error running command (%v): %s", err, prev) } if !quiet { log.Warn(strings.TrimSpace(string(prev))) } if n != 0 { actionVars = actionVars[:len(actionVars)-1] } actionVars = append(actionVars, ("prev=" + strings.TrimSpace(string(prev)))) } log.Info("Action performed") return nil }
//XXX chains and services only func ListAll(do *definitions.Do, typ string) (err error) { quiet := do.Quiet var result string if do.All == true { //overrides all the functionality used for flags/tests to stdout a nice table resK, err := ListKnown(typ) if err != nil { return err } do.Result = resK //for testing but not rly needed knowns := strings.Split(resK, "\n") typs := fmt.Sprintf("The known %s on your host kind marmot:", typ) log.WithField("=>", knowns[0]).Warn(typs) knowns = append(knowns[:0], knowns[1:]...) for _, known := range knowns { log.WithField("=>", known).Warn() } result, err = PrintTableReport(typ, true, true) //when latter bool is true, former one will be ignored... if err != nil { return err } contType := fmt.Sprintf("Active %s containers:", typ) log.Warn(contType) log.Warn(result) } else { var resK, resR, resE string if do.Known { if resK, err = ListKnown(typ); err != nil { return err } do.Result = resK } if do.Running { if resR, err = ListRunningOrExisting(quiet, false, typ); err != nil { return err } do.Result = resR } if do.Existing { if resE, err = ListRunningOrExisting(quiet, true, typ); err != nil { return err } do.Result = resE } } return nil }
// viper read config file, marshal to definition struct, // load service, validate name and data container func LoadChainDefinition(chainName string, newCont bool, cNum ...int) (*definitions.Chain, error) { if len(cNum) == 0 { cNum = append(cNum, 0) } if cNum[0] == 0 { cNum[0] = util.AutoMagic(0, definitions.TypeChain, newCont) log.WithField("=>", fmt.Sprintf("%s:%d", chainName, cNum[0])).Debug("Loading chain definition (autoassigned)") } else { log.WithField("=>", fmt.Sprintf("%s:%d", chainName, cNum[0])).Debug("Loading chain definition") } chain := definitions.BlankChain() chain.Name = chainName chain.Operations.ContainerNumber = cNum[0] chain.Operations.ContainerType = definitions.TypeChain chain.Operations.Labels = util.Labels(chain.Name, chain.Operations) if err := setChainDefaults(chain); err != nil { return nil, err } chainConf, err := config.LoadViperConfig(filepath.Join(ChainsPath), chainName, "chain") if err != nil { return nil, err } // marshal chain and always reset the operational requirements // this will make sure to sync with docker so that if changes // have occured in the interim they are caught. if err = MarshalChainDefinition(chainConf, chain); err != nil { return nil, err } // Docker 1.6 (which eris doesn't support) had different linking mechanism. if ver, _ := util.DockerClientVersion(); ver >= version.DVER_MIN { if chain.Dependencies != nil { addDependencyVolumesAndLinks(chain.Dependencies, chain.Service, chain.Operations) } } checkChainNames(chain) log.WithFields(log.Fields{ "container number": chain.Operations.ContainerNumber, "environment": chain.Service.Environment, "entrypoint": chain.Service.EntryPoint, "cmd": chain.Service.Command, }).Debug("Chain definition loaded") return chain, nil }
func TestChainGraduate(t *testing.T) { do := def.NowDo() do.Name = chainName log.WithField("=>", do.Name).Info("Graduate chain (from tests)") if err := GraduateChain(do); err != nil { tests.IfExit(err) } srvDef, err := loaders.LoadServiceDefinition(chainName, false, 1) if err != nil { tests.IfExit(err) } image := "quay.io/eris/erisdb:" + version.VERSION if srvDef.Service.Image != image { tests.IfExit(fmt.Errorf("FAILURE: improper service image on GRADUATE. expected: %s\tgot: %s\n", image, srvDef.Service.Image)) } if srvDef.Service.Command != loaders.ErisChainStart { tests.IfExit(fmt.Errorf("FAILURE: improper service command on GRADUATE. expected: %s\tgot: %s\n", loaders.ErisChainStart, srvDef.Service.Command)) } if !srvDef.Service.AutoData { tests.IfExit(fmt.Errorf("FAILURE: improper service autodata on GRADUATE. expected: %t\tgot: %t\n", true, srvDef.Service.AutoData)) } if len(srvDef.Dependencies.Services) != 1 { tests.IfExit(fmt.Errorf("FAILURE: improper service deps on GRADUATE. expected: [\"keys\"]\tgot: %s\n", srvDef.Dependencies.Services)) } }
func GetTheImages() error { if os.Getenv("ERIS_PULL_APPROVE") == "true" { if err := pullDefaultImages(); err != nil { return err } log.Warn("Pulling of default images successful") } else { var input string log.Warn(`WARNING: Approximately 1 gigabyte of docker images are about to be pulled onto your host machine Please ensure that you have sufficient bandwidth to handle the download On a remote host in the cloud, this should only take a few minutes but can sometimes take 10 or more. These times can double or triple on local host machines If you already have these images, they will be updated`) log.WithField("ERIS_PULL_APPROVE", "true").Warn("To avoid this warning on all future pulls, set as an environment variable") fmt.Print("Do you wish to continue? (y/n): ") if _, err := fmt.Scanln(&input); err != nil { return fmt.Errorf("Error reading from stdin: %v\n", err) } if input == "Y" || input == "y" || input == "YES" || input == "Yes" || input == "yes" { if err := pullDefaultImages(); err != nil { return err } log.Warn("Pulling of default images successful") } } return nil }
func ManagePinned(do *definitions.Do) error { ensureRunning() if do.Rm && do.Hash != "" { return fmt.Errorf("Either remove a file by hash or all of them\n") } if do.Rm { log.Info("Removing all cached files") hashes, err := rmAllPinned() if err != nil { return err } do.Result = hashes } else if do.Hash != "" { log.WithField("hash", do.Hash).Info("Removing from cache") hashes, err := rmPinnedByHash(do.Hash) if err != nil { return err } do.Result = hashes } else { log.Debug("Listing files pinned locally") hash, err := listPinned() if err != nil { return err } do.Result = hash } return nil }
//TODO test that this doesn't fmt things up, see note in #400 func moveOutOfDirAndRmDir(src, dest string) error { log.WithFields(log.Fields{ "from": src, "to": dest, }).Info("Move all files/dirs out of a dir and `rm -rf` that dir") toMove, err := filepath.Glob(filepath.Join(src, "*")) if err != nil { return err } if len(toMove) == 0 { log.Debug("No files to move") } for _, f := range toMove { // using a copy (read+write) strategy to get around swap partitions and other // problems that cause a simple rename strategy to fail. it is more io overhead // to do this, but for now that is preferable to alternative solutions. Copy(f, filepath.Join(dest, filepath.Base(f))) } log.WithField("=>", src).Info("Removing directory") err = os.RemoveAll(src) if err != nil { return err } return nil }
func RmService(do *definitions.Do) error { for _, servName := range do.Operations.Args { service, err := loaders.LoadServiceDefinition(servName, false, do.Operations.ContainerNumber) if err != nil { return err } if IsServiceExisting(service.Service, service.Operations) { err = perform.DockerRemove(service.Service, service.Operations, do.RmD, do.Volumes, do.Force) if err != nil { return err } } if do.File { oldFile := util.GetFileByNameAndType("services", servName) if err != nil { return err } oldFile = filepath.Join(ServicesPath, oldFile) + ".toml" log.WithField("file", oldFile).Warn("Removing file") if err := os.Remove(oldFile); err != nil { return err } } } do.Result = "success" return nil }
func InitDefaults(do *definitions.Do, newDir bool) error { var srvPath string var actPath string var chnPath string srvPath = common.ServicesPath actPath = common.ActionsPath chnPath = common.ChainsPath tsErrorFix := "toadserver may be down: re-run with `--source=rawgit`" if err := dropServiceDefaults(srvPath, do.Source); err != nil { return fmt.Errorf("%v\n%s\n", err, tsErrorFix) } if err := dropActionDefaults(actPath, do.Source); err != nil { return fmt.Errorf("%v\n%s\n", err, tsErrorFix) } if err := dropChainDefaults(chnPath, do.Source); err != nil { return fmt.Errorf("%v\n%s\n", err, tsErrorFix) } log.WithField("root", common.ErisRoot).Warn("Initialized eris root directory with default service, action, and chain files") return nil }