Skip to content

Commit a2bd414

Browse files
Merge pull request #5415 from yuwenma/unify-api
docs: unify api, mapper and fuzzer
2 parents 122ddf8 + da3525b commit a2bd414

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed

docs/ai/unify-api-mapper-fuzzer.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# How to Unify API Mappers and Fuzzers for Existing Resources
2+
3+
This guide provides a step-by-step process for refactoring and unifying the API, mapper, and fuzzer for existing resources. The goal is to leverage the auto-generation tools as much as possible, reduce manual code, and ensure consistency across different API versions.
4+
5+
## 1. Start with `generate.sh`
6+
7+
The unification process begins with the `generate.sh` script located in the `apis/<service>/<version>` directory (e.g., `apis/dataproc/v1alpha1/`). This script is the source of truth for the auto-generation process.
8+
9+
### Verify and Correct `generate.sh`
10+
11+
1. **Check for Existence**: Ensure a `generate.sh` script exists for each version of the service you are unifying (e.g., `v1alpha1`, `v1beta1`). If it doesn't exist, create one using a known good example like `apis/bigquerybiglake/v1alpha1/generate.sh` as a template.
12+
13+
2. **Verify Resource List**: Open the `generate.sh` script and check the `--resource` flags in the `go run . generate-types` command. This list should accurately reflect all the resources defined within that API version directory. Add or remove `--resource` flags as necessary.
14+
15+
3. **Check Output Directory**: Ensure the final `go run ... goimports` command is writing to the correct controller directory, which should be `pkg/controller/direct/<service>/`.
16+
17+
A corrected `generate.sh` for a `v1alpha1` service might look like this:
18+
19+
```bash
20+
#!/bin/bash
21+
# ... (license header)
22+
set -o errexit
23+
set -o nounset
24+
set -o pipefail
25+
26+
REPO_ROOT="$(git rev-parse --show-toplevel)"
27+
cd ${REPO_ROOT}/dev/tools/controllerbuilder
28+
29+
go run . generate-types \
30+
--service google.cloud.myservice.v1 \
31+
--api-version "myservice.cnrm.cloud.google.com/v1alpha1" \
32+
--resource MyResourceOne:ResourceOne \
33+
--resource MyResourceTwo:ResourceTwo
34+
35+
go run . generate-mapper \
36+
--service google.cloud.myservice.v1 \
37+
--api-version "myservice.cnrm.cloud.google.com/v1alpha1"
38+
39+
cd ${REPO_ROOT}
40+
dev/tasks/generate-crds
41+
42+
go run -mod=readonly golang.org/x/tools/cmd/goimports@latest -w pkg/controller/direct/myservice/
43+
```
44+
45+
## 2. Rely on Auto-Generated Mappers
46+
47+
The primary goal of unification is to remove as much manual mapping logic as possible and rely on the code generated by `generate-mapper`.
48+
49+
1. **Run `generate.sh`**: Execute the script for each API version you are unifying. This will create or update the `types.mapper.go` file in the controller directory (`pkg/controller/direct/<service>/`).
50+
51+
2. **Identify Manual Mappers**: Look for manually written mapper functions in files like `<resource>_mapper.go`. These are the functions you want to replace.
52+
53+
3. **Replace with Generated Functions**: Update your controller and fuzzer code to call the new, auto-generated functions from `types.mapper.go` instead of the old manual ones.
54+
55+
4. **Delete Old Code**: Once all references to the manual mapper functions have been removed, you can delete the `<resource>_mapper.go` file or remove the now-unused functions from it.
56+
57+
## 3. Handling Multi-Version Services
58+
59+
When a service has multiple API versions (e.g., `v1alpha1` and `v1beta1`), the mapper needs to handle potential differences in the resource schemas.
60+
61+
### Use the `--multiversion` Flag
62+
63+
For the newer version of the API (e.g., `v1beta1`), add the `--multiversion` flag to the `generate-mapper` command in its `generate.sh` script.
64+
65+
Example for `apis/myservice/v1beta1/generate.sh`:
66+
```bash
67+
# ...
68+
go run . generate-mapper \
69+
--multiversion \
70+
--service google.cloud.myservice.v1 \
71+
--api-version "myservice.cnrm.cloud.google.com/v1beta1"
72+
# ...
73+
```
74+
75+
When this flag is used, the generator will create version-specific mapping functions to avoid conflicts. The function names will have the version injected into their name, for example:
76+
* `MyResourceSpec_v1beta1_ToProto(...)`
77+
* `MyResourceSpec_v1alpha1_FromProto(...)`
78+
79+
**Note**: If the `--multiversion` flag is *not* used (typically for services with only one version), the generated function names will **not** have a version in them (e.g., `MyResourceSpec_ToProto(...)`).
80+
81+
## 4. Update Fuzzer and Controller Code
82+
83+
After re-generating the mappers, you must update your fuzzer and controller files to use the correct function names.
84+
85+
1. **Ensure Fuzzer File Exists**: Ensure each CRD being unified has a corresponding `_fuzzer.go` file. If one does not exist, create it by copying from a similar resource and adapting it.
86+
87+
2. **Update `*_fuzzer.go`**: Go to `pkg/controller/direct/<service>/<resource>_fuzzer.go` and update the `fuzztesting.NewKRMTypedFuzzer` call to use the new generated function names.
88+
89+
* If you used `--multiversion`, the names will be version-specific.
90+
* If you did not use `--multiversion`, the names will be generic.
91+
92+
**Example with `--multiversion`:**
93+
```go
94+
// For the v1beta1 fuzzer
95+
f := fuzztesting.NewKRMTypedFuzzer(&pb.MyResource{},
96+
MyResourceSpec_v1beta1_FromProto, MyResourceSpec_v1beta1_ToProto,
97+
MyResourceObservedState_v1beta1_FromProto, MyResourceObservedState_v1beta1_ToProto,
98+
)
99+
```
100+
101+
**Example without `--multiversion`:**
102+
```go
103+
f := fuzztesting.NewKRMTypedFuzzer(&pb.MyResource{},
104+
MyResourceSpec_FromProto, MyResourceSpec_ToProto,
105+
MyResourceObservedState_FromProto, MyResourceObservedState_ToProto,
106+
)
107+
```
108+
109+
3. **Update `*_controller.go`**: Search for any remaining usages of the old function names in your controller logic (`pkg/controller/direct/<service>/<resource>_controller.go`) and update them to point to the new generated functions.
110+
111+
By following these steps, you can systematically unify the API definitions, mappers, and fuzzers for existing resources, leading to a more maintainable and consistent codebase.

0 commit comments

Comments
 (0)