Development
December 23, 2021 ยท View on GitHub
Code generation
This project uses:
protocto generatepb.gofiles fromprotofiles, this is used in the client module onlycsi-proxy-api-gento generate_generated.gofiles, it's used both in the client module and in the server module
Read the Makefile for more details and the descriptions below to understand what targets to call
High Level Overview

Code structure
client- Client module (used by the drivers)api- Client API, versioned and compiled fromapi.protofilesgroups- Client API factory, the drivers will interact with methods of the wanted group/version from this folder, these methods use the structs defined inclient/api
pkg- Server side codeserver.go- Server entry point, invoked by thecsi-proxybinaryserver/<group>/impl/<version>/server_generated.go- First gRPC layer, once the gRPC server receives a request, it'll send it to these GRPC handlers, these handlers will convert a client versioned request e.g. a request fromv1beta2orv1beta3to an internal server representation (seeimpl/types.go) that doesn't have specific information about the version of a client.server/<group>/impl/types.go- All requests regardless of the client version used are converted into the structs declared here, structs of these types are what the server is aware of.server/<group>/impl/types_generated.go- The API exposed by the server API handler, it needs to match requests that may come from any client version.server/<group>/server.go- Server API handlers that implementstypes_generated.goand perform server side validations, once client requests are converted into the internal server structs they go through methods exposed here and invokeos/<group>methods.os/<group>/- The internal server implementation of the csi-proxy API.
Additional notes about the API files:
Additional notes about some autogenerated files:
pkg/server/<group>/impl/<version>/conversion_generated.go- In the First gRPC layer requests may come from different versioned clients, the server works with internal structs that don't have any info about a specific client request, there's the need of conversion functions that remap properties from a client to the internal server structs, this file has functions with autogenerated mappings (overrides can be specified throughconversion.gosee #138)- NOTE: some of the functions may be declared but may not be used, this happens if there's an override in
conversion.gofor that function.
- NOTE: some of the functions may be declared but may not be used, this happens if there's an override in
pkg/server/<group>/api_group_generated.go- Creates server handlers for all the known API versions for the<group>
Making changes to the client module
Some notes about changing code to the client module:
- APIs that were already released should be considered immutable, if the protoc compiler overwrites changes in released APIs we should undo these changes.
When there are changes to the to client module:
- Remove the
vendordirectory - If a
client/api/<group>/api.pb.goneeds to be regenerated, delete it first - If a
client/groups/<group>/<version>/client_generated.goneeds to be regenerated, delete it first - Compile the proto files
make generate-protobuf(there will be a lot of warnings and an error, just make sure that your desired protobuf was generated) - Generate
client_generated.gowithmake generate-csi-proxy-api-gen - Compiling the proto files overwrote the
pb.gofiles for older files, make sure you undo those changes because we consider releasedapi.protoandapi.pb.gofiles immutable.
# for example when I was working on making changes to the v1beta3 volume API
# I had to do the following to restore the changes protoc made to the other APIs
git restore client/api/volume/v1beta{1,2} client/api/{disk,iscsi,system,smb,filesystem}
- Finally after checking that only
client/api/<group>/<version>/api.pb.goandclient/groups/<group>/<version>/client_generated.gowere created/modified, sync these files to the vendor folder withgo mod vendor, verify that the wanted files were generated withgit status
Making changes to the server module
Some notes about making changes to the server module:
- Make sure that the
vendorfolder is up to date with the latest code from the client code. - Always remember to delete a file that was generated otherwise it won't be generated again even if there are changes that should make it autogenerate.
- Autogenerated files shouldn't be edited by hand, instead if there's a special conversion from a specific
client API version to an internal server version use the
conversion.gofile.
When there are changes to the server module:
- Delete the autogenerated files, for example when I was working on
making changes to the volume API I deleted all the
_generated.gofiles.
find pkg/server/volume -name "*_generated.go" | xargs rm
- Generate the
_generated.gofiles withmake generated-csi-proxy-api-gen - Update the unit tests in
pkg/server/<group>/server_test.go - Update the integration tests in
integrationtests/
Bumping versions
- Copy all the non-generated client files from the desired groups e.g. from
v1beta2tov1beta3and run the compiler (see #making changes to the client module), remember not to overwrite old API files! - Copy server API handlers for the desired group e.g.
pkg/server/<group>/impl/<version>/conversion.go, remember to delete the auto generated files first!
The steps above are implemented in scripts/bump-version.sh
If there are any non-backward compatible changes (for example renaming a parameter or a method)
- Make sure that
types.goreflects what we should know of the internal server structs - Remap old parameters in previous API versions e.g. let's say that we make a remap in
v1beta3then we need to updatedv1alpha1,v1beta1, etc. using theconversion.gofile. (see #138) - Update
pkg/<group>/server.goif there are new methods, the old methods should forward the request (see #138)
Also make sure you copy and execute the corresponding API integration test in integrationtests/
Running E2E tests
There are a few presubmit tests that run in Github Actions, E2E tests need to run in a Windows VM with Hyper-V enabled, to run the E2E tests in Google Cloud follow this workflow:
- Modify scripts/e2e-runner.ps1 to use your repo/branch
- Create a windows VM for csi-proxy with scripts/e2e-tests.sh, after the instance is initialized it'll build csi-proxy and attempt to run the E2E tests
During development we need to iterate faster, I follow this workflow during development:
- cross compile csi-prox.exe, copy it to the Windows VM and restart csi-proxy
./scripts/sync-csi-proxy.sh