func linkDappToChain(do *definitions.Do, dapp *definitions.Contracts) { var newLink string if do.Chain.ChainType == "service" { newLink = util.ServiceContainersName(dapp.ChainName, do.Operations.ContainerNumber) + ":" + "chain" } else { newLink = util.ChainContainersName(dapp.ChainName, do.Operations.ContainerNumber) + ":" + "chain" } do.Service.Links = append(do.Service.Links, newLink) }
func testExistAndRun(t *testing.T, chainName string, toExist, toRun bool) { var exist, run bool logger.Infof("\nTesting whether (%s) is running? (%t) and existing? (%t)\n", chainName, toRun, toExist) chainName = util.ChainContainersName(chainName, 1) // not worried about containerNumbers, deal with multiple containers in services tests do := def.NowDo() do.Quiet = true do.Args = []string{"testing"} if err := ListExisting(do); err != nil { logger.Errorln(err) t.FailNow() } res := strings.Split(do.Result, "\n") for _, r := range res { logger.Debugf("Existing =>\t\t\t%s\n", r) if r == util.ContainersShortName(chainName) { exist = true } } do = def.NowDo() do.Quiet = true do.Args = []string{"testing"} if err := ListRunning(do); err != nil { logger.Errorln(err) t.FailNow() } res = strings.Split(do.Result, "\n") for _, r := range res { logger.Debugf("Running =>\t\t\t%s\n", r) if r == util.ContainersShortName(chainName) { run = true } } if toExist != exist { if toExist { logger.Infof("Could not find an existing =>\t%s\n", chainName) } else { logger.Infof("Found an existing instance of %s when I shouldn't have\n", chainName) } t.Fail() } if toRun != run { if toRun { logger.Infof("Could not find a running =>\t%s\n", chainName) } else { logger.Infof("Found a running instance of %s when I shouldn't have\n", chainName) } t.Fail() } logger.Debugln("") }
// Convert the chain def to a service def but keep the "eris_chains" containers prefix and set the chain id func ChainsAsAService(chainName string, newCont bool, cNum ...int) (*definitions.ServiceDefinition, error) { chain, err := LoadChainDefinition(chainName, newCont, cNum...) if err != nil { return nil, err } s, err := ServiceDefFromChain(chain, ErisChainStart), nil if err != nil { return nil, err } // we keep the "eris_chain" prefix and set the CHAIN_ID var. // the run command is set in ServiceDefFromChain s.Operations.SrvContainerName = util.ChainContainersName(chainName, s.Operations.ContainerNumber) s.Service.Environment = append(s.Service.Environment, "CHAIN_ID="+chainName) return s, 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() { logger.Infof("Path (%s) does not exist or is not a directory, trying $HOME/.eris/chains/%s\n", do.Path, do.Path) 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 !data.IsKnown(do.Name) { 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) } } else { logger.Debugln("Data container already exists for", do.Name) } logger.Debugf("Chain's Data Contain Built =>\t%s\n", do.Name) // if something goes wrong, cleanup defer func() { if err != nil { logger.Infof("Error on setupChain =>\t\t%v\n", err) logger.Infoln("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 := path.Join("chains", do.Name) // path in container dst := path.Join(DataContainersPath, do.Name, containerDst) // path on host // TODO: deal with do.Operations.ContainerNumbers ....! // we probably need to update Import logger.Debugf("Container destination =>\t%s\n", containerDst) logger.Debugf("Local destination =>\t\t%s\n", dst) 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"}) } logger.Infof("Copying chain files into the correct location.\n") if err := copyFiles(dst, filesToCopy); err != nil { return err } // copy from host to container logger.Debugf("Copying Files into DataCont =>\t%s:%s\n", dst, containerDst) 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 { logger.Debugf(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 } logger.Debugf("Chain Loaded. Image =>\t\t%v\n", chain.Service.Image) 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") } logger.Debugf("Set env vars from setupChain =>\t%v\n", envVars) chain.Service.Environment = append(chain.Service.Environment, envVars...) logger.Debugf("Set links from setupChain =>\t%v\n", do.Links) 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 } logger.Debugf("Starting chain via Docker =>\t%s\n", chain.Service.Name) logger.Debugf("\twith Image =>\t\t%s\n", chain.Service.Image) err = perform.DockerRunService(chain.Service, chain.Operations) // this err is caught in the defer above return }
//---------------------------------------------------------------------- // validation funcs func checkChainNames(chain *definitions.Chain) { chain.Service.Name = chain.Name chain.Operations.SrvContainerName = util.ChainContainersName(chain.Name, chain.Operations.ContainerNumber) chain.Operations.DataContainerName = util.DataContainersName(chain.Name, chain.Operations.ContainerNumber) }
//return to handle failings in each pkg //typ = type of test for dealing with do.() details func TestExistAndRun(name, typ string, contNum int, toExist, toRun bool) bool { var exist, run bool if typ == "actions" { name = strings.Replace(name, " ", "_", -1) // dirty } //logger.Infof("\nTesting whether (%s) existing? (%t)\n", name, toExist) logger.Infof("\nTesting whether (%s) is running? (%t) and existing? (%t)\n", name, toRun, toExist) if typ == "chains" { name = util.ChainContainersName(name, 1) // not worried about containerNumbers, deal with multiple containers in services tests } else if typ == "services" { name = util.ServiceContainersName(name, contNum) } else { name = util.DataContainersName(name, 1) } do := def.NowDo() do.Quiet = true do.Operations.Args = []string{"testing"} if typ == "data" || typ == "chains" || typ == "services" { do.Existing = true } else if typ == "actions" { do.Known = true } if err := util.ListAll(do, typ); err != nil { logger.Errorln(err) return true } res := strings.Split(do.Result, "\n") for _, r := range res { logger.Debugf("Existing =>\t\t\t%s\n", r) if r == util.ContainersShortName(name) { exist = true } } if toExist != exist { if toExist { logger.Infof("Could not find an existing =>\t%s\n", name) } else { logger.Infof("Found an existing instance of %s when I shouldn't have\n", name) } return true } //func should always be testing for toExist, only sometimes tested for runining if typ == "chains" || typ == "services" { do.Running = true do.Existing = false //unset if err := util.ListAll(do, typ); err != nil { return true } logger.Debugln("RUNNING RESULT:", do.Result) res = strings.Split(do.Result, "\n") for _, r := range res { logger.Debugf("Running =>\t\t\t%s\n", r) if r == util.ContainersShortName(name) { run = true } } if toRun != run { if toRun { logger.Infof("Could not find a running =>\t%s\n", name) } else { logger.Infof("Found a running instance of %s when I shouldn't have\n", name) } return true } } return false }
// 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 } // do.Run containers and exit (creates data container) if !data.IsKnown(containerName) { if err := perform.DockerCreateDataContainer(do.Name, do.Operations.ContainerNumber); err != nil { return fmt.Errorf("Error creating data containr =>\t%v", err) } } logger.Debugf("Chain's Data Contain Built =>\t%s\n", do.Name) // if something goes wrong, cleanup defer func() { if err != nil { logger.Infof("Error on setupChain =>\t\t%v\n", err) logger.Infoln("Cleaning up...") if err2 := RmChain(do); err2 != nil { 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, config into container containerDst := path.Join("blockchains", do.Name) // path in container dst := path.Join(DataContainersPath, do.Name, containerDst) // path on host // TODO: deal with do.Operations.ContainerNumbers ....! // we probably need to update Import if err = os.MkdirAll(dst, 0700); err != nil { return fmt.Errorf("Error making data directory: %v", err) } if do.Path != "" { if err = Copy(do.Path, dst); err != nil { return err } } if do.GenesisFile != "" { if err = Copy(do.GenesisFile, path.Join(dst, "genesis.json")); err != nil { return err } } else { // TODO: do.Run mintgen and open the do.GenesisFile in editor } if do.ConfigFile != "" { if err = Copy(do.ConfigFile, path.Join(dst, "config."+path.Ext(do.ConfigFile))); err != nil { return err } } // copy from host to container logger.Debugf("Copying Files into DataCont =>\t%s:%s\n", dst, containerDst) importDo := definitions.NowDo() importDo.Name = do.Name importDo.Operations = do.Operations if err = data.ImportData(importDo); err != nil { return err } chain := loaders.MockChainDefinition(do.Name, do.ChainID, false, do.Operations.ContainerNumber) //get maintainer info uName, err := gitconfig.Username() if err != nil { logger.Debugf("Could not find git user.name, setting chain.Maintainer.Name = \"\"") uName = "" } email, err := gitconfig.Email() if err != nil { logger.Debugf("Could not find git user.email, setting chain.Maintainer.Email = \"\"") email = "" } chain.Maintainer.Name = uName chain.Maintainer.Email = email // write the chain definition file ... fileName := filepath.Join(BlockchainsPath, 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 } logger.Debugf("Chain Loaded. Image =>\t\t%v\n", chain.Service.Image) 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 // do we need to create our own do.GenesisFile? var genGen bool if do.GenesisFile == "" { genGen = true } // set chainid and other vars envVars := []string{ "CHAIN_ID=" + do.ChainID, "CONTAINER_NAME=" + containerName, fmt.Sprintf("RUN=%v", do.Run), fmt.Sprintf("GENERATE_GENESIS=%v", genGen), } logger.Debugf("Set env vars from setupChain =>\t%v\n", envVars) for _, eV := range envVars { chain.Service.Environment = append(chain.Service.Environment, eV) } // TODO mint vs. erisdb (in terms of rpc) chain.Operations.DataContainerName = util.DataContainersName(do.Name, do.Operations.ContainerNumber) if os.Getenv("TEST_IN_CIRCLE") != "true" { chain.Operations.Remove = true } logger.Debugf("Starting chain via Docker =>\t%s\n", chain.Service.Name) logger.Debugf("\twith Image =>\t\t%s\n", chain.Service.Image) err = perform.DockerRun(chain.Service, chain.Operations) // this err is caught in the defer above return }
// 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 } // ensure/create data container if !data.IsKnown(containerName) { if err := perform.DockerCreateDataContainer(do.Name, do.Operations.ContainerNumber); err != nil { return fmt.Errorf("Error creating data containr =>\t%v", err) } } else { logger.Debugln("Data container already exists for", do.Name) } logger.Debugf("Chain's Data Contain Built =>\t%s\n", do.Name) // if something goes wrong, cleanup defer func() { if err != nil { logger.Infof("Error on setupChain =>\t\t%v\n", err) logger.Infoln("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 := path.Join("blockchains", do.Name) // path in container dst := path.Join(DataContainersPath, do.Name, containerDst) // path on host // TODO: deal with do.Operations.ContainerNumbers ....! // we probably need to update Import logger.Debugln("container destination:", containerDst) logger.Debugln("local destination:", dst) if err = os.MkdirAll(dst, 0700); err != nil { return fmt.Errorf("Error making data directory: %v", err) } var csvFile, csvPath string if do.CSV != "" { csvFile = "genesis.csv" csvPath = fmt.Sprintf("/home/eris/.eris/blockchains/%s/%s", do.ChainID, csvFile) } if err := copyFiles(dst, []stringPair{ {do.Path, ""}, {do.GenesisFile, "genesis.json"}, {do.ConfigFile, "config.toml"}, {do.Priv, "priv_validator.json"}, {do.CSV, csvFile}, }); err != nil { return err } // copy from host to container logger.Debugf("Copying Files into DataCont =>\t%s:%s\n", dst, containerDst) importDo := definitions.NowDo() importDo.Name = do.Name importDo.Operations = do.Operations 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 { logger.Debugf(err.Error()) } // write the chain definition file ... fileName := filepath.Join(BlockchainsPath, 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 } logger.Debugf("Chain Loaded. Image =>\t\t%v\n", chain.Service.Image) 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 // do we need to create our own do.GenesisFile? var genGen bool if do.GenesisFile == "" { genGen = true } // 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("RUN=%v", do.Run), fmt.Sprintf("GENERATE_GENESIS=%v", genGen), fmt.Sprintf("CSV=%v", csvPath), fmt.Sprintf("CONFIG_OPTS=%s", configOpts), } logger.Debugf("Set env vars from setupChain =>\t%v\n", envVars) for _, eV := range envVars { chain.Service.Environment = append(chain.Service.Environment, eV) } // TODO: if do.N > 1 ... chain.Operations.DataContainerName = util.DataContainersName(do.Name, do.Operations.ContainerNumber) if os.Getenv("TEST_IN_CIRCLE") != "true" { chain.Operations.Remove = true } logger.Debugf("Starting chain via Docker =>\t%s\n", chain.Service.Name) logger.Debugf("\twith Image =>\t\t%s\n", chain.Service.Image) err = perform.DockerRun(chain.Service, chain.Operations) // this err is caught in the defer above return }