func ExecService(do *definitions.Do) error { service, err := loaders.LoadServiceDefinition(do.Name, false, do.Operations.ContainerNumber) if err != nil { return err } util.Merge(service.Operations, do.Operations) // Get the main service container name, check if it's running. main := util.FindServiceContainer(do.Name, do.Operations.ContainerNumber, false) if main != nil { if service.Service.ExecHost == "" { log.Info("exec_host not found in service definition file") log.WithField("service", do.Name).Info("May not be able to communicate with the service") } else { service.Service.Environment = append(service.Service.Environment, fmt.Sprintf("%s=%s", service.Service.ExecHost, do.Name)) } // Use service's short name as a link alias. service.Service.Links = append(service.Service.Links, fmt.Sprintf("%s:%s", main.FullName, do.Name)) } // Override links on the command line. if len(do.Links) > 0 { service.Service.Links = do.Links } return perform.DockerExecService(service.Service, service.Operations) }
func RmChain(do *definitions.Do) error { chain, err := loaders.LoadChainDefinition(do.Name, false, do.Operations.ContainerNumber) if err != nil { return err } if IsChainExisting(chain) { if err = perform.DockerRemove(chain.Service, chain.Operations, do.RmD, do.Volumes); err != nil { return err } } else { log.Info("Chain container does not exist") } if do.File { oldFile := util.GetFileByNameAndType("chains", do.Name) if err != nil { return err } log.WithField("file", oldFile).Warn("Removing file") if err := os.Remove(oldFile); err != nil { return err } } 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 }
//[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") }
//testType = one of each package, will switch over it for //make additional tempDirs and vars as needed -> [zr] or not, TBD func TestsInit(testType string) (err error) { // TODO: make a reader/pipe so we can see what is written from tests. config.GlobalConfig, err = config.SetGlobalObject(os.Stdout, os.Stderr) if err != nil { IfExit(fmt.Errorf("TRAGIC. Could not set global config.\n")) } // common is initialized on import so // we have to manually override these // variables to ensure that the tests // run correctly. config.ChangeErisDir(erisDir) util.DockerConnect(false, "eris") // this dumps the ipfs and keys services defs into the temp dir which // has been set as the erisRoot. do := def.NowDo() do.Pull = false //don't pull imgs do.Yes = true //over-ride command-line prompts do.Quiet = true // do.Source = "toadserver" //use "rawgit" if ts down do.Source = "rawgit" //use "rawgit" if ts down if err := ini.Initialize(do); err != nil { IfExit(fmt.Errorf("TRAGIC. Could not initialize the eris dir: %s.\n", err)) } log.Info("Test init completed. Starting main test sequence now") return nil }
func KillChain(do *definitions.Do) error { chain, err := loaders.LoadChainDefinition(do.Name, false, do.Operations.ContainerNumber) if err != nil { return err } if do.Force { do.Timeout = 0 //overrides 10 sec default } if IsChainRunning(chain) { if err := perform.DockerStop(chain.Service, chain.Operations, do.Timeout); err != nil { return err } } else { log.Info("Chain not currently running. Skipping") } if do.Rm { if err := perform.DockerRemove(chain.Service, chain.Operations, do.RmD, do.Volumes, do.Force); err != nil { return err } } return nil }
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 }
// DockerRebuild recreates the container based on the srv settings template. // If pullImage is true, it updates the Docker image before recreating // the container. Timeout is a number of seconds to wait before killing the // container process ungracefully. // // ops.SrvContainerName - service or a chain container name to rebuild // ops.ContainerNumber - container number // ops.ContainerType - container type // ops.Labels - container creation time labels // // Also see container parameters for DockerRunService. func DockerRebuild(srv *def.Service, ops *def.Operation, pullImage bool, timeout uint) error { var wasRunning bool = false log.WithField("=>", srv.Name).Info("Rebuilding container") if _, exists := ContainerExists(ops); exists { if _, running := ContainerRunning(ops); running { wasRunning = true err := DockerStop(srv, ops, timeout) if err != nil { return err } } log.WithField("=>", ops.SrvContainerName).Info("Removing old container") err := removeContainer(ops.SrvContainerName, true, false) if err != nil { return err } } else { log.Info("Container did not previously exist. Nothing to rebuild") return nil } if pullImage { log.WithField("image", srv.Image).Info("Pulling image") err := DockerPull(srv, ops) if err != nil { return err } } opts := configureServiceContainer(srv, ops) var err error srv.Volumes, err = util.FixDirs(srv.Volumes) if err != nil { return err } log.WithField("=>", ops.SrvContainerName).Info("Recreating container") _, err = createContainer(opts) if err != nil { return err } if wasRunning { log.WithField("=>", opts.Name).Info("Restarting container") err := startContainer(opts) if err != nil { return err } } log.WithField("=>", ops.SrvContainerName).Info("Container rebuilt") return nil }
func BootServicesAndChain(do *definitions.Do, app *definitions.Contracts) error { var err error var srvs []*definitions.ServiceDefinition // launch the services for _, s := range do.ServicesSlice { t, err := services.BuildServicesGroup(s, do.Operations.ContainerNumber, srvs...) if err != nil { return err } srvs = append(srvs, t...) } if len(srvs) >= 1 { if err := services.StartGroup(srvs); err != nil { return err } } // boot the chain switch do.ChainName { case "": if app.ChainName == "" { // TODO [csk]: first check if there is a chain checked out. if not, then use throwAway log.Info("No chain was given, booting a throwaway chain") err = bootThrowAwayChain(app.Name, do) } else { log.WithField("=>", app.ChainName).Info("Booting chain") err = bootChain(app.ChainName, do) } case "t", "tmp", "temp": log.Info("No chain was given, booting a throwaway chain") err = bootThrowAwayChain(app.Name, do) default: log.WithField("=>", do.ChainName).Info("Booting chain") err = bootChain(do.ChainName, do) } app.ChainName = do.Chain.Name if err != nil { return err } return nil }
func ensureRunning() { doNow := definitions.NowDo() doNow.Name = "ipfs" err := services.EnsureRunning(doNow) if err != nil { fmt.Printf("Failed to ensure IPFS is running: %v", err) return } log.Info("IPFS is running") }
func startErisMachine() error { log.Info("Starting Eris Docker Machine") cmd := "docker-machine" args := []string{"start", "eris"} if err := exec.Command(cmd, args...).Run(); err != nil { return fmt.Errorf("There was an error starting the newly created docker-machine.\nError:\t%v\n", err) } log.Debug("Eris Docker Machine started") 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 }
// DockerInspect displays container ops.SrvContainerName data on the terminal. // field can be a field name of one of `docker inspect` output or it can be // either "line" to display a short info line or "all" to display everything. I // DockerInspect returns Docker errors on exit in not successful. func DockerInspect(srv *def.Service, ops *def.Operation, field string) error { if _, exists := ContainerExists(ops); exists { log.WithField("=>", ops.SrvContainerName).Info("Inspecting") err := inspectContainer(ops.SrvContainerName, field) if err != nil { return err } } else { log.Info("Container does not exist. Cannot inspect") } 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 }
func TestMain(m *testing.M) { log.SetFormatter(logger.ErisFormatter{}) log.SetLevel(log.ErrorLevel) // log.SetLevel(log.InfoLevel) // log.SetLevel(log.DebugLevel) tests.IfExit(tests.TestsInit("actions")) exitCode := m.Run() log.Info("Tearing tests down") tests.IfExit(tests.TestsTearDown()) os.Exit(exitCode) }
func TestMain(m *testing.M) { runtime.GOMAXPROCS(1) log.SetFormatter(logger.ErisFormatter{}) log.SetLevel(log.ErrorLevel) // log.SetLevel(log.InfoLevel) // log.SetLevel(log.DebugLevel) tests.IfExit(tests.TestsInit("chain")) log.Info("Test init completed. Starting main test sequence now") layTestChainToml(chainName) fmt.Println(m.Run()) }
// DockerLogs displays tail number of lines of container ops.SrvContainerName // output. If follow is true, it behaves like `tail -f`. It returns Docker // errors on exit if not successful. func DockerLogs(srv *def.Service, ops *def.Operation, follow bool, tail string) error { if _, exists := ContainerExists(ops); exists { log.WithFields(log.Fields{ "=>": ops.SrvContainerName, "follow": follow, "tail": tail, }).Info("Getting logs") if err := logsContainer(ops.SrvContainerName, follow, tail); err != nil { return err } } else { log.Info("Container does not exist. Cannot display logs") } return nil }
func TestMain(m *testing.M) { log.SetFormatter(logger.ErisFormatter{}) log.SetLevel(log.ErrorLevel) // log.SetLevel(log.InfoLevel) // log.SetLevel(log.DebugLevel) tests.IfExit(tests.TestsInit("actions")) exitCode := m.Run() log.Info("Tearing tests down") if os.Getenv("TEST_IN_CIRCLE") != "true" { tests.IfExit(tests.TestsTearDown()) } os.Exit(exitCode) }
func TestMain(m *testing.M) { log.SetFormatter(logger.ErisFormatter{}) log.SetLevel(log.ErrorLevel) // log.SetLevel(log.InfoLevel) // log.SetLevel(log.DebugLevel) ifExit(testsInit()) toadUp = toadServerUp() exitCode := m.Run() log.Info("Commensing with Tests Tear Down.") ifExit(testsTearDown()) os.Exit(exitCode) }
func TestMain(m *testing.M) { log.SetFormatter(logger.ErisFormatter{}) log.SetLevel(log.ErrorLevel) // log.SetLevel(log.InfoLevel) // log.SetLevel(log.DebugLevel) tests.IfExit(tests.TestsInit("services")) // Prevent CLI from starting IPFS. os.Setenv("ERIS_SKIP_ENSURE", "true") exitCode := m.Run() log.Info("Tearing tests down") tests.IfExit(tests.TestsTearDown()) os.Exit(exitCode) }
func CleanUp(do *definitions.Do) error { log.Info("Cleaning up") do.Force = true if do.Chain.ChainType == "throwaway" { log.WithField("=>", do.Chain.Name).Debug("Destroying throwaway chain") doRm := definitions.NowDo() doRm.Operations = do.Operations doRm.Name = do.Chain.Name doRm.Rm = true doRm.RmD = true doRm.Volumes = true KillChain(doRm) latentDir := filepath.Join(DataContainersPath, do.Chain.Name) latentFile := filepath.Join(ChainsPath, do.Chain.Name+".toml") if doRm.Name == "default" { log.WithField("dir", latentDir).Debug("Removing latent dir") os.RemoveAll(latentDir) } else { log.WithFields(log.Fields{ "dir": latentDir, "file": latentFile, }).Debug("Removing latent dir and file") os.RemoveAll(latentDir) os.Remove(latentFile) } } else { log.Debug("No throwaway chain to destroy") } if do.RmD { log.WithField("dir", filepath.Join(DataContainersPath, do.Service.Name)).Debug("Removing data dir on host") os.RemoveAll(filepath.Join(DataContainersPath, do.Service.Name)) } if do.Rm { log.WithField("=>", do.Operations.SrvContainerName).Debug("Removing tmp service container") perform.DockerRemove(do.Service, do.Operations, true, true, false) } return nil }
//XXX this command absolutely needs a good test!! func MigrateDeprecatedDirs(dirsToMigrate map[string]string, prompt bool) error { dirsMap, isMigNeed := dirCheckMaker(dirsToMigrate) if isMigNeed { log.Warn("Deprecated directories detected. Marmot migration commencing") } if !isMigNeed { log.Info("Nothing to migrate") return nil } else if !prompt { return Migrate(dirsMap) } else if canWeMigrate() { return Migrate(dirsMap) } else { return fmt.Errorf("permission to migrate not given") } return nil }
func startInteractiveContainer(opts docker.CreateContainerOptions) error { // Trap signals so we can drop out of the container. c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt, os.Kill) go func() { <-c log.WithField("=>", opts.Name).Info("Caught signal. Stopping container") if err := stopContainer(opts.Name, 5); err != nil { log.Errorf("Error stopping container: %v", err) } }() attached := make(chan struct{}) go func(chan struct{}) { attachContainer(opts.Name, attached) }(attached) // Wait for a console prompt to appear. _, ok := <-attached if ok { attached <- struct{}{} } if err := startContainer(opts); err != nil { return err } log.WithField("=>", opts.Name).Info("Waiting for container to exit") // Set terminal into raw mode, and restore upon container exit. savedState, err := term.SetRawTerminal(os.Stdin.Fd()) if err != nil { log.Info("Cannot set the terminal into raw mode") } else { defer term.RestoreTerminal(os.Stdin.Fd(), savedState) } if err := waitContainer(opts.Name); err != nil { return err } return nil }
func testsInit() error { var err error config.GlobalConfig, err = config.SetGlobalObject(os.Stdout, os.Stderr) if err != nil { ifExit(fmt.Errorf("TRAGIC. Could not set global config.\n")) } // common is initialized on import so // we have to manually override these // variables to ensure that the tests // run correctly. config.ChangeErisDir(erisDir) util.DockerConnect(false, "eris") log.Info("Test init completed. Starting main test sequence now.") return nil }
func PerformAppActionService(do *definitions.Do, app *definitions.Contracts) error { log.Warn("Performing action. This can sometimes take a wee while") log.WithFields(log.Fields{ "service": do.Service.Name, "image": do.Service.Image, }).Info() log.WithFields(log.Fields{ "workdir": do.Service.WorkDir, "entrypoint": do.Service.EntryPoint, }).Debug() do.Operations.ContainerType = definitions.TypeService if err := perform.DockerExecService(do.Service, do.Operations); err != nil { do.Result = "could not perform app action" return err } log.Info("Finished performing app action") return nil }
// DockerRemove removes the ops.SrvContainerName container. // If withData is true, the associated data container is also removed. // If volumes is true, the associated volumes are removed for both containers. // DockerRemove returns Docker errors on exit if not successful. func DockerRemove(srv *def.Service, ops *def.Operation, withData, volumes, force bool) error { if _, exists := ContainerExists(ops); exists { log.WithField("=>", ops.SrvContainerName).Info("Removing container") if err := removeContainer(ops.SrvContainerName, volumes, force); err != nil { return err } if withData { if _, ext := DataContainerExists(ops); ext { log.WithField("=>", ops.DataContainerName).Info("Removing dependent data container") if err := removeContainer(ops.DataContainerName, volumes, force); err != nil { return err } } } } else { log.Info("Container does not exist. Cannot remove") } return nil }
// DockerCreateData creates a blank data container. It returns ErrContainerExists // if such a container exists or other Docker errors. // // ops.DataContainerName - data container name to be created // ops.ContainerType - container type // ops.ContainerNumber - container number // ops.Labels - container creation time labels (use LoadDataDefinition) // func DockerCreateData(ops *def.Operation) error { log.WithField("=>", ops.DataContainerName).Info("Creating data container") if _, exists := ContainerExists(ops); exists { log.Info("Data container exists. Not creating") return ErrContainerExists } optsData, err := configureDataContainer(def.BlankService(), ops, nil) if err != nil { return err } _, err = createContainer(optsData) if err != nil { return err } log.WithField("=>", optsData.Name).Info("Data container created") return nil }
func cullCLIVariables(act []string) ([]string, []string) { var actionVars []string var action []string log.Debug("Pulling out named variables") for _, a := range act { if strings.Contains(a, ":") { r := strings.Replace(a, ":", "=", 1) actionVars = append(actionVars, r) log.WithField("=>", r).Debug("Culling from variable list") } else { action = append(action, a) } } log.Info("Successfully parsed named variables") log.WithFields(log.Fields{ "culled": actionVars, "not culled": action, }).Debug() return action, actionVars }
func LoadContractPackage(path, chainName, command, typ string) (*definitions.Contracts, error) { var app *definitions.Contracts contConf, err := loadContractPackage(path) if err != nil { log.Info("The marmots could not read that package.json. Will use defaults") app, _ = DefaultContractPackage() _, err := LoadEPMInstructions(path) if err != nil { // TODO [csk]: rework this logic } } else { // 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. app, err = marshalContractPackage(contConf) if err != nil { return nil, err } } log.WithFields(log.Fields{ "test task": app.TestTask, "test type": app.TestType, "deploy type": app.DeployType, "deploy task": app.DeployTask, }).Debug("Loading package") if err := setAppType(app, chainName, command, typ); err != nil { return nil, err } if err := checkAppAndChain(app, chainName); err != nil { return nil, err } return app, nil }
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 { tests.IfExit(fmt.Errorf("Wrong number of containers existing for service (%s). Expected (%d). Got (%d).\n", servName, containerExist, exist)) } if run != containerRun { tests.IfExit(fmt.Errorf("Wrong number of containers running for service (%s). Expected (%d). Got (%d).\n", servName, containerRun, run)) } log.Info("All good") }