ColtenOuO opened a new pull request, #71003:
URL: https://github.com/apache/airflow/pull/71003

   ## Summary
   
   `update_mask` lets a PATCH caller say "only apply these fields". Every 
endpoint
   implements it by intersecting the mask with the fields present in the body:
   
   ```python
   fields_to_update = patch_body.model_fields_set.intersection(update_mask)
   ```
   
   An entry that matches no field simply falls out of the intersection. Nothing
   notices, so the request becomes a no-op — and still answers `200`, echoing 
back
   the untouched record.
   
   A typo is therefore indistinguishable from success:
   
   ```console
   $ curl -X PATCH '.../variables/pk?update_mask=value' -d 
'{"key":"pk","value":"CHANGED",...}'
   200   # value -> "CHANGED"
   
   $ curl -X PATCH '.../variables/pk?update_mask=valu' -d 
'{"key":"pk","value":"CHANGED",...}'
   200   # value still "original"
   
   $ curl -X PATCH '.../pools/p?update_mask=slot' -d 
'{"pool":"p","slots":99,...}'
   200   # slots still 1
   ```
   
   A stray space does the same thing, since nothing trims the entries:
   
   ```console
   $ curl -X PATCH '.../variables/pk?update_mask=%20value' ...
   200   # value still "original"
   ```
   
   A client that checks the status code has no way to learn its patch never 
landed.
   
   `dags.py` already guards against this (`if update_mask != ["is_paused"]: 
raise 400`),
   so rejecting an unusable mask is an established expectation in this API — it 
was
   just missing from the other five places that accept one.
   
   ## Before / after
   
   | Request | Before | After |
   | --- | --- | --- |
   | `?update_mask=value` | `200`, applied | unchanged |
   | `?update_mask=valu` | `200`, **not applied** | `400` naming the unknown 
field |
   | `?update_mask=%20value` | `200`, **not applied** | `200`, applied |
   
   The error names both the offender and the accepted fields:
   
   ```
   Unknown field(s) in update_mask: 'slot'.
   Valid fields are: description, include_deferred, name, slots, team_name.
   ```
   
   ## The change
   
   A single `validate_update_mask()` helper in `services/public/common.py`, 
called from
   the five places that accept a mask: `apply_patch_with_update_mask` (covers 
variables
   and pools, including their bulk actions), the connections route, the dag-run 
route,
   and the task-instance service. `dags.py` is left alone — it already 
validates.
   
   Two decisions worth flagging:
   
   **Aliases count as known names.** Validating against field names alone broke 
an
   existing connections test: `ConnectionBody.schema_` is aliased to `schema`, 
and
   `update_mask=["schema","extra"]` is a working request today. A caller sends 
the alias
   in the body and reads it back in the response, so it has to be accepted. 
This PR only
   *validates* the mask — which of the two names a given endpoint acts on is 
deliberately
   left untouched.
   
   **Whitespace is trimmed rather than rejected.** `pools.py` already compares 
with
   `mask.strip()`, and the intent of `" value"` is not in doubt.
   
   ## Note on an existing test
   
   `test_patch_dag_run_with_update_mask` had a case asserting that
   `{"update_mask": ["random"]}` returns `200` — the buggy behaviour written 
down as an
   expectation. It now expects `400` and the error message.
   
   ## Tests
   
   Four new cases on variables: three unknown-field shapes (a typo, a name that 
exists
   nowhere, an empty string) assert `400` **and** that the row is unchanged, 
plus one
   asserting a mask with surrounding whitespace still applies.
   
   `test_variables` + `test_dag_run`: 443 passed.
   `test_pools` + `test_connections` + `test_task_instances` + `test_dags`: 684 
passed.
   
   ---
   
   ##### Was generative AI tooling used to co-author this PR?
   
   - [X] Yes — Claude Code (Opus 5)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to