code: func (s *APIServer) upsertServer(auth ClientI, role teleport.Role, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
  	var req upsertServerRawReq
  	if err := httplib.ReadJSON(r, &req); err != nil {
  		return nil, trace.Wrap(err)
  	}
  	var kind string
  	switch role {
  	case teleport.RoleNode:
  		kind = services.KindNode
  	case teleport.RoleAuth:
  		kind = services.KindAuthServer
  	case teleport.RoleProxy:
  		kind = services.KindProxy
  	}
  	server, err := services.GetServerMarshaler().UnmarshalServer(req.Server, kind)
  	if err != nil {
  		return nil, trace.Wrap(err)
  	}
  	// if server sent "local" IP address to us, replace the ip/host part with the remote address we see
  	// on the socket, but keep the original port:
  	server.SetAddr(utils.ReplaceLocalhost(server.GetAddr(), r.RemoteAddr))
  	if req.TTL != 0 {
  		server.SetTTL(s, req.TTL)
  	}
  	switch role {
  	case teleport.RoleNode:
  		namespace := p.ByName("namespace")
  		if !services.IsValidNamespace(namespace) {
  			return nil, trace.BadParameter("invalid namespace %q", namespace)
  		}
  		server.SetNamespace(namespace)
  		handle, err := auth.UpsertNode(server)
  		if err != nil {
  			return nil, trace.Wrap(err)
  		}
  		return handle, nil
  	case teleport.RoleAuth:
  		if err := auth.UpsertAuthServer(server); err != nil {
  			return nil, trace.Wrap(err)
  		}
  	case teleport.RoleProxy:
  		if err := auth.UpsertProxy(server); err != nil {
  			return nil, trace.Wrap(err)
  		}
  	}
  	return message("ok"), nil
  }
docs: // upsertServer is a common utility function