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 }