-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Updates to Custom kind for new schema format #9
Conversation
…e a schema format when being used to generate a CRD.
kindcat_custom.cue
Outdated
// TODO: should this just be pluginID? Is there a world where an app and plugin may not share the same ID? | ||
// The practical reason to have it different is to allow the appID to be shorter than the pluginID as the group | ||
// is generated from the appID, and <kind name>+<group> cannot exceed 63 characters in kubernetes. | ||
appID: =~"^([a-z][a-z0-9-]{0,61}[a-z0-9])$" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussed with @IfSentient a nice compromise might be to default to use the plugin id, but in case that results in a longer group than 63 characters we could allow an override (appId or group). This will allow plugin authors to easily determine the rules, if needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated the PR so that now there is a plugin
trait with an id
field (there is a TODO on whether this should be a trait, or if pluginID
should just be a top-level field in the kind). The crd
trait has an optional groupOverride
field which can be used to override using plugin.id
as the group name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. Yeah let's discuss plugin trait vs part of kind. Since common and composable kinds refer to plugins maybe make most sense to include plugin id as a field?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've done a weird temporary compromise where pluginID
is a top-level field now, but the plugin
trait still exists, and plugin.id
is set to the pluginID
field. Not sure if we want the trait to continue to exist, or if we want to revert that and have the ID live solely in the trait. I'm somewhat unopinionated on this, because I'm not sure if we're going to ever need more plugin info in the kind--if we do, we'll want to keep the trait. If there's both the trait and pluginID fields, it seems a bit confusing to use.
…ded plugin trait for specifing plugin ID which nominally determines CRD group unless crd.groupOverride is provided.
…ata in Custom.lineage.joinSchema, as thema codegen fails for externally-defined types. Update CustomProperties in props.go to reflect new traits added to the Custom kind. Add the method ToDef in load.go, which works similarly to ToKindProps, except it returns a def that includes the props _and_ the unified CUE value, allowing changes to the lineage to be part of the CUE value when passed to Bind<X>.
kindcat_custom.cue
Outdated
joinSchema: { | ||
// metadata contains embedded CommonMetadata and can be extended with custom string fields | ||
// TODO: use CommonMetadata instead of redfining here; currently needs to be defined here | ||
// without extenal reference as using the CommonMetadata reference breaks thema codegen. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What breaks, exactly?
We should be able to specifically force dereferencing of such a type with a NameFunc
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got a nasty nil pointer panic from inside of cue's openapi package, I didn't look too far into it, but it appears that it's a problem when there's an external ref. For now, it was simpler to not dig into that and unify the CommonMetadata model into the joinSchema
once that's been worked out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tried adding a NameFunc
, and it panics before I see any calls to the NameFunc. I'll open an issue for this in thema and look into it after dealing with this PR (as I have a tighter timeline with getting this into kindsys).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SGTM on timing - and huh! well, i'm poking at that code right now as part of lineage flattening, i'll keep an eye out for panics
kindcat_custom.cue
Outdated
// If the crd trait is defined, the schemas in the lineage must follow the format: | ||
// { | ||
// "metadata": CommonMetadata & {...string} | ||
// "spec": {...} | ||
// "status": {...} | ||
// } | ||
if S.crd != _|_ { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a couple ways we might structure the CUE, depending on whether we want to make using the CRD trait a decision that's made in kindsys for an entire kind category, or left up to individual kind authors.
Regardless, i'd suggest that for introspectability purposes, it's worth turning this comparison to bottom into a simple boolean in a top-level field within the kind, such as isCRD: crd != _|_
, then referencing that field here. The fewer comparisons to bottom the better, and having an explicit field will make a kind trivially introspectable either on Go structs or when exported to JSON.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I've now addressed all this:
- created
isCRD
, which is equal toS.crd == _|_
- moved the definition of
metadata
/spec
/status
out of the lineage and into a kindsys top-level_crdSchema
type (tested--codegen still works fine with this) - moved the
isCRD
check out of the lineage to the root of the kind, if true, it applieslineage: joinSchema: _crdSchema
Let me know if I'm missing something here, or if I should do anything in an alternate way.
… field in joinSchema.
…which is used in if is true.
…def. This cleans up the generated lineage.
kindcat_custom.cue
Outdated
@@ -10,6 +98,79 @@ package kindsys | |||
Custom: S={ | |||
_sharedKind | |||
|
|||
lineage: { name: S.machineName } | |||
// pluginID is the unique identifier of the plugin which owns this Custom kind | |||
pluginID: =~"^([a-z][a-z0-9-]*[a-z0-9])$" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thoughts on whether this should be a top-level field, or live only in the plugin
trait (or even if the plugin
trait should disappear, and only the pluginID
reference should remain)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think we need to firm up the notion of a trait to really decide.
For the CUE part of it, i've been imagining traits as discrete sets of fields that can be composed into kind category definitions. Those sets - which in this PR i would imagine include both the top-level props and the joinschema - would then be imported into the github.com/grafana/kindsys
CUE package and composed into the kind category definitions in as simple a manner possible. i'm thinking of that as valuable because as a reader/maintainer of the kind cat definitions, i want to be able to easily see and reason about how the trait is composed across kind categories, basically independent of what's in the trait itself.
Given the above, and because we actually need plugins to be a container/wrapper around kind definitions, they fall at least partly outside my current operating concept of "trait". Happy to change my mind here if we find something that feels right, though!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense to me, I think we can ditch the plugin
trait in favor of just having the pluginID
field as the top-level prop for Custom.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@IfSentient this is nit-picking but I would prefer if the kind system weren't aware of specific entities owning kinds. IMHO this is in agreement to sam's point about plugins (or apps) being containers of kind definitions.
To that end I suggest renaming pluginID to something more general, like a kindGroup or simply group (similar to CRD groups basically).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on discussions/input yesterday and the need for grouping all kinds (core, custom, composable) to fit in a schema registry I think group
or similar makes more sense as well. Currently working on a doc that hopefully should propose how all of this are supposed to fit together in regards to a schema registry and plugins.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't mind leaving it as this either for now. We can change it later if needed given it happens soon (before too many depends on this)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated it to be group
in the top-level, just so we don't need to change as much later, and it doesn't explicitly reference plugins within the kind itself.
cc @AgnesToulet |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good from my side. I left a nitpicky comment about the naming of the pluginID field but I don't mind leaving it as it is.
kindcat_custom.cue
Outdated
if S.crd.groupOverride != _|_ { | ||
strings.ToLower(S.crd.groupOverride) + ".apps.grafana.com", | ||
} | ||
strings.ToLower(strings.Replace(S.pluginID, "-","_",-1)) + ".apps.grafana.com" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As an open comment here as well: <kind>.<pluginID/custom override>.apps.grafana.com
--do we want this to be apps.grafana.com
, ext.grafana.com
, plugins.grafana.com
? I think it makes sense to group all custom kinds under one <x>.grafana.com
, as that way they can't overlap with core kinds (which are <kind>.grafana.com
), but what should be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ext.grafana.com
works for me.
Side note – IMHO the core kinds should also be grouped under a subdomain, e.g. core.grafana.com
.
kindcat_custom.cue
Outdated
// This field could be inlined into `group`, but is separate for clarity. | ||
_computedGroups: [ | ||
if S.crd.groupOverride != _|_ { | ||
strings.ToLower(S.crd.groupOverride) + ".apps.grafana.com", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is "apps" too specific?
Will there be cases where Kinds are defined in the scope of other "extensions". Datasources, Apps, Plugins generally?
Perhaps "ext.grafana.com"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm in favor of ext.grafana.com
. Doesn't take up too much of the allotted 63 characters for the full GroupKind, and is clear enough about what it is (an extension vs something in core).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ext.grafana.com
works for me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now uses <group>.ext.grafana.com
(where group is typically the plugin ID). groupOverride
can be set, which overrides the entire crd.group
property, so there is a way to make the group something else if the need arises.
…ana.com', remove openness (...) wherever possible.
…efore 'ext.grafana.com', as 'group' is no longer explicitly tied to plugin ID.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Since this is scoped to only custom kinds, it doesn't force our hand on integrating with core kinds yet. That'll be a key follow-up once this is merged
kindcat_custom.cue
Outdated
@@ -130,19 +140,19 @@ Custom: S={ | |||
// This field could be inlined into `group`, but is separate for clarity. | |||
_computedGroups: [ | |||
if S.crd.groupOverride != _|_ { | |||
strings.ToLower(S.crd.groupOverride) + ".apps.grafana.com", | |||
strings.ToLower(S.crd.groupOverride) + ".ext.grafana.com", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@IfSentient as per our discussion earlier this week, let's make sure there's an escape hatch of overriding also the group suffix, in case there's no viable migration path for SLO / CLE apps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, most recent commit should have groupOverride
overriding the whole group string.
Initial work on the Custom kind to enforce the new schema format, specifically when the kind as a
crd
trait.If a Custom kind has the
crd
trait, then the lineage's schema enforces a specific format using joinSchema:As part of adding the optional
crd
trait, theappID
field was added to allow for generating the group (see TODO note about this).Also as a part of this PR, a
codegen
trait was added, allowing app/plugin development tooling to know what kind of code to generate from this kind.