Skip to content

Commit 2cdc687

Browse files
authored
Merge pull request #743 from sap-contributions/rfc-route-features
rfc: generic per-route features
2 parents 669dc3a + 98f3092 commit 2cdc687

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# Meta
2+
[meta]: #meta
3+
- Name: Generic Per-Route Features
4+
- Start Date: 2024-01-08
5+
- Author(s): @maxmoehl, @domdom82
6+
- Status: Draft <!-- Acceptable values: Draft, Approved, On Hold, Superseded -->
7+
- RFC Pull Request: (fill in with PR link after you submit it)
8+
9+
## Summary
10+
11+
## Problem
12+
13+
Implementing per-route features in Cloud Foundry is a tedious process because it requires changes to
14+
multiple components in multiple working groups. Most components will only need to be made aware of
15+
new fields without adding any significant logic but the overhead of making the change still exists.
16+
17+
On the other side are the components that actually need to be aware of the change. Mostly the
18+
routing components (gorouter, maybe route-emitter / -registrar), the API (cloud controller) and
19+
UIs (CLI).
20+
21+
## Proposal
22+
23+
To reduce the overall overhead of implementing new per-route features we propose to add a generic
24+
key-value map to the definition of a route across all components. All components handling the map
25+
SHOULD ignore the contents of the map except gorouter, cloud controller and cf CLI which MUST handle
26+
the map and its values accordingly. Other components MAY limit the size of the map or size of keys /
27+
values for technical reasons.
28+
29+
The following constraints apply (types are as specified in [RFC 8259](https://rfc-editor.org/rfc/rfc8259)):
30+
* The map MUST be representable as an object.
31+
* The map MUST only use strings as keys.
32+
* The map MUST only use numbers, strings and the literal values `true` and `false` as values.
33+
34+
### Required Changes
35+
36+
#### CLI
37+
38+
There SHOULD be a single flag which supports generic key-value pairs for the `map-route`
39+
sub-command. The flag should accept a JSON structure like the `-c` argument of `cf create-service`.
40+
41+
#### Cloud Controller
42+
43+
The API MUST specify and implement a new field to carry the map inside the route object. The
44+
API MUST implement per-field validations as features of the map are specified. The route MUST be
45+
rejected with an appropriate error message if the provided map is invalid and MUST be passed on
46+
as-is otherwise. The API also MUST store the map as a generic key-value map to ensure changes to the
47+
map do not require a change to the database schema.
48+
49+
Support for a generic map MUST be added to the manifest. The updated routes section in a manifest
50+
MAY look like this:
51+
52+
```yml
53+
version: 1
54+
applications:
55+
- name: test
56+
routes:
57+
- route: example.com
58+
options:
59+
loadbalancing-algorithm: round-robin
60+
connection-limit: 15
61+
session-cookie: FOOBAR
62+
trim-path: true
63+
- route: www.example.com/foo
64+
protocol: http2
65+
- route: tcp-example.com:1234
66+
```
67+
68+
The new fields MUST be supported by the already existing endpoints to create and update and get
69+
routes:
70+
* [`POST /v3/routes`](https://v3-apidocs.cloudfoundry.org/version/3.159.0/index.html#create-a-route)
71+
* [`GET /v3/routes/:guid`](https://v3-apidocs.cloudfoundry.org/version/3.159.0/index.html#get-a-route)
72+
* [`GET /v3/routes`](https://v3-apidocs.cloudfoundry.org/version/3.159.0/index.html#list-routes)
73+
* [`GET /v3/apps/:guid/routes`](https://v3-apidocs.cloudfoundry.org/version/3.159.0/index.html#list-routes-for-an-app)
74+
* [`PATCH /v3/routes/:guid`](https://v3-apidocs.cloudfoundry.org/version/3.159.0/index.html#update-a-route)
75+
76+
The overall goal MUST be to implement the new fields in a way that fits in with the current
77+
behavior of the cloud controller API. It is up to the maintainers / implementers to decide on the
78+
exact behavior.
79+
80+
Implementation pointers:
81+
* Add a new field to the [route model](https://github.com/cloudfoundry/cloud_controller_ng/blob/main/app/models/runtime/route.rb).
82+
* Add validation to the [route validator](https://github.com/cloudfoundry/cloud_controller_ng/blob/e719d017ea4625397a97c2c14352ebdee66febe9/lib/cloud_controller/route_validator.rb#L2).
83+
* Use a mechanism similar to the [droplet](https://github.com/cloudfoundry/cloud_controller_ng/blob/e719d017ea4625397a97c2c14352ebdee66febe9/app/models/runtime/droplet_model.rb#L47-L48) to store the encoded map.
84+
85+
#### BBS, Rep, Executor, Route-Emitter
86+
87+
The diego components MUST add support for the new field specified by the API and forward the
88+
contents as-is without modification or, if the field exceeds technical limitations, MUST raise an
89+
error.
90+
91+
### Route-Registrar
92+
93+
Route-registrar MUST offer the new features in its config as they are added to the other components.
94+
95+
#### Gorouter
96+
97+
Gorouter MUST accept the new field and parse its contents. If the map cannot be parsed it MUST be
98+
ignored. If individual key-value pairs are invalid those MUST be ignored and other key-value pairs
99+
MUST still be parsed and acted upon. For any option which could not be parsed gorouter MUST NOT
100+
fail but fall back to the value provided in the gorouter config. When encountering an invalid option
101+
gorouter MUST log the error at least once, the log SHOULD indicate what it tried to parse, why it
102+
failed and which value will come into effect.
103+
104+
It MAY be decided to implement one feature as part of this RFC which would be implemented together
105+
with the generic logic for supporting the new map.
106+
107+
As new features are specified they MUST be implemented in gorouter.
108+
109+
Example `router.register` NATS message containing additional options (field names and values are
110+
not final):
111+
112+
```json
113+
{
114+
"host": "127.0.0.1",
115+
"port": 4567,
116+
"tls_port": 1234,
117+
"protocol": "http1",
118+
"uris": [
119+
"my_first_url.localhost.routing.cf-app.com",
120+
"my_second_url.localhost.routing.cf-app.com/some-path"
121+
],
122+
"tags": {
123+
"another_key": "another_value",
124+
"some_key": "some_value"
125+
},
126+
"options": {
127+
"lb-algo": "least-conn",
128+
"conn-limit": 100,
129+
"cookie": "my-session-cookie",
130+
"trim-path": true
131+
},
132+
"app": "some_app_guid",
133+
"stale_threshold_in_seconds": 120,
134+
"private_instance_id": "some_app_instance_id",
135+
"isolation_segment": "some_iso_seg_name",
136+
"server_cert_domain_san": "some_subject_alternative_name"
137+
}
138+
```
139+
140+
### Specifying Features
141+
142+
It's the responsibility of the App Runtime Platform Working Group (ARP-WG) to specify new features
143+
based on what is specified in this RFC. When a new feature is proposed the ARP-WG uses the process
144+
it would use for any new feature to decide whether and how it should be implemented. It MAY involve
145+
other working groups in the process.
146+
147+
### Features Which Could be Implemented
148+
149+
So far we have collected a list of features which would benefit from a more flexible approach to
150+
per-route features:
151+
152+
- Custom Load-Balancing Algorithm
153+
- Custom Connection Limits
154+
- Custom session cookie name (currently set on platform level, mostly to `JSESSIONID`)
155+
- Option to trim path mapping on request (i.e. an app mapped to `/some-path/` receiving a request
156+
`GET /some-path/books` will see the request as `GET /books` if the `trim-path` option is set,
157+
instead of the full path)
158+
159+
All of these options are already (or could easily be made) configurable for the entire CF
160+
installation. Changing them will almost certainly break existing scenarios which is why we are
161+
looking for a cheap way to gradually allow for more configuration per route.

0 commit comments

Comments
 (0)