github.com/pachyderm/pachyderm@v1.13.4/src/server/transaction/pretty/pretty.go (about) 1 package pretty 2 3 import ( 4 "fmt" 5 "html/template" 6 "io" 7 "os" 8 "strings" 9 10 "github.com/pachyderm/pachyderm/src/client/pfs" 11 "github.com/pachyderm/pachyderm/src/client/pps" 12 "github.com/pachyderm/pachyderm/src/client/transaction" 13 "github.com/pachyderm/pachyderm/src/server/pkg/pretty" 14 ) 15 16 const ( 17 //TransactionHeader is the header for transactions. 18 TransactionHeader = "TRANSACTION\tSTARTED\tOPS\t\n" 19 ) 20 21 // PrintableTransactionInfo wraps a transaction.TransactionInfo with the 22 // information needed to format it when printing. 23 type PrintableTransactionInfo struct { 24 *transaction.TransactionInfo 25 FullTimestamps bool 26 } 27 28 // PrintTransactionInfo prints a short summary of a transaction to the provided 29 // device. 30 func PrintTransactionInfo(w io.Writer, info *transaction.TransactionInfo, fullTimestamps bool) { 31 fmt.Fprintf(w, "%s\t", info.Transaction.ID) 32 if fullTimestamps { 33 fmt.Fprintf(w, "%s\t", info.Started.String()) 34 } else { 35 fmt.Fprintf(w, "%s\t", pretty.Ago(info.Started)) 36 } 37 fmt.Fprintf(w, "%d\n", len(info.Requests)) 38 } 39 40 // PrintDetailedTransactionInfo prints detailed information about a transaction 41 // to stdout. 42 func PrintDetailedTransactionInfo(info *PrintableTransactionInfo) error { 43 template, err := template.New("TransactionInfo").Funcs(funcMap).Parse( 44 `ID: {{.Transaction.ID}}{{if .FullTimestamps}} 45 Started: {{.Started}}{{else}} 46 Started: {{prettyAgo .Started}}{{end}} 47 Requests: 48 {{transactionRequests .Requests .Responses}} 49 `) 50 if err != nil { 51 return err 52 } 53 return template.Execute(os.Stdout, info) 54 } 55 56 func sprintCreateRepo(request *pfs.CreateRepoRequest) string { 57 if request.Update { 58 return fmt.Sprintf("update repo %s", request.Repo.Name) 59 } 60 return fmt.Sprintf("create repo %s", request.Repo.Name) 61 } 62 63 func sprintDeleteRepo(request *pfs.DeleteRepoRequest) string { 64 force := "" 65 if request.Force { 66 force = " --force" 67 } 68 if request.All { 69 return fmt.Sprintf("delete repo --all%s", force) 70 } 71 return fmt.Sprintf("delete repo %s %s", request.Repo.Name, force) 72 } 73 74 func sprintStartCommit(request *pfs.StartCommitRequest, response *transaction.TransactionResponse) string { 75 commit := "unknown" 76 if response == nil || response.Commit == nil { 77 commit = "ERROR (unknown response type)" 78 } else { 79 commit = response.Commit.ID 80 } 81 return fmt.Sprintf("start commit %s@%s (%s)", request.Parent.Repo.Name, request.Branch, commit) 82 } 83 84 func sprintFinishCommit(request *pfs.FinishCommitRequest) string { 85 return fmt.Sprintf("finish commit %s@%s", request.Commit.Repo.Name, request.Commit.ID) 86 } 87 88 func sprintDeleteCommit(request *pfs.DeleteCommitRequest) string { 89 return fmt.Sprintf("delete commit %s@%s", request.Commit.Repo.Name, request.Commit.ID) 90 } 91 92 func sprintCreateBranch(request *pfs.CreateBranchRequest) string { 93 provenance := "" 94 for _, p := range request.Provenance { 95 provenance = fmt.Sprintf("%s -p %s@%s", provenance, p.Repo.Name, p.Name) 96 } 97 98 return fmt.Sprintf("create branch %s@%s", request.Branch.Repo.Name, request.Branch.Name) 99 } 100 101 func sprintDeleteBranch(request *pfs.DeleteBranchRequest) string { 102 force := "" 103 if request.Force { 104 force = " --force" 105 } 106 return fmt.Sprintf("delete branch %s@%s%s", request.Branch.Repo.Name, request.Branch.Name, force) 107 } 108 109 func sprintUpdateJobState(request *pps.UpdateJobStateRequest) string { 110 state := func() string { 111 switch request.State { 112 case pps.JobState_JOB_STARTING: 113 return "STARTING" 114 case pps.JobState_JOB_RUNNING: 115 return "RUNNING" 116 case pps.JobState_JOB_FAILURE: 117 return "FAILURE" 118 case pps.JobState_JOB_SUCCESS: 119 return "SUCCESS" 120 case pps.JobState_JOB_KILLED: 121 return "KILLED" 122 case pps.JobState_JOB_MERGING: 123 return "MERGING" 124 default: 125 return "<unknown state>" 126 } 127 }() 128 return fmt.Sprintf( 129 "update job %s -> %s (%s)", 130 request.Job.ID, state, request.Reason, 131 ) 132 } 133 134 func sprintCreatePipeline(request *pps.CreatePipelineRequest) string { 135 verb := "create" 136 if request.Update { 137 verb = "update" 138 } 139 return fmt.Sprintf("%s pipeline %s", verb, request.Pipeline.Name) 140 } 141 142 func transactionRequests( 143 requests []*transaction.TransactionRequest, 144 responses []*transaction.TransactionResponse, 145 ) string { 146 if len(requests) == 0 { 147 return " -" 148 } 149 150 lines := []string{} 151 for i, request := range requests { 152 var line string 153 if request.CreateRepo != nil { 154 line = sprintCreateRepo(request.CreateRepo) 155 } else if request.DeleteRepo != nil { 156 line = sprintDeleteRepo(request.DeleteRepo) 157 } else if request.StartCommit != nil { 158 if len(responses) > i { 159 line = sprintStartCommit(request.StartCommit, responses[i]) 160 } else { 161 line = sprintStartCommit(request.StartCommit, nil) 162 } 163 } else if request.FinishCommit != nil { 164 line = sprintFinishCommit(request.FinishCommit) 165 } else if request.DeleteCommit != nil { 166 line = sprintDeleteCommit(request.DeleteCommit) 167 } else if request.CreateBranch != nil { 168 line = sprintCreateBranch(request.CreateBranch) 169 } else if request.DeleteBranch != nil { 170 line = sprintDeleteBranch(request.DeleteBranch) 171 } else if request.UpdateJobState != nil { 172 line = sprintUpdateJobState(request.UpdateJobState) 173 } else if request.CreatePipeline != nil { 174 line = sprintCreatePipeline(request.CreatePipeline) 175 } else { 176 line = "ERROR (unknown request type)" 177 } 178 lines = append(lines, fmt.Sprintf(" %s", line)) 179 } 180 181 return strings.Join(lines, "\n") 182 } 183 184 var funcMap = template.FuncMap{ 185 "prettyAgo": pretty.Ago, 186 "prettySize": pretty.Size, 187 "transactionRequests": transactionRequests, 188 }