...

Source file src/golang.conradwood.net/go-easyops/standalone/standalone.go

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

     1  /*
     2  Package standalone handles applications running in "standalone" mode (that is without failover/datacenter etc)
     3  */
     4  package standalone
     5  
     6  // a standalone "registry replacement"
     7  
     8  import (
     9  	"context"
    10  	"flag"
    11  	"fmt"
    12  	reg "golang.conradwood.net/apis/registry"
    13  	"golang.conradwood.net/go-easyops/cmdline"
    14  	"golang.conradwood.net/go-easyops/utils"
    15  	"net"
    16  	"strings"
    17  )
    18  
    19  var (
    20  	debug = flag.Bool("ge_debug_standalone", false, "if true debug the standalone dialler")
    21  	// if we receive requests to resolve any of those (and they don't happen to be available), we panic
    22  	UNSUPPORTED_SERVICES = []string{""}
    23  )
    24  
    25  // register a service with the local "registry"
    26  func RegisterService(rsr *reg.RegisterServiceRequest) (string, error) {
    27  	dir := cmdline.LocalRegistrationDir()
    28  	if !utils.FileExists(dir) {
    29  		utils.Bail("failed to create register dir", utils.RecreateSafely(dir))
    30  	}
    31  	b, err := utils.MarshalBytes(rsr)
    32  	if err != nil {
    33  		panic(fmt.Sprintf("failed to marshal proto (BUG!): %s", err))
    34  	}
    35  	fname := fmt.Sprintf("%s/%s.proto", dir, rsr.ServiceName)
    36  	t := utils.FileExists(fname)
    37  	err = utils.WriteFile(fname, b)
    38  	if err != nil {
    39  		panic(fmt.Sprintf("failed to write standalone registration details to %s: %s", fname, err))
    40  	}
    41  	if !t {
    42  		fmt.Printf("[go-easyops] Registered service \"%s\" in %s\n", rsr.ServiceName, fname)
    43  	}
    44  	return "local", nil
    45  }
    46  
    47  // dial a service (using local "registry" to find the local port)
    48  // serviceurl is something like "direct://[host]:port"
    49  func DialService(ctx context.Context, serviceurl string) (net.Conn, error) {
    50  	if !strings.HasPrefix(serviceurl, "direct://") {
    51  		panic(fmt.Sprintf("[go-easyops] standalone unsupported serviceurl \"%s\"", serviceurl))
    52  	}
    53  	dialstring := strings.TrimPrefix(serviceurl, "direct://")
    54  	if *debug {
    55  		fmt.Printf("[go-easyops] standalone dialler dialing \"%s\"\n", dialstring)
    56  	}
    57  	conn, err := (&net.Dialer{}).DialContext(ctx, "tcp", dialstring)
    58  
    59  	if err != nil {
    60  		fmt.Printf("[go-easyops] standalone dialling error: %s\n", err)
    61  	}
    62  	if *debug {
    63  		fmt.Printf("[go-easyops] standalone dialler connection established to \"%s\"\n", dialstring)
    64  	}
    65  	return conn, err
    66  }
    67  
    68  // find all registrations for a given service
    69  func Registry_V2GetTarget(ctx context.Context, req *reg.V2GetTargetRequest) (*reg.V2GetTargetResponse, error) {
    70  	if *debug {
    71  		fmt.Printf("[go-easyops] standalone resolving service \"%s\"...\n", req.ServiceName)
    72  	}
    73  	res := &reg.V2GetTargetResponse{}
    74  	dir := cmdline.LocalRegistrationDir()
    75  	for _, serviceName := range req.ServiceName {
    76  		fname := fmt.Sprintf("%s/%s.proto", dir, serviceName)
    77  		if !utils.FileExists(fname) {
    78  			fmt.Printf("[go-easyops] standalone resolver: file %s does not exist\n", fname)
    79  			is_well_known_unsupported(serviceName)
    80  			return res, nil
    81  		}
    82  		b, err := utils.ReadFile(fname)
    83  		if err != nil {
    84  			fmt.Printf("[go-easyops] standalone resolver: cannot read file %s: %s\n", fname, err)
    85  			return nil, err
    86  		}
    87  		rsr := &reg.RegisterServiceRequest{}
    88  		err = utils.UnmarshalBytes(b, rsr)
    89  		if err != nil {
    90  			fmt.Printf("[go-easyops] standalone resolver: cannot parse file %s: %s\n", fname, err)
    91  			return nil, err
    92  		}
    93  		t, err := registration_request_to_target(rsr)
    94  		if err != nil {
    95  			fmt.Printf("[go-easyops] standalone resolver: failed to convert file %s: %s\n", fname, err)
    96  			return nil, err
    97  		}
    98  		res.Targets = append(res.Targets, t)
    99  	}
   100  	if len(res.Targets) == 0 {
   101  		for _, s := range req.ServiceName {
   102  			is_well_known_unsupported(s)
   103  		}
   104  	}
   105  
   106  	return res, nil
   107  }
   108  func is_well_known_unsupported(s string) {
   109  	for _, u := range UNSUPPORTED_SERVICES {
   110  		if u == s {
   111  			panic(fmt.Sprintf("[go-easyops] standalone does not support well-known service \"%s\".", s))
   112  		}
   113  	}
   114  }
   115  func registration_request_to_target(rsr *reg.RegisterServiceRequest) (*reg.Target, error) {
   116  	res := &reg.Target{
   117  		IP:          "localhost",
   118  		ServiceName: rsr.ServiceName,
   119  		Port:        rsr.Port,
   120  		ApiType:     []reg.Apitype{reg.Apitype_grpc},
   121  		RoutingInfo: &reg.RoutingInfo{},
   122  	}
   123  	return res, nil
   124  }
   125  

View as plain text