mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-08 03:08:45 +00:00
* feat(terraform): expose key type on virtual keys
* docs(terraform): remove in-tree key type docs
* fix(terraform): preserve server-derived key routes
* fix(terraform): keep unconfigured key routes plan-known and unsent
Two regressions from exposing key_type on litellm_key:
1. Marking allowed_routes Computed makes an omitted attribute unknown at
plan time ("known only after apply"), so any plan that consumes it
before the key exists fails, e.g.
for_each = toset(coalesce(litellm_key.x.allowed_routes, [])).
Computed is dropped again; server-derived routes still land in state
through reads, and a DiffSuppressFunc keyed on the raw config keeps a
config that never declares the attribute from showing a perpetual
removal diff against those routes (a config that shrinks the list or
sets it still diffs).
2. mapResourceDataToKey copies allowed_routes unconditionally and
UpdateKey sends it when non-empty, so once reads materialize the
server's routes into state, every update re-asserts them: an
alias-only rename POSTs allowed_routes (the pre-key_type provider
sent none), and with stale state (-refresh=false) it silently
overwrites routes managed outside Terraform. Updates now omit the
field whenever the raw config does not declare it.
The key_type flow is unchanged: create still sends key_type, the proxy
presets the routes, reads materialize them into state, and plans stay
drift-free.
* fix(terraform): reject allowed_routes alongside a presetting key_type
The proxy derives allowed_routes from the key_type preset and overwrites
whatever the request declared, so a config combining the two could never
match what gets stored: the key came back with the preset routes and
drifted against the declared list on every plan. A CustomizeDiff now
fails the plan with an actionable message when a presetting key_type
(llm_api, management, read_only) is combined with allowed_routes.
key_type "default" presets nothing and keeps declared routes.
* fix(terraform): scope key_type route rejection to create-shaped plans
/key/update stores an explicit allowed_routes verbatim and never reapplies
the key_type preset, so an existing or imported typed key can manage its
routes in place. Only plans that create a key (fresh, or a replacement
that changes key_type) still reject the combination, because there the
preset always overwrites the declared list. A replacement forced by
another ForceNew attribute converges on the next apply, which re-sends
the declared routes.
* fix(terraform): restore declared routes on typed key creation
/key/generate replaces a declared allowed_routes with the key_type
preset while /key/update stores the list verbatim, so any create that
carries both (a fresh key, or a replacement forced by key_type or
another ForceNew attribute) used to leave the key holding the preset
instead of the declared routes until a second apply. When the generate
response does not match the declared list, create now follows up with an
update that re-sends the full create payload against the new key hash,
so the first apply already stores the declared routes. This also
replaces the plan-time rejection of the combination: every config shape
now converges, and existing typed keys keep managing routes in place as
before.
* fix(terraform): delete the key when a route restore fails at create
If /key/generate succeeds but the restore update is rejected, the key
exists server-side while terraform holds no state for it: an active key
with the type preset would be orphaned and a retried apply would mint
another one. The restore failure path now deletes the created key, and a
delete that also fails names the key hash in the error so an operator
can remove it manually.
* fix(terraform): make the route restore surgical and keep supplied keys
Two sharp edges on the create-time route restore:
- Re-sending the full create payload rewrote fields the config never
declared: /key/update is a merge patch, so the empty metadata and
model_rpm_limit/model_tpm_limit maps the restored struct carried would
clear server-applied values such as team-inherited rate limits. The
restore now sends only the routes plus the two fields /key/update
requires non-null (permissions, model_max_budget); every other stored
value is kept.
- /key/generate upserts a config-supplied key value, so a restore
failure on such a key must not delete it: it may be an existing
credential that predates this apply. The compensating delete now runs
only for proxy-minted keys, and the error names the hash either way.
* fix(terraform): echo stored permissions and budgets in route restore
The surgical restore body carried empty permissions and model_max_budget
objects, and /key/update writes fields that are present: a key created
with declared permissions or model budgets next to a presetting key_type
and allowed_routes lost them on the first apply. The restore now echoes
the values /key/generate just stored (falling back to the configured
values when the response omits them), so the only field the restore ever
changes is allowed_routes.
* test(terraform): pin echoed budgets in the route restore
Adds the nonempty model_max_budget case Greptile asked for (the restore
must echo the stored map, never clear it) and drops a comment that
restated its own line.
* test(terraform): assert the declared budget reaches key generation
The budget echo case fed the raw config a malformed JSON string (a
template leftover), so nothing verified the declared budget actually
reached /key/generate. The config now carries the valid JSON and the
generate payload is asserted to match it.
* chore(terraform): trim the restore test preface to the proxy facts
---------
Co-authored-by: Roman Soletskyi <roman@mistral.ai>
|
||
|---|---|---|
| .. | ||
| litellm | ||
| provider | ||