github.com/crossplane/upjet@v1.3.0/pkg/terraform/operation.go (about)

     1  // SPDX-FileCopyrightText: 2023 The Crossplane Authors <https://crossplane.io>
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package terraform
     6  
     7  import (
     8  	"sync"
     9  	"time"
    10  )
    11  
    12  // Operation is the representation of a single Terraform CLI operation.
    13  type Operation struct {
    14  	Type string
    15  
    16  	startTime *time.Time
    17  	endTime   *time.Time
    18  	err       error
    19  	mu        sync.RWMutex
    20  }
    21  
    22  // MarkStart marks the operation as started atomically after checking
    23  // no previous operation is already running.
    24  // Returns `false` if a previous operation is still in progress.
    25  func (o *Operation) MarkStart(t string) bool {
    26  	o.mu.Lock()
    27  	defer o.mu.Unlock()
    28  	if o.startTime != nil && o.endTime == nil {
    29  		return false
    30  	}
    31  	now := time.Now()
    32  	o.Type = t
    33  	o.startTime = &now
    34  	o.endTime = nil
    35  	return true
    36  }
    37  
    38  // MarkEnd marks the operation as ended.
    39  func (o *Operation) MarkEnd() {
    40  	o.mu.Lock()
    41  	defer o.mu.Unlock()
    42  	now := time.Now()
    43  	o.endTime = &now
    44  }
    45  
    46  // Flush cleans the operation information including the registered error from
    47  // the last reconciliation.
    48  // Deprecated: Please use Clear, which allows optionally preserving the error
    49  // from the last reconciliation to implement proper SYNC status condition for
    50  // the asynchronous external clients.
    51  func (o *Operation) Flush() {
    52  	o.Clear(false)
    53  }
    54  
    55  // Clear clears the operation information optionally preserving the last
    56  // registered error from the last reconciliation.
    57  func (o *Operation) Clear(preserveError bool) {
    58  	o.mu.Lock()
    59  	defer o.mu.Unlock()
    60  	o.Type = ""
    61  	o.startTime = nil
    62  	o.endTime = nil
    63  	if !preserveError {
    64  		o.err = nil
    65  	}
    66  }
    67  
    68  // IsEnded returns whether the operation has ended, regardless of its result.
    69  func (o *Operation) IsEnded() bool {
    70  	o.mu.RLock()
    71  	defer o.mu.RUnlock()
    72  	return o.endTime != nil
    73  }
    74  
    75  // IsRunning returns whether there is an ongoing operation.
    76  func (o *Operation) IsRunning() bool {
    77  	o.mu.RLock()
    78  	defer o.mu.RUnlock()
    79  	return o.startTime != nil && o.endTime == nil
    80  }
    81  
    82  // StartTime returns the start time of the current operation.
    83  func (o *Operation) StartTime() time.Time {
    84  	o.mu.RLock()
    85  	defer o.mu.RUnlock()
    86  	return *o.startTime
    87  }
    88  
    89  // EndTime returns the end time of the current operation.
    90  func (o *Operation) EndTime() time.Time {
    91  	o.mu.RLock()
    92  	defer o.mu.RUnlock()
    93  	return *o.endTime
    94  }
    95  
    96  // SetError records the given error on the current operation.
    97  func (o *Operation) SetError(err error) {
    98  	o.mu.Lock()
    99  	defer o.mu.Unlock()
   100  	o.err = err
   101  }
   102  
   103  // Error returns the recorded error of the current operation.
   104  func (o *Operation) Error() error {
   105  	o.mu.RLock()
   106  	defer o.mu.RUnlock()
   107  	return o.err
   108  }