protobuf changes in preparation for buf breaking#26792
Conversation
138b92c to
97df3f1
Compare
|
This touches every test that refers to |
codingllama
left a comment
There was a problem hiding this comment.
Thanks for tackling this, your effort is very much appreciated.
| // RoleV6 represents role resource specification | ||
| message RoleV6 { | ||
| // RoleImpl represents role resource specification | ||
| message RoleImpl { |
There was a problem hiding this comment.
We talked about this before, but I'm not a fan of this rename. There's nothing "Impl" about the protos, they are the definition of the role. This introduces a poor name to our API surface and preserves less-relevant impl details.
I would rather:
- Leave names as-is (RoleVx, RoleSpecVx). It's not great but at least it's in keeping with other types.
- Rename Role(interface)->RoleI, RoleVx->Role, RoleSpecVx->RoleSpec. Better naming overall, and a better pattern for other types to follow.
There was a problem hiding this comment.
The issue with the name with the V in it is that we should pick a name that works across teleport versions even if newer versions support a higher resource version; case in point, if we left RoleV6 in place we'd be looking at bumping the struct name to RoleV6 even in teleport 11, which only supports role resources between v3 and v5.
Calling it Role with an additional rename of the Role to RoleI works and I like it, but what are we going to call the next incompatible protobuf message for RoleI? Role2? And if we're never going to have another implementation of RoleI (and I suspect we might not), why even have an interface for it?
There was a problem hiding this comment.
Should we be versioning types instead of versioning the resources within it, i.e. typesv1.Role vs typesv2.Role?
There was a problem hiding this comment.
I don't think that works, we actively want to support multiple resource versions with a single protobuf type. Also, versioning "all the types" is kind of counterproductive, you'd need to copy everything when you need a new version of a single resource.
Maybe each group of related messages should be in its own package, probably together with a dedicated service, but that doesn't help the fact that we also need to be able to refer and unmarshal any of those from storage as necessary.
There was a problem hiding this comment.
The issue with the name with the V in it is that we should pick a name that works across teleport versions even if newer versions support a higher resource version; case in point, if we left RoleV6 in place we'd be looking at bumping the struct name to RoleV6 even in teleport 11, which only supports role resources between v3 and v5.
Keeping the resource "version numbers" stable, starting from v13, wouldn't be a bad way to "fix" our chronic habit of breaking name changes. We'd have to live with multiple role versions while v12 and v11 are active, but over time it stabilizes.
Calling it Role with an additional rename of the Role to RoleI works and I like it, but what are we going to call the next incompatible protobuf message for RoleI? Role2? And if we're never going to have another implementation of RoleI (and I suspect we might not), why even have an interface for it?
The idea here is to stop with the needless renames, so we wouldn't have new Role/RoleSpec/RoleI unless it is a true breaking change.
As for the purpose of the interfaces, let's not get on that in this thread. :)
Should we be versioning types instead of versioning the resources within it, i.e. typesv1.Role vs typesv2.Role?
My 2c is no - bumping the package version is akin to saying everything changed, or enough changed in the API that we are calling it a new major entirely. The "ideal" proto API versioning scheme is that you release v1, do incremental, backwards-compatible changes and never ever release v2 (think of how much trouble we get with breaking changes in our dependencies, mostly for no benefit to us).
The proper way to evolve protos is to keep the name do backwards-compatible changes. Fields like api_version exist to do what we do by renaming the protos (that would be a better way to go about this, btw). A message name change should only happen if the representations are truly incompatible; eg, Role and Role2 are radically different, and that's why the name change would be necessary.
There was a problem hiding this comment.
Either way, I was really hoping for this PR to only deal with naming changes that are guaranteed to not affect anything functionally, so maybe that's for a future step we can deal with later, especially since we're gonna have a few more safeguards on not breaking the protobuf wire compat in place.
There was a problem hiding this comment.
As a side note, I'd say that this is one of the main benefits of the change detector: making it painfully clear what our bad habits are.
97df3f1 to
2ebab3d
Compare
This PR, together with the PRs on v11, v12 and v13:
buf breakingconfiguration toWIRE_JSON(which, sadly, won't prevent us from breakingencoding/jsonencoding as specified bygogoproto.jsontag, but that doesn't seem to be happening anyway)proto.WatchKindintotypes.WatchKind)Contributes to #26688
With this PR it should be possible to get a clean
buf breakingbetweenmasterand the release branches, with the exception of errors pertaining to field 17 ofUserCertsRequestin v11'sauthservice.proto(as described in #24817) and to errors pertaining to the renaming ofRoleV5toRoleV6between v11 and later versions.How to address backwards compatibility checking in v11 (maybe ignoring those specific errors, and accepting the lack of backwards compatibility check for the
RoleV5message?), and how to handle future resource versioning in general is out of scope for these PRs.