code: func (c *NodeCommand) Invite(client auth.ClientI) error {
  	// parse --roles flag
  	roles, err := teleport.ParseRoles(c.roles)
  	if err != nil {
  		return trace.Wrap(err)
  	}
  	token, err := client.GenerateToken(auth.GenerateTokenRequest{Roles: roles, TTL: c.ttl, Token: c.token})
  	if err != nil {
  		return trace.Wrap(err)
  	}
  
  	// Calculate the CA pin for this cluster. The CA pin is used by the client
  	// to verify the identity of the Auth Server.
  	caPin, err := calculateCAPin(client)
  	if err != nil {
  		return trace.Wrap(err)
  	}
  
  	authServers, err := client.GetAuthServers()
  	if err != nil {
  		return trace.Wrap(err)
  	}
  	if len(authServers) == 0 {
  		return trace.Errorf("This cluster does not have any auth servers running.")
  	}
  
  	// output format swtich:
  	if c.format == "text" {
  		if roles.Include(teleport.RoleTrustedCluster) || roles.Include(teleport.LegacyClusterTokenType) {
  			fmt.Printf(trustedClusterMessage, token, int(c.ttl.Minutes()))
  		} else {
  			fmt.Printf(nodeMessage,
  				token,
  				int(c.ttl.Minutes()),
  				strings.ToLower(roles.String()),
  				token,
  				caPin,
  				authServers[0].GetAddr(),
  				int(c.ttl.Minutes()),
  				authServers[0].GetAddr(),
  			)
  		}
  	} else {
  		// Always return a list, otherwise we'll break users tooling. See #1846 for
  		// more details.
  		tokens := []string{token}
  		out, err := json.Marshal(tokens)
  		if err != nil {
  			return trace.Wrap(err, "failed to marshal token")
  		}
  		fmt.Printf(string(out))
  	}
  	return nil
  }
docs: // Invite generates a token which can be used to add another SSH node
  // to a cluster