func PutFiles(do *definitions.Do) error { ensureRunning() if do.Gateway != "" { _, err := url.Parse(do.Gateway) if err != nil { return fmt.Errorf("Invalid gateway URL provided %v\n", err) } logger.Debugf("Posting to %v\n", do.Gateway) } else { logger.Debugf("Posting to gateway.ipfs.io\n") } if do.AddDir { logger.Debugf("Gonna add the contents of a directory =>\t\t%s:%v\n", do.Name, do.Path) hashes, err := exportDir(do.Name, do.Gateway) if err != nil { return err } do.Result = hashes } else { logger.Debugf("Gonna Add a file =>\t\t%s:%v\n", do.Name, do.Path) hash, err := exportFile(do.Name, do.Gateway) if err != nil { return err } do.Result = hash } 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 }
func ImportKey(do *definitions.Do) error { do.Name = "keys" do.Operations.ContainerNumber = 1 if err := srv.EnsureRunning(do); err != nil { return err } do.Operations.Interactive = false dir := path.Join(ErisContainerRoot, "keys", "data", do.Address) do.Operations.Args = []string{"mkdir", dir} //need to mkdir for import if err := srv.ExecService(do); err != nil { return err } //src on host if do.Source == "" { do.Source = filepath.Join(KeysPath, "data", do.Address, do.Address) } //dest in container do.Destination = dir if err := data.ImportData(do); err != nil { return err } return nil }
// boot chain dependencies // TODO: this currently only supports simple services (with no further dependencies) func bootDependencies(chain *definitions.Chain, do *definitions.Do) error { if chain.Dependencies != nil { name := do.Name logger.Infoln("Booting chain dependencies", chain.Dependencies.Services, chain.Dependencies.Chains) for _, srvName := range chain.Dependencies.Services { do.Name = srvName srv, err := loaders.LoadServiceDefinition(do.Name, false, do.Operations.ContainerNumber) if err != nil { return err } // Start corresponding service. if !services.IsServiceRunning(srv.Service, srv.Operations) { name := strings.ToUpper(do.Name) logger.Infof("%s is not running. Starting now. Waiting for %s to become available \n", name, name) if err = perform.DockerRunService(srv.Service, srv.Operations); err != nil { return err } } } do.Name = name // undo side effects for _, chainName := range chain.Dependencies.Chains { chn, err := loaders.LoadChainDefinition(chainName, false, do.Operations.ContainerNumber) if err != nil { return err } if !IsChainRunning(chn) { return fmt.Errorf("chain %s depends on chain %s but %s is not running", chain.Name, chainName, chainName) } } } return nil }
// check path for ErisContainerRoot // XXX this is opiniated & we may want to change in future // for more flexibility with filesystem of data conts func checkErisContainerRoot(do *definitions.Do, typ string) error { r, err := regexp.Compile(ErisContainerRoot) if err != nil { return err } switch typ { case "import": if r.MatchString(do.Destination) != true { //if not there join it do.Destination = path.Join(ErisContainerRoot, do.Destination) return nil } else { // matches: do nothing return nil } case "export": if r.MatchString(do.Source) != true { do.Source = path.Join(ErisContainerRoot, do.Source) return nil } else { return nil } } 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 { logger.Infoln("Removing all cached files") hashes, err := rmAllPinned() if err != nil { return err } do.Result = hashes } else if do.Hash != "" { logger.Infof("Removing %v, from cache", do.Hash) hashes, err := rmPinnedByHash(do.Hash) if err != nil { return err } do.Result = hashes } else { logger.Debugf("Listing files pinned locally") hash, err := listPinned() if err != nil { return err } do.Result = hash } 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 }
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 { logger.Debugf("About to fail. Name:NewName =>\t%s:%s", do.Name, do.NewName) return err } do.Name = strings.Replace(do.Name, " ", "_", -1) logger.Debugf("About to find defFile =>\t%s\n", do.Name) oldFile := util.GetFileByNameAndType("actions", do.Name) if oldFile == "" { return fmt.Errorf("Could not find that action definition file.") } logger.Debugf("Found defFile at =>\t\t%s\n", oldFile) 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 { logger.Infoln("Those are the same file. Not renaming") return nil } act.Name = strings.Replace(newNameBase, "_", " ", -1) logger.Debugf("About to write new def file =>\t%s:%s\n", act.Name, newFile) err = WriteActionDefinitionFile(act, newFile) if err != nil { return err } logger.Debugf("Removing old file =>\t\t%s\n", oldFile) os.Remove(oldFile) 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 CheckoutChain(do *definitions.Do) error { if do.Name == "" { do.Result = "nil" return util.NullHead() } curHead, _ := util.GetHead() if do.Name == curHead { do.Result = "no change" return nil } return util.ChangeHead(do.Name) }
//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 }
// Throw away chains are used for eris contracts func ThrowAwayChain(do *definitions.Do) error { do.Name = do.Name + "_" + strings.Split(uuid.New(), "-")[0] do.Path = filepath.Join(ChainsPath, "default") logger.Debugf("Making a ThrowAwayChain =>\t%s:%s\n", do.Name, do.Path) if err := NewChain(do); err != nil { return err } logger.Debugf("ThrowAwayChain created =>\t%s\n", do.Name) do.Run = true // turns on edb api StartChain(do) // XXX [csk]: may not need to do this now that New starts.... logger.Debugf("ThrowAwayChain started =>\t%s\n", do.Name) return nil }
func NewChain(do *definitions.Do) error { // read chainID from genesis. genesis may be in dir // if no genesis or no genesis.chain_id, chainID = name var err error if do.GenesisFile = resolveGenesisFile(do.GenesisFile, do.Path); do.GenesisFile == "" { do.ChainID = do.Name } else { do.ChainID, err = getChainIDFromGenesis(do.GenesisFile, do.Name) if err != nil { return err } } logger.Debugf("Starting Setup for ChnID =>\t%s\n", do.ChainID) return setupChain(do, loaders.ErisChainNew) }
func PlopChain(do *definitions.Do) error { do.Name = do.ChainID rootDir := path.Join("/home/eris/.eris/blockchains", do.ChainID) switch do.Type { case "genesis": do.Args = []string{"cat", path.Join(rootDir, "genesis.json")} case "config": do.Args = []string{"cat", path.Join(rootDir, "config.toml")} case "status": do.Args = []string{"mintinfo", "--node-addr", "http://0.0.0.0:46657", "status"} default: return fmt.Errorf("unknown plop option %s", do.Type) } return ExecChain(do) }
func NewService(do *definitions.Do) error { srv := definitions.BlankServiceDefinition() srv.Name = do.Name srv.Service.Name = do.Name srv.Service.Image = do.Operations.Args[0] srv.Service.AutoData = true var err error //get maintainer info srv.Maintainer.Name, srv.Maintainer.Email, err = config.GitConfigUser() if err != nil { log.Debug(err.Error()) } log.WithFields(log.Fields{ "service": srv.Service.Name, "image": srv.Service.Image, }).Debug("Creating a new service definition file") err = WriteServiceDefinitionFile(srv, filepath.Join(ServicesPath, do.Name+".toml")) if err != nil { return err } do.Result = "success" return nil }
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 }
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 { logger.Infoln("Chain not currently running. Skipping.") } if do.Rm { if err := perform.DockerRemove(chain.Service, chain.Operations, do.RmD, do.Volumes); err != nil { return err } } return nil }
// TODO: finish when the PR which is blocking // eris files put --dir is integrated into // ipfs func PutPackage(do *definitions.Do) error { // do.Name = args[0] var hash string = "" do.Result = hash return nil }
func MakeGenesisFile(do *def.Do) error { //otherwise it'll start its own keys server that won't have the key needed... do.Name = "keys" IfExit(srv.EnsureRunning(do)) doThr := def.NowDo() doThr.Chain.ChainType = "throwaway" //for teardown doThr.Name = "default" doThr.Operations.ContainerNumber = 1 doThr.Operations.PublishAllPorts = true logger.Infof("Starting chain from MakeGenesisFile =>\t%s\n", doThr.Name) if er := StartChain(doThr); er != nil { return fmt.Errorf("error starting chain %v\n", er) } doThr.Operations.Args = []string{"mintgen", "known", do.Chain.Name, fmt.Sprintf("--pub=%s", do.Pubkey)} doThr.Chain.Name = "default" //for teardown // pipe this output to /chains/chainName/genesis.json err := ExecChain(doThr) if err != nil { logger.Printf("exec chain err: %v\nCleaning up...\n", err) doThr.Rm = true doThr.RmD = true if err := CleanUp(doThr); err != nil { return err } } doThr.Rm = true doThr.RmD = true return CleanUp(doThr) // doesn't clean up keys but that's ~ ok b/c it's about to be used... }
func ImportService(do *definitions.Do) error { fileName := filepath.Join(ServicesPath, do.Name) if filepath.Ext(fileName) == "" { fileName = fileName + ".toml" } var err error if log.GetLevel() > 0 { err = ipfs.GetFromIPFS(do.Hash, fileName, "", os.Stdout) } else { err = ipfs.GetFromIPFS(do.Hash, fileName, "", bytes.NewBuffer([]byte{})) } if err != nil { return err } _, err = loaders.LoadServiceDefinition(do.Name, false, 0) //XXX add protections? if err != nil { return fmt.Errorf("Your service definition file looks improperly formatted and will not marshal.") } do.Result = "success" return nil }
func RmService(do *definitions.Do) error { for _, servName := range do.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) if err != nil { return err } } if do.File { oldFile := util.GetFileByNameAndType("services", servName) if err != nil { return err } oldFile = path.Join(ServicesPath, oldFile) + ".toml" logger.Printf("Removing file =>\t\t%s\n", oldFile) if err := os.Remove(oldFile); err != nil { return err } } } do.Result = "success" return nil }
func NewService(do *definitions.Do) error { srv := definitions.BlankServiceDefinition() srv.Name = do.Name srv.Service.Name = do.Name srv.Service.Image = do.Args[0] srv.Service.AutoData = true //get maintainer info uName, err := gitconfig.Username() if err != nil { logger.Debugf("Could not find git user.name, setting service.Maintainer.Name = \"\"") uName = "" } email, err := gitconfig.Email() if err != nil { logger.Debugf("Could not find git user.email, setting service.Maintainer.Email = \"\"") email = "" } srv.Maintainer.Name = uName srv.Maintainer.Email = email logger.Debugf("Creating a new srv def file =>\t%s:%s\n", srv.Service.Name, srv.Service.Image) err = WriteServiceDefinitionFile(srv, path.Join(ServicesPath, do.Name+".toml")) if err != nil { return err } do.Result = "success" return nil }
func ImportService(do *definitions.Do) error { fileName := filepath.Join(ServicesPath, do.Name) if filepath.Ext(fileName) == "" { fileName = fileName + ".toml" } var err error if logger.Level > 0 { err = ipfs.GetFromIPFS(do.Hash, fileName, "", logger.Writer) } else { err = ipfs.GetFromIPFS(do.Hash, fileName, "", bytes.NewBuffer([]byte{})) } if err != nil { return err //return fmt.Errorf("I do not know how to get that file. Sorry. %v\n", err) } _, err = loaders.LoadServiceDefinition(do.Name, false, 0) //XXX add protections? if err != nil { return fmt.Errorf("Your service defintion file looks improperly formatted and will not marshal.") } do.Result = "success" return nil }
func ImportService(do *definitions.Do) error { fileName := filepath.Join(ServicesPath, do.Name) if filepath.Ext(fileName) == "" { fileName = fileName + ".toml" } s := strings.Split(do.Path, ":") if s[0] == "ipfs" { var err error if logger.Level > 0 { err = ipfs.GetFromIPFS(s[1], fileName, "", logger.Writer) } else { err = ipfs.GetFromIPFS(s[1], fileName, "", bytes.NewBuffer([]byte{})) } if err != nil { return err } return nil } if strings.Contains(s[0], "github") { logger.Errorln("https://twitter.com/ryaneshea/status/595957712040628224") return nil } do.Result = "success" return fmt.Errorf("I do not know how to get that file. Sorry.") }
// 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 StartChain(do *definitions.Do) error { logger.Infoln("Ensuring Key Server is Started.") //should it take a flag? keys server may be running another cNum // XXX: currently we don't use or need a key server. // plus this should be specified in a service def anyways keysService, err := loaders.LoadServiceDefinition("keys", false, 1) if err != nil { return err } err = perform.DockerRun(keysService.Service, keysService.Operations) if err != nil { return err } chain, err := loaders.LoadChainDefinition(do.Name, false, do.Operations.ContainerNumber) if err != nil { logger.Infoln("Cannot start a chain I cannot find.") do.Result = "no file" return nil } if chain.Name == "" { logger.Infoln("Cannot start a chain without a name.") do.Result = "no name" return nil } chain.Service.Command = loaders.ErisChainStart if do.Run { chain.Service.Command = loaders.ErisChainStartApi } util.OverWriteOperations(chain.Operations, do.Operations) chain.Service.Environment = append(chain.Service.Environment, "CHAIN_ID="+chain.ChainID) logger.Infof("StartChainRaw to DockerRun =>\t%s\n", chain.Service.Name) logger.Debugf("\twith ChainID =>\t\t%v\n", chain.ChainID) logger.Debugf("\twith Environment =>\t%v\n", chain.Service.Environment) logger.Debugf("\twith AllPortsPublshd =>\t%v\n", chain.Operations.PublishAllPorts) if err := perform.DockerRun(chain.Service, chain.Operations); err != nil { do.Result = "error" return err } return nil }
func bootThrowAwayChain(name string, do *definitions.Do) error { do.Chain.ChainType = "throwaway" tmp := do.Name do.Name = name err := chains.ThrowAwayChain(do) if err != nil { do.Name = tmp return err } do.Chain.Name = do.Name // setting this for tear down purposes log.WithField("=>", do.Name).Debug("Throwaway chain booted") do.Name = tmp return nil }
func ListKeys(do *definitions.Do) error { if do.Host { keysPath := filepath.Join(KeysPath, "data") addrs, err := ioutil.ReadDir(keysPath) if err != nil { return err } hostAddrs := make([]string, len(addrs)) for i, addr := range addrs { hostAddrs[i] = addr.Name() } do.Result = strings.Join(hostAddrs, ",") log.WithField("=>", hostAddrs[0]).Warn("The keys on your host kind marmot:") hostAddrs = append(hostAddrs[:0], hostAddrs[1:]...) for _, addr := range hostAddrs { log.WithField("=>", addr).Warn() } } if do.Container { keysOut := new(bytes.Buffer) config.GlobalConfig.Writer = keysOut do.Name = "keys" do.Operations.ContainerNumber = 1 if err := srv.EnsureRunning(do); err != nil { return err } do.Operations.Interactive = false do.Operations.Args = []string{"ls", "/home/eris/.eris/keys/data"} if err := srv.ExecService(do); err != nil { return err } keysOutString := strings.Split(util.TrimString(string(keysOut.Bytes())), "\n") do.Result = strings.Join(keysOutString, ",") log.WithField("=>", keysOutString[0]).Warn("The keys in your container kind marmot:") keysOutString = append(keysOutString[:0], keysOutString[1:]...) for _, addr := range keysOutString { log.WithField("=>", addr).Warn() } } return nil }
func ExportKey(do *definitions.Do) error { do.Name = "keys" do.Operations.ContainerNumber = 1 if err := srv.EnsureRunning(do); err != nil { return err } //destination on host if do.Destination == "" { do.Destination = filepath.Join(KeysPath, "data") } //src in container do.Source = path.Join(ErisContainerRoot, "keys", "data", do.Address) if err := data.ExportData(do); err != nil { return err } return nil }
// Throw away chains are used for eris contracts func ThrowAwayChain(do *definitions.Do) error { do.Name = do.Name + "_" + strings.Split(uuid.New(), "-")[0] do.Path = filepath.Join(ChainsPath, "default") log.WithFields(log.Fields{ "=>": do.Name, "path": do.Path, }).Debug("Making a throaway chain") if err := NewChain(do); err != nil { return err } log.WithField("=>", do.Name).Debug("Throwaway chain created") do.Run = true // turns on edb api StartChain(do) // XXX [csk]: may not need to do this now that New starts.... log.WithField("=>", do.Name).Debug("Throwaway chain started") return nil }