github.com/Tri-stone/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  }