// load config via login service
func (s *serviceToService) load() error {
	svc := s.getService()
	if svc == "" {
		log.Debug("[Auth] Skipping loading service-to-service auth rules (no service defined)")
		return nil
	}

	log.Tracef("[Auth] Loading service-to-service auth rules for %s", svc)
	reqProto := &endpointauth.Request{
		Service: proto.String(svc),
	}
	req, err := client.NewRequest("com.hailocab.service.login", "endpointauth", reqProto)
	if err != nil {
		return err
	}
	// scope it
	req.SetFrom(svc)
	rsp := &endpointauth.Response{}
	if err := client.Req(req, rsp); err != nil {
		return err
	}

	newEndpoints := make(map[string]grantedServices)

	for _, ep := range rsp.GetEndpoints() {
		name := ep.GetEndpoint()
		if _, ok := newEndpoints[name]; !ok {
			newEndpoints[name] = make(grantedServices)
		}
		// add in the granted services to this endpoint
		for _, gs := range ep.GetGranted() {
			newEndpoints[name][gs.GetName()] = role(gs.GetRole())
		}
	}

	// check if changed - to avoid locking/changing/logging if not
	if hashEndpoints(newEndpoints) == s.hash() {
		return nil
	}

	// switch in config
	s.Lock()
	defer s.Unlock()
	s.endpoints = newEndpoints

	log.Debugf("[Auth] Loaded service-to-service auth rules: %#v", s.endpoints)

	return nil
}
// PlatformCaller is the default caller and makes requests via the platform layer
// RPC mechanism (eg: RabbitMQ)
func PlatformCaller() Caller {
	return func(req *client.Request, rsp proto.Message) errors.Error {
		return client.Req(req, rsp)
	}
}
// callDiscoveryService sends off a request to register or unregister to the discovery service
func (self *discovery) callDiscoveryService(action string, successState bool) error {
	log.Infof("[Server] Attempting to %s with the discovery service...", action)

	azName, _ := util.GetAwsAZName()
	regSize := reg.size()
	machineClass := os.Getenv("H2O_MACHINE_CLASS")

	endpoints := make([]*register.MultiRequest_Endpoint, regSize)
	i := 0
	for _, endpoint := range reg.iterate() {
		endpoints[i] = &register.MultiRequest_Endpoint{
			Name:      proto.String(endpoint.Name),
			Mean:      proto.Int32(endpoint.Mean),
			Upper95:   proto.Int32(endpoint.Upper95),
			Subscribe: proto.String(endpoint.Subscribe),
		}

		i++
	}

	service := &dscShared.Service{
		Name:        proto.String(Name),
		Description: proto.String(Description),
		Version:     proto.Uint64(Version),
		Source:      proto.String(Source),
		OwnerEmail:  proto.String(OwnerEmail),
		OwnerMobile: proto.String(OwnerMobile),
		OwnerTeam:   proto.String(OwnerTeam),
	}

	request, err := ScopedRequest(
		"com.hailocab.kernel.discovery",
		action,
		&register.MultiRequest{
			InstanceId:   proto.String(InstanceID),
			Hostname:     proto.String(self.hostname),
			MachineClass: proto.String(machineClass),
			AzName:       proto.String(azName),
			Service:      service,
			Endpoints:    endpoints,
		},
	)

	if err != nil {
		log.Warnf("[Server] Failed to build request when %sing services", action)
		return err
	}

	// explicitly define timeout, since we're happy to wait
	clientOptions := client.Options{"retries": 0, "timeout": 5 * time.Second}

	rsp := &register.Response{}
	if err := client.Req(request, rsp, clientOptions); err != nil {
		log.Warnf("[Server] Failed to %s services: %v", action, err)
		return err
	}

	// ok -- all done!
	self.connected = successState
	log.Infof("[Server] Successfully %sed with the hive mind!", action)

	return nil
}