github.com/kanishk98/terraform@v1.3.0-dev.0.20220917174235-661ca8088a6a/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(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(backoffMin, backoffMax, 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  }