Validate Cloud Function deploy body after template rendering - #70531
Validate Cloud Function deploy body after template rendering#70531mitre88 wants to merge 1 commit into
Conversation
potiuk
left a comment
There was a problem hiding this comment.
Thanks — correct move. body is a template field, so GcpBodyFieldValidator in __init__ was validating the un-rendered value: a templated body could never pass validation, and a literal bad one broke Dag parsing instead of failing the task. Constructing the validator and the ZipPathPreprocessor in execute and running _validate_inputs() there is the right shape.
test_templated_body_deploys_after_rendering is a good addition — asserting create_new_function.assert_called_once() after a rendered body proves the happy path still works, not just that the failure path raises.
One robustness point inline about an attribute that no longer exists until execute runs.
Drafted-by: Claude Code (Opus 5); reviewed by @potiuk before posting
| } | ||
|
|
||
| def execute(self, context: Context): | ||
| self.zip_path_preprocessor = ZipPathPreprocessor(self.body, self.zip_path) |
There was a problem hiding this comment.
self.zip_path_preprocessor is now only assigned here, so between construction and the first execute the attribute doesn't exist at all — any access raises AttributeError rather than returning something sensible. That affects subclasses, tests, and anything introspecting the operator between parse and run.
Note you've already handled the sibling case correctly: self._field_validator: GcpBodyFieldValidator | None = None is still initialised in __init__ and merely reassigned in execute. Doing the same for the preprocessor — declare it as None in __init__, build it here — would make the two consistent and keep the operator's attribute surface stable from construction onwards.
Drafted-by: Claude Code (Opus 5); reviewed by @potiuk before posting
Rebased onto current main. Move body/location validation and zip preprocessing into execute so Jinja-templated body is checked after render.
8319802 to
3280b64
Compare
Part of the template-field validation burn-down tracked in #70296.
CloudFunctionDeployFunctionOperatorlistsbody,location, andapi_versionintemplate_fields, but__init__validated the body, ranZipPathPreprocessor.preprocess_body()(which both validates and mutates the body), and constructedGcpBodyFieldValidatorpinned to the un-renderedapi_version. A fully templatedbodycrashed withAttributeErrorat parse time inside the preprocessor. All of this now runs at the start ofexecute()against the rendered values.The missing-
location/bodytruthiness checks and the zip-path exclusivity rules depend on rendered values (an expression rendering to an empty string must count as missing), so per the discussion in #70505 these are genuine value reads, not provision checks.Tests: converted the four construction-time raise tests to execute-time, and added
test_templated_body_deploys_after_rendering, which constructs the operator with a templatedbody(previously a parse-time crash) and deploys once the field holds the rendered value — it fails against the previous implementation. The class is removed from the exemption list and thevalidate-operators-initcheck passes locally.Was generative AI tooling used to co-author this PR?
Generated-by: Claude Code (Fable 5) following the guidelines