package module
Version: v0.0.0-...-7a4e406 Latest Latest

This package is not in the latest version of its module.

Go to latest
Published: May 27, 2022 License: Apache-2.0 Imports: 15 Imported by: 59


CF Routing API Server

The purpose of the Routing API is to present a RESTful interface for registering and deregistering routes for both internal and external clients. This allows easier consumption by different clients as well as the ability to register routes from outside of the CF deployment.

Note: This repository should be imported as

Reporting issues and requesting features

Please report all issues and feature requests in cloudfoundry/routing-release.

Downloading and Installing

External Dependencies
  • Go should be installed and in the PATH
  • This repo is part of routing-release bosh release repo. So to work on routing-api you will need to checkout routing-release and follow instructions in its README.
Development Setup

Refer to routing-release README for development setup.


To run the tests you need a running RDB (either Postgres or MySQL). Currently there is a helper script under routing-release which runs tests in docker container. cf-routing-pipeline docker image used in the below script is configured with correct version of MySQL and Postgres for testing purposes. To run the tests for routing-api:

./scripts/run-unit-tests-in-docker routing-api
Local Database Instances in Docker

A Docker Compose is provided to start the database locally for testing.

$ docker-compose up
postgress_1  | 2020-11-12 18:00:21.618 UTC [1] LOG:  database system is ready to accept connections
mysql_1      | [Entrypoint] Starting MySQL 5.7.32-1.1.18

Running the API Server

Server Configuration
jwt token

To run the routing-api server, a configuration file with the public uaa jwt token must be provided. This configuration file can then be passed in with the flag -config [path_to_config]. An example of the configuration file can be found under example_config/example.yml for bosh-lite.

To generate your own config file, you must provide a uaa_verification_key in pem format, such as the following:

uaa_verification_key: |
  -----BEGIN PUBLIC KEY-----
  -----END PUBLIC KEY-----

This can be found in your Cloud Foundry manifest under uaa.jwt.verification_key

Oauth Clients

The Routing API uses OAuth tokens to authenticate clients. To obtain a token from UAA that grants the API client permission to register routes, an OAuth client must first be created for the API client in UAA. An API client can then authenticate with UAA using the registered OAuth client credentials, request a token, then provide this token with requests to the Routing API.

Registering OAuth clients can be done using the cf-release BOSH deployment manifest, or manually using the uaac CLI for UAA.

  • For API clients that wish to register/unregister routes with the Routing API, the OAuth client in UAA must be configured with the routing.routes.write authority.
  • For API clients that wish to list routes with the Routing API, the OAuth client in UAA must be configured with the authority.
  • For API clients that wish to list router groups with the Routing API, the OAuth client in UAA must be configured with the authority.

For instructions on fetching a token, please refer to the API documentation.

Configure OAuth clients in the cf-release BOSH Manifest
      authorities: routing.routes.write,,
      authorized_grant_type: client_credentials
      secret: route_secret
Configure OAuth clients manually using uaac CLI for UAA
  1. Install the uaac CLI

    gem install cf-uaac
  2. Get the admin client token

    uaac target
    uaac token client get admin # You will need to provide the client_secret, found in your CF manifest.
  3. Create the OAuth client.

    uaac client add routing_api_client \
      --authorities "routing.routes.write,," \
      --authorized_grant_type "client_credentials"
Starting the Server

To run the API server you need to provide RDB configuration for the Postgres or MySQL, a configuration file containing the public UAA jwt key, plus some optional flags.

routing-api \
   -ip \
   -systemDomain \
   -config example_config/example.yml \
   -port 3000 \
   -maxTTL 60
Profiling the Server

The Routing API runs the cf_debug_server, which is a wrapper around the go pprof tool. In order to generate this profile, do the following:

# Establish a SSH tunnel to your server (not necessary if you can connect directly)
ssh -L localhost:8080:[INTERNAL_SERVER_IP]:17002 vcap@[BOSH_DIRECTOR]
# Run the profile tool.
go tool pprof http://localhost:8080/debug/pprof/profile

Note: Debug server should run on loopback interface i.e., for the SSH tunnel to work.

Using the API

The Routing API uses OAuth tokens to authenticate clients. To obtain a token from UAA an OAuth client must first be created for the API client in UAA. For instructions on registering OAuth clients, see Server Configuration.

Using the API with the rtr CLI

A CLI client called rtr has been created for the Routing API that simplifies interactions by abstracting authentication.

Using the API manually

Please refer to the API documentation.

Known issues

  • The routing-api will return a 404 if you attempt to hit the endpoint http://[router host]/routing/v1/routes/ as opposed to http://[router host]/routing/v1/routes




