...

Source file src/golang.conradwood.net/go-easyops/rpc/callstate.go

Documentation: golang.conradwood.net/go-easyops/rpc

     1  /*
     2  deprecated. See ctx package for a replacement implementation.
     3  */
     4  package rpc
     5  
     6  import (
     7  	"flag"
     8  	"fmt"
     9  	"golang.conradwood.net/apis/auth"
    10  	ge "golang.conradwood.net/apis/goeasyops"
    11  	"golang.conradwood.net/go-easyops/common"
    12  	"golang.conradwood.net/go-easyops/prometheus"
    13  	//	"golang.conradwood.net/go-easyops/tokens"
    14  	"golang.org/x/net/context"
    15  	"time"
    16  )
    17  
    18  const (
    19  	LOCALCONTEXTNAME   = "GOEASYOPS_LOCALCTX"
    20  	LOCALCONTEXTNAMEV2 = "GOEASYOPS_LOCALCTX_V2"
    21  	// timeout for newly created context in this package
    22  	DEFAULT_TIMEOUT_SECS = 10
    23  )
    24  
    25  var (
    26  	moan_about_no_auth = flag.Bool("ge_debug_print_old_signatures", false, "if true print services which are calling this module with old-style signatures")
    27  	userSourceMetric   = prometheus.NewCounterVec(
    28  		prometheus.CounterOpts{
    29  			Name: "grpc_requests_user_source",
    30  			Help: "V=1 UNIT=ops DESC=RPC requests with users, split by source",
    31  		},
    32  		[]string{"servicename", "method", "source"},
    33  	)
    34  )
    35  
    36  func init() {
    37  	prometheus.MustRegister(userSourceMetric)
    38  }
    39  
    40  // information about our local call stack.
    41  // this should always have been an interface, really..
    42  type CallState struct {
    43  	// v1
    44  	Debug           bool
    45  	Started         time.Time
    46  	ServiceName     string          // this is our servicename (the one this module exports)
    47  	MethodName      string          // the method that was called (the one we are implementing)
    48  	CallingMethodID uint64          // who called us (maybe 0)
    49  	Context         context.Context // guaranteed to be the most "up-to-date" context.
    50  	MyServiceID     uint64          // that is us (our local serviceid)
    51  	userCounted     bool
    52  	// v2
    53  	v2            LocalCallState // might be nil for old stuff
    54  	isV2          bool
    55  	signedUser    *auth.SignedUser
    56  	signedService *auth.SignedUser
    57  }
    58  
    59  // this now is a "V2" style callstate
    60  func (c *CallState) SetV2(lcs LocalCallState) {
    61  	c.v2 = lcs
    62  	c.isV2 = true
    63  }
    64  func (c *CallState) IsV2() bool {
    65  	return c.isV2
    66  }
    67  func EnableDebug(ctx context.Context) {
    68  	cs := CallStateFromContext(ctx)
    69  	if cs == nil {
    70  		return
    71  	}
    72  	cs.Debug = true
    73  }
    74  
    75  func (cs *CallState) RequestID() string {
    76  	if cs.IsV2() {
    77  		return cs.v2.RequestID()
    78  	}
    79  	panic("obsolete codepath")
    80  }
    81  
    82  func (cs *CallState) SignedUser() *auth.SignedUser {
    83  	return cs.signedUser
    84  
    85  }
    86  func (cs *CallState) SignedService() *auth.SignedUser {
    87  	return cs.signedService
    88  }
    89  
    90  // return the authenticated user
    91  func (cs *CallState) User() *auth.User {
    92  	if cs == nil {
    93  		return nil
    94  	}
    95  	if cs.IsV2() {
    96  		return cs.v2.User()
    97  	}
    98  	panic("obsolete codepath")
    99  }
   100  
   101  func (cs *CallState) userbysource(src string) {
   102  	if cs.userCounted {
   103  		return
   104  	}
   105  	if *moan_about_no_auth && src != "signedv2" && src != "none" {
   106  		sn := "undef"
   107  		s := cs.CallerService()
   108  		if s != nil {
   109  			sn = fmt.Sprintf("%s/%s", s.ID, s.Email)
   110  		}
   111  		fmt.Printf("[go-easyops] service %s called us with old style signature \"%s\"\n", sn, src)
   112  	}
   113  	l := prometheus.Labels{"servicename": cs.ServiceName, "method": cs.MethodName, "source": src}
   114  	userSourceMetric.With(l).Inc()
   115  }
   116  
   117  // return the authenticated service
   118  func (cs *CallState) CallerService() *auth.User {
   119  	if cs == nil {
   120  		return nil
   121  	}
   122  	if cs.IsV2() {
   123  		return cs.v2.CallingService()
   124  	}
   125  	panic("obsolete codepath")
   126  }
   127  func (cs *CallState) TargetString() string {
   128  	if cs == nil {
   129  		return ""
   130  	}
   131  	return fmt.Sprintf("%s.%s", cs.ServiceName, cs.MethodName)
   132  }
   133  func (cs *CallState) CallerString() string {
   134  	if cs == nil {
   135  		return ""
   136  	}
   137  	u := common.VerifySignedUser(cs.SignedUser())
   138  	if u == nil {
   139  		return ""
   140  	}
   141  	return u.Abbrev
   142  
   143  }
   144  
   145  // print context (if debug enabled)
   146  func (cs *CallState) DebugPrintContext() {
   147  	if cs == nil || !cs.Debug {
   148  		return
   149  	}
   150  	cs.PrintContext()
   151  }
   152  func (cs *CallState) RoutingTags() *ge.CTXRoutingTags {
   153  	if cs == nil {
   154  		return nil
   155  	}
   156  	if cs.IsV2() {
   157  		return cs.v2.RoutingTags()
   158  	}
   159  	panic("obsolete codepath")
   160  }
   161  func (cs *CallState) PrintContext() {
   162  	if cs == nil {
   163  		fmt.Printf("[go-easyops] Context has no Callstate\n")
   164  		return
   165  	}
   166  	fmt.Printf("[go-easyops] printing old style context (%v)", cs.v2)
   167  	/*
   168  		lcv := CallStateFromContext(cs.Context)
   169  		ls := "missing"
   170  		if lcv != nil {
   171  			if lcv.Metadata == nil {
   172  				ls = "metadata missing"
   173  			} else {
   174  				ls = fmt.Sprintf("present (requestid: \"%s\")", lcv.Metadata.RequestID)
   175  			}
   176  		}
   177  		fmt.Printf("[go-easyops] Local Context value: %s\n", ls)
   178  		md, ex := metadata.FromIncomingContext(cs.Context)
   179  		if ex {
   180  			fmt.Printf("[go-easyops] InboundMeta: %v\n", metaToString(md))
   181  		} else {
   182  			fmt.Printf("[go-easyops] InboundMeta: NONE\n")
   183  		}
   184  		md, ex = metadata.FromOutgoingContext(cs.Context)
   185  		if ex {
   186  			fmt.Printf("[go-easyops] OutboundMeta: %v\n", metaToString(md))
   187  		} else {
   188  			fmt.Printf("[go-easyops] OutboundMeta: NONE\n")
   189  		}
   190  	*/
   191  }
   192  func desc(u *auth.User) string {
   193  	if u == nil {
   194  		return "NONE"
   195  	}
   196  	return fmt.Sprintf("%s[%s]", u.ID, u.Email)
   197  }
   198  func (cs *CallState) DISMetadataValue() string {
   199  	return ""
   200  }
   201  func CallStateFromContext(ctx context.Context) *CallState {
   202  	if ctx == nil {
   203  		return nil
   204  	}
   205  	lcv := ctx.Value(LOCALCONTEXTNAME)
   206  	if lcv == nil {
   207  		return nil
   208  	}
   209  	return lcv.(*CallState)
   210  }
   211  
   212  // add the information from the interceptor response into the context
   213  // it replaces the context data with information held in callstate
   214  // it adds it in two distinct ways:
   215  // 1. Accessible as a local context Variable
   216  // 2. Ready to be transmitted via metadata (in case the context is use for outbound calls)
   217  func (cs *CallState) UpdateContextFromResponse() error {
   218  	return cs.UpdateContextFromResponseWithTimeout(time.Duration(10) * time.Second)
   219  }
   220  func (cs *CallState) UpdateContextFromResponseWithTimeout(t time.Duration) error {
   221  	panic("obsolete codepath")
   222  }
   223  
   224  func ContextWithCallState(ctx context.Context) (context.Context, *CallState) {
   225  	cs := &CallState{}
   226  	nc := context.WithValue(ctx, LOCALCONTEXTNAME, cs)
   227  	return nc, cs
   228  }
   229  func (cs *CallState) SignedSession() *auth.SignedSession {
   230  	if cs.IsV2() {
   231  		return cs.v2.SignedSession()
   232  	}
   233  	panic("obsolete codepath")
   234  }
   235  

View as plain text