...

Source file src/golang.conradwood.net/go-easyops/ctx/shared/common.go

Documentation: golang.conradwood.net/go-easyops/ctx/shared

     1  package shared
     2  
     3  import (
     4  	"context"
     5  	"reflect"
     6  	"time"
     7  
     8  	"golang.conradwood.net/apis/auth"
     9  	ge "golang.conradwood.net/apis/goeasyops"
    10  	"golang.conradwood.net/go-easyops/cmdline"
    11  	"golang.conradwood.net/go-easyops/common"
    12  	"golang.conradwood.net/go-easyops/utils"
    13  	"golang.yacloud.eu/apis/session"
    14  )
    15  
    16  const (
    17  	LOCALSTATENAME = "goeasysops_localstate"
    18  )
    19  
    20  // the local state, this is not transmitted across grpc boundaries. The Localstate is queried by functions like GetUser(ctx) etc to determine the user who called us. The context metadata is not used for this purpose. In fact, metadata != localstate: localstate includes the services which called us as CallingService(). The metadata sets "us" to the CallingService()
    21  type LocalState interface {
    22  	CreatorService() *auth.SignedUser
    23  	CallingService() *auth.SignedUser // this is the service that called us
    24  	Debug() bool
    25  	Trace() bool
    26  	User() *auth.SignedUser
    27  	SudoUser() *auth.SignedUser
    28  	Session() *session.Session
    29  	RequestID() string
    30  	RoutingTags() *ge.CTXRoutingTags
    31  	Info() string                  // return (debug) information about this localstate
    32  	Experiments() []*ge.Experiment // enabled experiments
    33  	Services() []*ge.ServiceTrace  // serviceids of services which this context passed through
    34  	AuthTags() []string            // get the authtags from context
    35  }
    36  
    37  type ContextBuilder interface {
    38  	/*
    39  		This function parses metadata found in an inbound context and, if successful, returns an "outbound" context with localstate.
    40  		the bool return parameter indicates if it was successful(true) or not(false).
    41  		Note that it requires the LOCAL service, because the calling service is modified and passed to the next service
    42  	*/
    43  	Inbound2Outbound(ctx context.Context, svc *auth.SignedUser) (context.Context, bool)
    44  	/*
    45  		return the context from this builder based on the options and WithXXX functions
    46  	*/
    47  	Context() (context.Context, context.CancelFunc)
    48  
    49  	// like Context(), but automatically call the CancelFunc after timeout
    50  	ContextWithAutoCancel() context.Context
    51  
    52  	/*
    53  	   add a user to context
    54  	*/
    55  	WithUser(user *auth.SignedUser)
    56  	/*
    57  	   set a sudo user
    58  	*/
    59  	WithSudoUser(user *auth.SignedUser)
    60  	/*
    61  	   add a creator service to context
    62  	*/
    63  	WithCreatorService(user *auth.SignedUser)
    64  
    65  	/*
    66  	   add a calling service (e.g. "me") to context
    67  	*/
    68  	WithCallingService(user *auth.SignedUser)
    69  
    70  	/*
    71  	   add a session to the context
    72  	*/
    73  	WithSession(session *session.Session)
    74  
    75  	// mark context as with debug
    76  	WithDebug()
    77  
    78  	// mark context as with trace
    79  	WithTrace()
    80  	// enable experimental feature(s)
    81  	EnableExperiment(name string)
    82  	// add routing tags
    83  	WithRoutingTags(*ge.CTXRoutingTags)
    84  	//set the requestid
    85  	WithRequestID(reqid string)
    86  	// set a timeout for this context
    87  	WithTimeout(time.Duration)
    88  	// set a parent context for cancellation propagation (does not transfer metadata to the new context!)
    89  	WithParentContext(context context.Context)
    90  	// add an authtag. may be called multiple times
    91  	WithAuthTag(tag string)
    92  }
    93  
    94  func PrettyUser(su *auth.SignedUser) string {
    95  	u := common.VerifySignedUser(su)
    96  	if u == nil {
    97  		return "NOUSER"
    98  	}
    99  	return u.Email
   100  }
   101  
   102  func Checksum(buf []byte) byte {
   103  	f := byte(0x37)
   104  	for _, b := range buf {
   105  		f = f + b
   106  	}
   107  	return f
   108  }
   109  
   110  // return "localstate" from a context. This is never "nil", but it is not guaranteed that the LocalState interface actually resolves details
   111  func GetLocalState(ctx context.Context) LocalState {
   112  	if ctx == nil {
   113  		panic("cannot get localstate from nil context")
   114  	}
   115  	v := ctx.Value(LOCALSTATENAME)
   116  	if v == nil {
   117  		/*
   118  			if *debug {
   119  				utils.PrintStack("no localstate")
   120  			}
   121  		*/
   122  		cmdline.DebugfContext("[go-easyops] context-builder warning, tried to extract localstate from context which is not a contextbuilder context\n")
   123  	}
   124  	res, ok := v.(LocalState)
   125  	if ok {
   126  		return res
   127  	}
   128  	cmdline.DebugfContext("could not get localstate from context (caller: %s)\n", utils.CallingFunction())
   129  	return newEmptyLocalState()
   130  
   131  }
   132  
   133  func isNil(v interface{}) bool {
   134  	return v == nil || (reflect.ValueOf(v).Kind() == reflect.Ptr && reflect.ValueOf(v).IsNil())
   135  }
   136  

View as plain text