github.com/sleungcy-sap/cli@v7.1.0+incompatible/actor/v7action/logging.go (about) 1 package v7action 2 3 import ( 4 "context" 5 "errors" 6 "strings" 7 "time" 8 9 "code.cloudfoundry.org/cli/actor/sharedaction" 10 "github.com/SermoDigital/jose/jws" 11 ) 12 13 func (actor Actor) GetStreamingLogsForApplicationByNameAndSpace(appName string, spaceGUID string, client sharedaction.LogCacheClient) (<-chan sharedaction.LogMessage, <-chan error, context.CancelFunc, Warnings, error) { 14 app, allWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) 15 if err != nil { 16 return nil, nil, nil, allWarnings, err 17 } 18 19 messages, logErrs, cancelFunc := sharedaction.GetStreamingLogs(app.GUID, client) 20 21 return messages, logErrs, cancelFunc, allWarnings, err 22 } 23 24 func (actor Actor) GetRecentLogsForApplicationByNameAndSpace(appName string, spaceGUID string, client sharedaction.LogCacheClient) ([]sharedaction.LogMessage, Warnings, error) { 25 app, allWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) 26 if err != nil { 27 return nil, allWarnings, err 28 } 29 30 logCacheMessages, err := sharedaction.GetRecentLogs(app.GUID, client) 31 if err != nil { 32 return nil, allWarnings, err 33 } 34 35 var logMessages []sharedaction.LogMessage 36 37 for _, message := range logCacheMessages { 38 logMessages = append(logMessages, *sharedaction.NewLogMessage( 39 message.Message(), 40 message.Type(), 41 message.Timestamp(), 42 message.SourceType(), 43 message.SourceInstance(), 44 )) 45 } 46 47 return logMessages, allWarnings, nil 48 } 49 50 func (actor Actor) ScheduleTokenRefresh( 51 after func(time.Duration) <-chan time.Time, 52 stop chan struct{}, 53 stoppedRefreshingToken chan struct{}) (<-chan error, error) { 54 55 timeToRefresh, err := actor.refreshAccessTokenIfNecessary() 56 if err != nil { 57 close(stoppedRefreshingToken) 58 return nil, err 59 } 60 61 refreshErrs := make(chan error) 62 63 go func() { 64 defer close(stoppedRefreshingToken) 65 for { 66 select { 67 case <-after(*timeToRefresh): 68 d, err := actor.refreshAccessTokenIfNecessary() 69 if err == nil { 70 timeToRefresh = d 71 } else { 72 refreshErrs <- err 73 } 74 case <-stop: 75 return 76 } 77 } 78 }() 79 80 return refreshErrs, nil 81 } 82 83 func (actor Actor) refreshAccessTokenIfNecessary() (*time.Duration, error) { 84 accessToken := actor.Config.AccessToken() 85 86 duration, err := actor.tokenExpiryTime(accessToken) 87 if err != nil || *duration < time.Minute { 88 accessToken, err = actor.RefreshAccessToken() 89 if err != nil { 90 return nil, err 91 } 92 } 93 94 accessToken = strings.TrimPrefix(accessToken, "bearer ") 95 token, err := jws.ParseJWT([]byte(accessToken)) 96 if err != nil { 97 return nil, err 98 } 99 100 var timeToRefresh time.Duration 101 expiration, ok := token.Claims().Expiration() 102 if !ok { 103 return nil, errors.New("Failed to get an expiry time from the current access token") 104 } 105 expiresIn := time.Until(expiration) 106 if expiresIn >= 2*time.Minute { 107 timeToRefresh = expiresIn - time.Minute 108 } else { 109 timeToRefresh = expiresIn * 9 / 10 110 } 111 return &timeToRefresh, nil 112 } 113 114 func (actor Actor) tokenExpiryTime(accessToken string) (*time.Duration, error) { 115 var expiresIn time.Duration 116 117 accessTokenString := strings.TrimPrefix(accessToken, "bearer ") 118 token, err := jws.ParseJWT([]byte(accessTokenString)) 119 if err != nil { 120 return nil, err 121 } 122 123 expiration, ok := token.Claims().Expiration() 124 if ok { 125 expiresIn = time.Until(expiration) 126 } 127 return &expiresIn, nil 128 }