-
-
Notifications
You must be signed in to change notification settings - Fork 750
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
Retrieve live params first, include template-driven defaults #3892
Conversation
6e07e92
to
c245cde
Compare
Also change order so validation is done after this rendering Signed-off-by: Matt Oswalt <matt@keepingitclassless.net>
57fc1d1
to
393bd55
Compare
…avior Signed-off-by: Matt Oswalt <matt@keepingitclassless.net>
+100 |
for schema in schemas: | ||
for param_name, param_details in schema.items(): | ||
|
||
# Skip if the parameter doesn't have a default, or if the |
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 it possible to add some test cases just for this function for various scenarios which are possible here?
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 approved it, but it would be great if we can add some more test cases for that, because just this for loop shows that at least 4 different scenarios are possible just in this code block.
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.
Thanks for the approve, I'll add more test cases for this before merging.
Overall, from a high level perspective the change and approach looks good to me. We had some discussion about this in the past (dynamic default parameter values) and I was strongly against it then. My main reason was that is very hard to reason about - different values are available at different point in lifecycle of an execution (before any rendering is happen, after rendering happens, when execution is created, etc). I'm still personally not a big fan of it (static > dynamic - a lot easier to reason about, develop, troubleshoot, see what is going on, etc.), but apparently other users see value in it and in a sense it's opt-in so I'm fine with it. |
I agree with you actually. I far prefer predictable values than moving the problem to runtime. One of the reasons I go write Go code when Python starts grinding my gears again :) In any case, my point was that IMO we crossed this boundary when we allowed templates in default values for actions in the first place. This PR just finishes that work by making the type cast portion work the way you'd expect. |
Signed-off-by: Matt Oswalt <matt@keepingitclassless.net>
Signed-off-by: Matt Oswalt <matt@keepingitclassless.net>
Problem
#3820 reported an issue that parameter defaults that use Jinja templates that return something other than string, simply don't work.
This is caused by two things:
action_service.create_request
before the live parameters are retrieved, which is where any templates are rendered into a result value. So if a parameter is aninteger
but the default value is still a template (string) - even if that template is expected to return an int, naturally this will cause problems because it hasn't even rendered yet.param_utils.render_live_params
and the function calls within will render the templates, but will not actually use the resulting value, as the default values for parameters are not seen as "live". So even though there's a rendered value available to use, it's not placed in the params list because it wasn't passed in explicitly by the user, and the same problem occurs, as the unrendered template value is used (string).Proposed Solution
To fix the behavior observed in #3820, I propose the following changes:
action_service.request
until the live params are retrieved.I think treating rendered default values as "live" parameters makes sense. Inherently, since we're using a template, it could easily be user-provided, even if the user provides it via
st2kv
. It's a bit of a paradigm change but I think it makes sense, personally.One potential consequence to note is that the parameter schema will now have to validate against what the template's value will be, but IMO this should already be happening anyways. I would expect that if I'm getting a value from a template, that the datatype should be predictable, and if it's different for any reason, I would expect a validation error at runtime. We've already inherently moved this problem to runtime by using templates in params like this anyways - this just makes the resulting behavior more intuitive.
Demo
I threw together a quick action to demonstrate the new logic:
I'll create the referenced key in the datastore and execute my action:
Note that
kv_test
appears in the resulting live parameters as if I had passed it in explicitly. While it's true, I didn't do this at the CLI, I believe the intention is the same - the default value is based on dynamic retrieval from the datastore via the template.Note also that I can still override this with my own value - a "true" live param:
Closes #3820