Europa: The Great Compromise of December 16, 2021. (spec).#1234
Europa: The Great Compromise of December 16, 2021. (spec).#1234shykes merged 1 commit intodagger:mainfrom shykes:europa-hidden-fields-plan-b
Conversation
|
I do agree things as they are are a bit confusing, however I disagree on why it's confusing and how to fix it :) I realize Discord isn't the best medium to share context, so let me try to here. Those fields only matter to people writing Engine code / advanced users, and IMHO if explained/organized better, it makes a lot of sense. There's two things:
I agree it's currently not in the best of shapes from a simplicity point of view, and I have a few suggestions to make it better:
On consistency:
Following this logic -- shouldn't we add a marker to Where does it stop? Should we have an On inputs:
I agree the inlined However, I recommend doing something along these lines: #Plan: {
input: secrets: [name=string]: #_ClientReadSecret | _#ClientExecSecret
}
// Read secret from a file ON THE CLIENT MACHINE
_#ClientReadSecret: {
_task: "ClientReadSecret"
path: string
// Reference to the secret contents
contents: #Secret
}
_#ClientExecSecret: {
_task: "ClientExecSecret"
// Execute a command ON THE CLIENT MACHINE and read secret from standard output
command: [string, ...string] | string
// Execute command in an interactive terminal
// for example to prompt for a passphrase
interactive: true | *false
// Reference to the secret contents
contents: #Secret
}
To me this feels pretty consistent, I believe advanced users would have no trouble understanding what's going on. |
|
BTW, as you can tell I'm pretty excited about this model because IMHO it makes contributing/developing the Engine dead simple. Want to add support for
No other changes to the entire Go code base. No need to add a concept of outputs, that's entirely in CUE and the core task model is enough. Some day those could very well be external plugins. Since we're using |
This makes sense to me. Clarifying the terminology of “core types” vs “tasks” is helpful.
Yes I agree, if we ignore for a second the issues with hidden fields, adding Now, incorporating the hidden fields issue into the mix: if we were to replace On top of this, my thinking was: “let’s just group all these keys in a reserved namespace, with a predictable key So, my order of preferences from favorite to least favorite:
I don’t actually find that confusing. There are very few core types, and not that many tasks. Keeping it all under a single package is fine, and a good tradeoff IMO.
I actually tried this for the container image operations:
Same reaction, not worth it. Also
This is a completely new concept to me, so I might need time to digest it. My initial reaction is: definitions nowhere could work, definitions everywhere could work, half and half scares me because it’s too subtle. But my opinion may evolve as I digest.
If the engine actually needs to accurately match these types (which is what I meant by “special”), then yes they should have a marker. But:
What I’m proposing is a very clear cut rule. Either the engine needs to reliably match a type (aka “it’s special”) or not. I don’t understand how this You don’t have to agree with my suggestion that grouping everything under top-level marker key is better DX, but let’s at least agree that it’s a reasonable and easy rule to apply. This “where does it stop” argument is nonsense.
This is not terrible but I believe we can do better (I mean DX wise - I don’t have strong opinions on the implementation beyond how it impacts DX). Specifically I see 2 possible improvements to the DX:
EDIT: adding your follow-up comment here, which I only saw now
I love this, and would love it even more if privileged tasks could be registered against a path instead of a marker. That way I get my dream DX, and you get your dream implementation :) I think the distinction between privileged and unprivileged tasks is important enough to justify a slightly different registration mecanism (but then it can all be run in the same unified cue-flow, just with slightly different matching logic in the respective cueflow handlers). Perhaps this is wishful thinking and absolutely impossible in the implementation,but one can hope :) |
Perhaps that's the misconception. The engine doesn't care one bit. It doesn't need to reliably match core types. The thing that cares about differentiating It's not nonsense -- we have the same problem with EDIT What I'm saying is, we don't need any kind of special markers for core types. What we need is CUE to be happy about ALL of our types (whether they're low or high level) being distinguishable one another if we plan to use disjunctions on them or validate that we're passing the right thing (e.g. passing a Where does it stop? --> I legit meant this in a non sarcastic way. Like, do we end up throwing a In the case of And the same goes for core types -- the runtime doesn't care about |
OK I understand what you mean, but what about the ID field? The engine needs to fill and lookup that field. Don’t you count that as a “special” interaction that makes
Let me provide additional context on this one, since I wrote that disjunction.
Bottom line, I’m fine with a strict interpretation of my “markers are only for special interactions with the engine” rule. If that means a little more work for me getting my magic disjunctions to work, that’s OK. |
|
I think we landed on a good compromise which incorporates:
// Core types (e.g. #FS)
#FS: {
$dagger: fs: _id: string
}
// Tasks (e.g. #Exec)
#Exec: {
$dagger: task: _id: "Exec"
} |
Yes this works for me. Note that in the future I might advocate for getting rid of hidden fields, depending on whether the possible issue described in #1241 materializes. But we can cross that bridge if/when we get to it. |
|
Im not sold on I might agree with @shykes re: hidden fields. It might get weird to see visible keys with invisible and un-referencable contents |
I’m fine with that too.
Just to re-iterate, I’m happy to kick this can down the road. |
|
Next step: I will update this PR so that the spec matches the corresponding implementation change in #1242 . |
$dagger field to mark CUE types for engine recognition
$dagger field to mark CUE types for engine recognitionSigned-off-by: Solomon Hykes <[email protected]>
|
Merging in spite of failing (flaky) integration test, since this is a 100% spec change. |
Summary
This PR implements the Great Design Compromise of December 16, 2021, summarized below.
Note I am incorporating the tweak suggested by @talentedmrjones of using
task: _namerather thantask: _id.Related PRs
Future issues
See #1241 . Note that we are kicking this can down the road.
Original proposal
Below is my original proposal, for historical record. Most of the comments below are in response to this.