Skip to content

Commit 98f4d40

Browse files
committed
Update devguide with API documentation guideline
1 parent 82e6d27 commit 98f4d40

File tree

1 file changed

+139
-1
lines changed

1 file changed

+139
-1
lines changed

site-src/contributing/devguide.md

Lines changed: 139 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,4 +169,142 @@ directory at the `tools` directory.
169169
To add a new tool, use `go get -tool -modfile tools/go.mod the.tool.repo/toolname@version`
170170
and tidy the specific module with `go mod tidy -modfile=tools/go.mod`.
171171

172-
To execute the new tool, use `go tool -modfile=tools/go.mod toolname`.
172+
To execute the new tool, use `go tool -modfile=tools/go.mod toolname`.
173+
174+
## API Documentation
175+
176+
When writing API documentation (the `godoc` for API fields and structures) it should be done
177+
in a meaningful and concise way, where information are provided for the different
178+
Gateway API personas (Ian, Chihiro and Ana) without leaking implementation details.
179+
180+
The implementation details are still important for a Gateway API implementation
181+
developer, and they should still be provided but without being exposed on the
182+
CRD generation, that can end leaking to users on a diverse set of ways, like
183+
on Gateway API documentation website, or via `kubectl explain`.
184+
185+
Additionally, it is worth noticing that API documentation reflects on the CRD generation
186+
size, which impacts directly on resource consumption like a maximum Kubernetes resource size
187+
(which is limited by etcd maximum value size) and avoiding problems with `last-applied-configuration`
188+
annotation, when doing a client-side apply.
189+
190+
There are two kind of API documentations:
191+
192+
* User facing - MUST define how a user should be consuming an API and its field, on a concise way.
193+
* Developer facing - MUST define how a controller should implement an API and its fields.
194+
195+
### User facing Documentation
196+
197+
The API documentation, when meaningful, helps users of it on doing proper configuration
198+
in a way that Gateway API controllers react and configure the proxies the right way.
199+
200+
A good API documentation should cover:
201+
* What is the main feature of the API and Field - Eg.: "`Foo` allows configuring how a
202+
a header should be forwarded to backends"
203+
* What is the support level of the field - Eg.: "Support: Core/Extended/Implementation Specific"
204+
* Caveats of that field - Eg.: "Setting `Foo` field can have conflicts with `Bar` field, and in this
205+
case it will be shown as a Condition". (we don't need to cover all the conditions).
206+
207+
In a simple way, a user reading the field documentation should understand, on one or two
208+
phrases what happens when the field is configured, what can be configured and what are
209+
the impacts of that field
210+
211+
When adding a documentation, it is very important to remove your "Developer hat"
212+
and put yourself on a user that is trying to solve a problem: Does setting a field
213+
solves my needs? How can I use it?
214+
215+
On an implementation, a user facing documentation belongs to the field documentation. Taking
216+
`Listeners`, one of the most complex fields as an example:
217+
218+
```golang
219+
// Listeners define logical endpoints that are bound on this Gateway's addresses.
220+
// At least one Listener MUST be specified. When setting a Listener, conflicts can
221+
// happen depending on its configuration like protocol, hostname and port, and in
222+
// this case a status condition will be added representing what was the conflict.
223+
//
224+
// The definition of a Listener protocol implies what kind of Route can be attached
225+
// to it
226+
Listeners []Listener `json:"listeners"`
227+
```
228+
229+
We don't specify what are the Protocol types (saving this to the `Protocol` field),
230+
what a hostname means, when a TLS configuration is required. All of these information
231+
belongs to each field, so when a user does something like `kubectl explain gateway.spec.listeners`
232+
they will also get the information of each field.
233+
234+
### Developer facing documentation
235+
236+
Developer facing documentation helps during implementations to define the expected
237+
behavior of it, and should answer questions like:
238+
239+
* How that field should be reconciled?
240+
* What conditions should be set during the reconciliation?
241+
* What should be validated during the reconciliation of that field?
242+
243+
In this case, as the API documentation serves as a guide for implementors on how
244+
their implementations should behave, it is very important to be as much verbose as
245+
required to avoid any ambiguity. These information are used also to define expected
246+
conformance behavior, and can even point to existing GEPs so a developer looking
247+
at it can know where to look for more references on what and why are those the expected
248+
behavior of this field.
249+
250+
Still taking the `Listeners` field as an example, it does good definitions of situations
251+
like:
252+
253+
* Two listeners have different protocols but the same hostname. Should this be a conflict?
254+
* A listener of type `XXX` sets the field `TLS`. Is this a problem? How to expose this to
255+
the user?
256+
257+
Because these information don't matter for a user, they should be hidden from the CRD/OpenAPI
258+
generation and also from the website API Reference.
259+
260+
This can be achieved putting these information between the tags
261+
`<gateway:util:excludeFromCRD></gateway:util:excludeFromCRD>` and preferably
262+
contain a callout that those are a Note for implementors:
263+
264+
```golang
265+
// Mode defines the TLS behavior for the TLS session initiated by the client.
266+
// There are two possible modes:
267+
//
268+
// - Terminate: The TLS session between the downstream client and the
269+
// Gateway is terminated at the Gateway. This mode requires certificates
270+
// to be specified in some way, such as populating the certificateRefs
271+
// field.
272+
// - Passthrough: The TLS session is NOT terminated by the Gateway. This
273+
// implies that the Gateway can't decipher the TLS stream except for
274+
// the ClientHello message of the TLS protocol. The certificateRefs field
275+
// is ignored in this mode.
276+
//
277+
// Support: Core
278+
//
279+
// <gateway:util:excludeFromCRD>
280+
// Notes for implementors:
281+
//
282+
// Setting TLSModeType to Passthrough is only supported on Listeners that are of
283+
// type HTTP, HTTPS and TLS. In case a user sets a different type, the implementation
284+
// MUST set a condition XXX with value XXX and a message specifying why the condition
285+
// happened.
286+
// </gateway:util:excludeFromCRD>
287+
Mode *TLSModeType `json:"mode,omitempty"`
288+
```
289+
290+
### Advices when writing the API documentation
291+
As an advice, the person writing the documentation should always being questioning:
292+
293+
**As a user**:
294+
* Does the documentation provide meaningful information and removes any doubt
295+
about what will happen when setting this field?
296+
* Does the documentation provide information about where should I look if something
297+
goes wrong?
298+
* If I do `kubectl explain` or look into the API Reference, do I have enough
299+
information to achieve my goals without being buried with information I don't care?
300+
301+
**As a developer/implementor**:
302+
* Does the documentation provide enough information for another developer on
303+
how they should implement their controller?
304+
* Does the documentation provide enough information on what other fields/resources
305+
should be verified to provide the right behavior?
306+
* Does the documentation provide enough information on how I should signal to the
307+
users what went right/wrong and how to fix it?
308+
309+
It is important to exercise changing the personas for which you are writing the
310+
documentation.

0 commit comments

Comments
 (0)