github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/cloud/cloud_integration.go (about) 1 package cloud 2 3 import ( 4 "context" 5 "fmt" 6 "strconv" 7 "time" 8 9 "github.com/hashicorp/go-tfe" 10 "github.com/hashicorp/terraform/internal/backend" 11 "github.com/mitchellh/cli" 12 ) 13 14 // IntegrationOutputWriter is an interface used to to write output tailored for 15 // Terraform Cloud integrations 16 type IntegrationOutputWriter interface { 17 End() 18 OutputElapsed(message string, maxMessage int) 19 Output(str string) 20 SubOutput(str string) 21 } 22 23 // IntegrationContext is a set of data that is useful when performing Terraform Cloud integration operations 24 type IntegrationContext struct { 25 B *Cloud 26 StopContext context.Context 27 CancelContext context.Context 28 Op *backend.Operation 29 Run *tfe.Run 30 } 31 32 // integrationCLIOutput implements IntegrationOutputWriter 33 type integrationCLIOutput struct { 34 CLI cli.Ui 35 Colorizer Colorer 36 started time.Time 37 } 38 39 var _ IntegrationOutputWriter = (*integrationCLIOutput)(nil) // Compile time check 40 41 func (s *IntegrationContext) Poll(backoffMinInterval float64, backoffMaxInterval float64, every func(i int) (bool, error)) error { 42 for i := 0; ; i++ { 43 select { 44 case <-s.StopContext.Done(): 45 return s.StopContext.Err() 46 case <-s.CancelContext.Done(): 47 return s.CancelContext.Err() 48 case <-time.After(backoff(backoffMinInterval, backoffMaxInterval, i)): 49 // blocks for a time between min and max 50 } 51 52 cont, err := every(i) 53 if !cont { 54 return err 55 } 56 } 57 } 58 59 // BeginOutput writes a preamble to the CLI and creates a new IntegrationOutputWriter interface 60 // to write the remaining CLI output to. Use IntegrationOutputWriter.End() to complete integration 61 // output 62 func (s *IntegrationContext) BeginOutput(name string) IntegrationOutputWriter { 63 var result IntegrationOutputWriter = &integrationCLIOutput{ 64 CLI: s.B.CLI, 65 Colorizer: s.B.Colorize(), 66 started: time.Now(), 67 } 68 69 result.Output("\n[bold]" + name + ":\n") 70 71 return result 72 } 73 74 // End writes the termination output for the integration 75 func (s *integrationCLIOutput) End() { 76 if s.CLI == nil { 77 return 78 } 79 80 s.CLI.Output("\n------------------------------------------------------------------------\n") 81 } 82 83 // Output writes a string after colorizing it using any [colorstrings](https://github.com/mitchellh/colorstring) it contains 84 func (s *integrationCLIOutput) Output(str string) { 85 if s.CLI == nil { 86 return 87 } 88 s.CLI.Output(s.Colorizer.Color(str)) 89 } 90 91 // SubOutput writes a string prefixed by a "│ " after colorizing it using any [colorstrings](https://github.com/mitchellh/colorstring) it contains 92 func (s *integrationCLIOutput) SubOutput(str string) { 93 if s.CLI == nil { 94 return 95 } 96 s.CLI.Output(s.Colorizer.Color(fmt.Sprintf("[reset]│ %s", str))) 97 } 98 99 // OutputElapsed writes a string followed by the amount of time that has elapsed since calling BeginOutput. 100 // Example pending output; the variable spacing (50 chars) allows up to 99 tasks (two digits) in each category: 101 // --------------- 102 // 13 tasks still pending, 0 passed, 0 failed ... 103 // 13 tasks still pending, 0 passed, 0 failed ... (8s elapsed) 104 // 13 tasks still pending, 0 passed, 0 failed ... (19s elapsed) 105 // 13 tasks still pending, 0 passed, 0 failed ... (33s elapsed) 106 func (s *integrationCLIOutput) OutputElapsed(message string, maxMessage int) { 107 if s.CLI == nil { 108 return 109 } 110 elapsed := time.Since(s.started).Truncate(1 * time.Second) 111 s.CLI.Output(fmt.Sprintf("%-"+strconv.FormatInt(int64(maxMessage), 10)+"s", message) + s.Colorizer.Color(fmt.Sprintf("[dim](%s elapsed)", elapsed))) 112 }