code.cloudfoundry.org/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  }