github.com/nmanchovski/burrow@v0.25.0/deploy/run_deploy.go (about) 1 package pkgs 2 3 import ( 4 "bytes" 5 "fmt" 6 "os" 7 "path/filepath" 8 "time" 9 10 "github.com/go-kit/kit/log" 11 "github.com/hyperledger/burrow/deploy/def" 12 "github.com/hyperledger/burrow/deploy/jobs" 13 "github.com/hyperledger/burrow/deploy/loader" 14 "github.com/hyperledger/burrow/execution/evm/abi" 15 "github.com/hyperledger/burrow/logging" 16 ) 17 18 type playbookWork struct { 19 playbook string 20 jobNo int 21 } 22 23 type playbookResult struct { 24 jobNo int 25 log bytes.Buffer 26 err error 27 duration time.Duration 28 } 29 30 func worker(playbooks <-chan playbookWork, results chan<- playbookResult, args *def.DeployArgs, logger *logging.Logger) { 31 32 client := def.NewClient(args.Chain, args.KeysService, args.MempoolSign, time.Duration(args.Timeout)*time.Second) 33 34 for playbook := range playbooks { 35 doWork := func(work playbookWork) (logBuf bytes.Buffer, err error) { 36 // block that triggers if the do.Path was NOT set 37 // via cli flag... or not 38 fname := filepath.Join(args.Path, work.playbook) 39 40 // if YAMLPath cannot be found, abort 41 if _, err := os.Stat(fname); os.IsNotExist(err) { 42 return logBuf, fmt.Errorf("could not find playbook file (%s)", 43 fname) 44 } 45 46 if args.Jobs != 1 { 47 logger = logging.NewLogger(log.NewLogfmtLogger(&logBuf)) 48 if !args.Debug { 49 logger.Trace = log.NewNopLogger() 50 } 51 } 52 53 // Load the package if it doesn't exist 54 script, err := loader.LoadPlaybook(fname, args, logger) 55 if err != nil { 56 return logBuf, err 57 } 58 59 // Load existing bin files to decode events 60 var abiError error 61 client.AllSpecs, abiError = abi.LoadPath(script.BinPath) 62 if err != nil { 63 logger.InfoMsg("failed to load ABIs for Event parsing", "path", script.BinPath, "error", abiError) 64 } 65 66 err = jobs.ExecutePlaybook(args, script, client, logger) 67 return 68 } 69 70 startTime := time.Now() 71 logBuf, err := doWork(playbook) 72 results <- playbookResult{ 73 jobNo: playbook.jobNo, 74 log: logBuf, 75 err: err, 76 duration: time.Since(startTime), 77 } 78 } 79 } 80 81 // RunPlaybooks starts workers, and loads the playbooks in parallel in the workers, and executes them. 82 func RunPlaybooks(args *def.DeployArgs, playbooks []string, logger *logging.Logger) (int, error) { 83 // if bin and abi paths are default cli settings then use the 84 // stated defaults of do.Path plus bin|abi 85 if args.Path == "" { 86 var err error 87 args.Path, err = os.Getwd() 88 if err != nil { 89 panic(fmt.Sprintf("failed to get current directory %v", err)) 90 } 91 } 92 93 // useful for debugging 94 logger.InfoMsg("Using chain", "Chain", args.Chain, "Signer", args.KeysService) 95 96 workQ := make(chan playbookWork, 100) 97 resultQ := make(chan playbookResult, 100) 98 99 for i := 1; i <= args.Jobs; i++ { 100 go worker(workQ, resultQ, args, logger) 101 } 102 103 for i, playbook := range playbooks { 104 workQ <- playbookWork{jobNo: i, playbook: playbook} 105 } 106 close(workQ) 107 108 // work queued, now read the results 109 results := make([]*playbookResult, len(playbooks)) 110 printed := 0 111 failures := 0 112 successes := 0 113 114 for range playbooks { 115 jobResult := <-resultQ 116 results[jobResult.jobNo] = &jobResult 117 for results[printed] != nil { 118 res := results[printed] 119 os.Stderr.Write(res.log.Bytes()) 120 if res.err != nil { 121 fmt.Fprintf(os.Stderr, "ERROR: %v", res.err) 122 } 123 res.log.Truncate(0) 124 if jobResult.err != nil { 125 failures++ 126 } else { 127 successes++ 128 } 129 printed++ 130 if printed >= len(playbooks) { 131 break 132 } 133 } 134 } 135 close(resultQ) 136 137 if successes > 0 { 138 logger.InfoMsg("JOBS THAT SUCCEEEDED", "count", successes) 139 for i, playbook := range playbooks { 140 res := results[i] 141 if res.err != nil { 142 continue 143 } 144 logger.InfoMsg("Playbook result", 145 "jobNo", i, 146 "file", playbook, 147 "time", res.duration.String()) 148 } 149 } 150 151 if failures > 0 { 152 logger.InfoMsg("JOBS THAT FAILED", "count", failures) 153 for i, playbook := range playbooks { 154 res := results[i] 155 if res.err == nil { 156 continue 157 } 158 logger.InfoMsg("Playbook result", 159 "jobNo", i, 160 "file", playbook, 161 "error", res.err, 162 "time", res.duration.String()) 163 } 164 } 165 166 return failures, nil 167 }