View Source
const (
	UpsertRoute           = "UpsertRoute"
	DeleteRoute           = "Delete"
	ListRoute             = "List"
	EventStreamRoute      = "EventStream"
	ListRouterGroups      = "ListRouterGroups"
	UpdateRouterGroup     = "UpdateRouterGroup"
	CreateRouterGroup     = "CreateRouterGroup"
	DeleteRouterGroup     = "DeleteRouterGroup"
	UpsertTcpRouteMapping = "UpsertTcpRouteMapping"
	DeleteTcpRouteMapping = "DeleteTcpRouteMapping"
	ListTcpRouteMapping   = "ListTcpRouteMapping"
	EventStreamTcpRoute   = "TcpRouteEventStream"


View Source
var RoutesMap = map[string]rata.Route{UpsertRoute: {Path: "/routing/v1/routes", Method: "POST", Name: UpsertRoute},
	DeleteRoute:           {Path: "/routing/v1/routes", Method: "DELETE", Name: DeleteRoute},
	ListRoute:             {Path: "/routing/v1/routes", Method: "GET", Name: ListRoute},
	EventStreamRoute:      {Path: "/routing/v1/events", Method: "GET", Name: EventStreamRoute},
	CreateRouterGroup:     {Path: "/routing/v1/router_groups", Method: "POST", Name: CreateRouterGroup},
	DeleteRouterGroup:     {Path: "/routing/v1/router_groups/:guid", Method: "DELETE", Name: DeleteRouterGroup},
	ListRouterGroups:      {Path: "/routing/v1/router_groups", Method: "GET", Name: ListRouterGroups},
	UpdateRouterGroup:     {Path: "/routing/v1/router_groups/:guid", Method: "PUT", Name: UpdateRouterGroup},
	UpsertTcpRouteMapping: {Path: "/routing/v1/tcp_routes/create", Method: "POST", Name: UpsertTcpRouteMapping},
	DeleteTcpRouteMapping: {Path: "/routing/v1/tcp_routes/delete", Method: "POST", Name: DeleteTcpRouteMapping},
	ListTcpRouteMapping:   {Path: "/routing/v1/tcp_routes", Method: "GET", Name: ListTcpRouteMapping},
	EventStreamTcpRoute:   {Path: "/routing/v1/tcp_routes/events", Method: "GET", Name: EventStreamTcpRoute},


func Routes

func Routes() rata.Routes


type Client

type Client interface {
	UpsertRoutes([]models.Route) error
	Routes() ([]models.Route, error)
	DeleteRoutes([]models.Route) error
	RouterGroups() ([]models.RouterGroup, error)
	RouterGroupWithName(string) (models.RouterGroup, error)
	UpdateRouterGroup(models.RouterGroup) error
	CreateRouterGroup(models.RouterGroup) error
	DeleteRouterGroup(models.RouterGroup) error
	ReservePort(string, string) (int, error)
	UpsertTcpRouteMappings([]models.TcpRouteMapping) error
	DeleteTcpRouteMappings([]models.TcpRouteMapping) error
	TcpRouteMappings() ([]models.TcpRouteMapping, error)
	FilteredTcpRouteMappings([]string) ([]models.TcpRouteMapping, error)

	SubscribeToEvents() (EventSource, error)
	SubscribeToEventsWithMaxRetries(retries uint16) (EventSource, error)
	SubscribeToTcpEvents() (TcpEventSource, error)
	SubscribeToTcpEventsWithMaxRetries(retries uint16) (TcpEventSource, error)

func NewClient

func NewClient(url string, skipTLSVerification bool) Client

func NewClientWithTLSConfig

func NewClientWithTLSConfig(url string, tlsConfig *tls.Config) Client

type Error

type Error struct {
	Type    Type   `json:"name"`
	Message string `json:"message"`

func NewError

func NewError(errType Type, message string) Error

func (Error) Error

func (err Error) Error() string

type Event

type Event struct {
	Route  models.Route
	Action string

type EventSource

type EventSource interface {
	Next() (Event, error)
	Close() error

func NewEventSource

func NewEventSource(raw RawEventSource) EventSource

type RawEventSource

type RawEventSource interface {
	Next() (sse.Event, error)
	Close() error

type TcpEvent

type TcpEvent struct {
	TcpRouteMapping models.TcpRouteMapping
	Action          string

type TcpEventSource

type TcpEventSource interface {
	Next() (TcpEvent, error)
	Close() error

func NewTcpEventSource

func NewTcpEventSource(raw RawEventSource) TcpEventSource

type Type

type Type string
const (
	ResponseError               Type = "ResponseError"
	ResourceNotFoundError       Type = "ResourceNotFoundError"
	ProcessRequestError         Type = "ProcessRequestError"
	RouteInvalidError           Type = "RouteInvalidError"
	RouteServiceUrlInvalidError Type = "RouteServiceUrlInvalidError"
	DBCommunicationError        Type = "DBCommunicationError"
	GuidGenerationError         Type = "GuidGenerationError"
	UnauthorizedError           Type = "UnauthorizedError"
	TcpRouteMappingInvalidError Type = "TcpRouteMappingInvalidError"
	DBConflictError             Type = "DBConflictError"
	PortRangeExhaustedError     Type = "PortRangeExhaustedError"


Path Synopsis
Code generated by counterfeiter.
Code generated by counterfeiter.
Code generated by counterfeiter.
Code generated by counterfeiter.
Code generated by counterfeiter.
Code generated by counterfeiter.
This file was generated by counterfeiter
This file was generated by counterfeiter
Code generated by counterfeiter.
Code generated by counterfeiter.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL