mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-14 09:03:16 +00:00
Merge a7bf5fc3e2 into 72228db5c6
This commit is contained in:
commit
ac2ade7169
4 changed files with 131 additions and 27 deletions
|
|
@ -58,8 +58,10 @@ func resourceLiteLLMTeamMemberCreate(d *schema.ResourceData, m interface{}) erro
|
|||
"user_email": d.Get("user_email").(string),
|
||||
},
|
||||
},
|
||||
"team_id": d.Get("team_id").(string),
|
||||
"max_budget_in_team": d.Get("max_budget_in_team").(float64),
|
||||
"team_id": d.Get("team_id").(string),
|
||||
}
|
||||
if v, ok := d.GetOk("max_budget_in_team"); ok {
|
||||
memberData["max_budget_in_team"] = v.(float64)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Create team member request payload: %+v", memberData)
|
||||
|
|
@ -94,11 +96,15 @@ func resourceLiteLLMTeamMemberUpdate(d *schema.ResourceData, m interface{}) erro
|
|||
client := m.(*Client)
|
||||
|
||||
updateData := map[string]interface{}{
|
||||
"user_id": d.Get("user_id").(string),
|
||||
"user_email": d.Get("user_email").(string),
|
||||
"team_id": d.Get("team_id").(string),
|
||||
"role": d.Get("role").(string),
|
||||
"max_budget_in_team": d.Get("max_budget_in_team").(float64),
|
||||
"user_id": d.Get("user_id").(string),
|
||||
"user_email": d.Get("user_email").(string),
|
||||
"team_id": d.Get("team_id").(string),
|
||||
"role": d.Get("role").(string),
|
||||
}
|
||||
if v, ok := d.GetOk("max_budget_in_team"); ok {
|
||||
updateData["max_budget_in_team"] = v.(float64)
|
||||
} else if d.HasChange("max_budget_in_team") {
|
||||
updateData["max_budget_in_team"] = nil
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Update team member request payload: %+v", updateData)
|
||||
|
|
|
|||
|
|
@ -79,6 +79,9 @@ func expandAllowedModels(raw []interface{}) []string {
|
|||
}
|
||||
|
||||
func applyAddOnlySettings(d *schema.ResourceData, payload map[string]interface{}) {
|
||||
if v, ok := d.GetOk("max_budget_in_team"); ok {
|
||||
payload["max_budget_in_team"] = v.(float64)
|
||||
}
|
||||
if v, ok := d.GetOk("budget_duration"); ok {
|
||||
payload["budget_duration"] = v.(string)
|
||||
}
|
||||
|
|
@ -98,7 +101,7 @@ func applyLimits(d *schema.ResourceData, payload map[string]interface{}) {
|
|||
func applyUpdateSettings(d *schema.ResourceData, payload map[string]interface{}) {
|
||||
applyAddOnlySettings(d, payload)
|
||||
applyLimits(d, payload)
|
||||
for _, key := range []string{"tpm_limit", "rpm_limit", "budget_duration"} {
|
||||
for _, key := range []string{"max_budget_in_team", "tpm_limit", "rpm_limit", "budget_duration"} {
|
||||
if _, ok := d.GetOk(key); !ok && d.HasChange(key) {
|
||||
payload[key] = nil
|
||||
}
|
||||
|
|
@ -153,7 +156,6 @@ func resourceLiteLLMTeamMemberAddCreate(d *schema.ResourceData, m interface{}) e
|
|||
|
||||
teamID := d.Get("team_id").(string)
|
||||
members := d.Get("member").(*schema.Set)
|
||||
maxBudget := d.Get("max_budget_in_team").(float64)
|
||||
|
||||
// Convert members to the expected format
|
||||
membersList := make([]map[string]interface{}, 0, members.Len())
|
||||
|
|
@ -172,9 +174,8 @@ func resourceLiteLLMTeamMemberAddCreate(d *schema.ResourceData, m interface{}) e
|
|||
}
|
||||
|
||||
memberData := map[string]interface{}{
|
||||
"member": membersList,
|
||||
"team_id": teamID,
|
||||
"max_budget_in_team": maxBudget,
|
||||
"member": membersList,
|
||||
"team_id": teamID,
|
||||
}
|
||||
applyAddOnlySettings(d, memberData)
|
||||
|
||||
|
|
@ -208,7 +209,6 @@ func resourceLiteLLMTeamMemberAddRead(d *schema.ResourceData, m interface{}) err
|
|||
func resourceLiteLLMTeamMemberAddUpdate(d *schema.ResourceData, m interface{}) error {
|
||||
client := m.(*Client)
|
||||
teamID := d.Get("team_id").(string)
|
||||
maxBudget := d.Get("max_budget_in_team").(float64)
|
||||
|
||||
o, n := d.GetChange("member")
|
||||
oldMembers := o.(*schema.Set)
|
||||
|
|
@ -249,9 +249,8 @@ func resourceLiteLLMTeamMemberAddUpdate(d *schema.ResourceData, m interface{}) e
|
|||
for key, newMember := range newMemberMap {
|
||||
if _, exists := oldMemberMap[key]; exists {
|
||||
updateData := map[string]interface{}{
|
||||
"team_id": teamID,
|
||||
"role": newMember["role"].(string),
|
||||
"max_budget_in_team": maxBudget,
|
||||
"team_id": teamID,
|
||||
"role": newMember["role"].(string),
|
||||
}
|
||||
applyUpdateSettings(d, updateData)
|
||||
memberIdentity(newMember, updateData)
|
||||
|
|
@ -313,9 +312,8 @@ func resourceLiteLLMTeamMemberAddUpdate(d *schema.ResourceData, m interface{}) e
|
|||
// Check if member attributes have changed
|
||||
if memberAttributesChanged(oldMember, newMember) {
|
||||
updateData := map[string]interface{}{
|
||||
"team_id": teamID,
|
||||
"role": newMember["role"].(string),
|
||||
"max_budget_in_team": maxBudget,
|
||||
"team_id": teamID,
|
||||
"role": newMember["role"].(string),
|
||||
}
|
||||
applyUpdateSettings(d, updateData)
|
||||
memberIdentity(newMember, updateData)
|
||||
|
|
@ -354,9 +352,8 @@ func resourceLiteLLMTeamMemberAddUpdate(d *schema.ResourceData, m interface{}) e
|
|||
|
||||
if len(membersToAdd) > 0 {
|
||||
memberData := map[string]interface{}{
|
||||
"member": membersToAdd,
|
||||
"team_id": teamID,
|
||||
"max_budget_in_team": maxBudget,
|
||||
"member": membersToAdd,
|
||||
"team_id": teamID,
|
||||
}
|
||||
applyAddOnlySettings(d, memberData)
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ func TestTeamMemberAddCreateSendsMemberSettings(t *testing.T) {
|
|||
if addPayload["budget_duration"] != "30d" {
|
||||
t.Fatalf("member_add payload sent budget_duration %v, want 30d", addPayload["budget_duration"])
|
||||
}
|
||||
if addPayload["max_budget_in_team"] != float64(25) {
|
||||
t.Fatalf("member_add payload sent max_budget_in_team %v, want 25", addPayload["max_budget_in_team"])
|
||||
}
|
||||
wantModels := []interface{}{"claude-opus-4-6-v1"}
|
||||
if !reflect.DeepEqual(addPayload["allowed_models"], wantModels) {
|
||||
t.Fatalf("member_add payload sent allowed_models %v, want %v", addPayload["allowed_models"], wantModels)
|
||||
|
|
@ -111,7 +114,7 @@ func TestTeamMemberAddCreateOmitsUnsetSettings(t *testing.T) {
|
|||
t.Fatalf("create failed: %v", err)
|
||||
}
|
||||
|
||||
for _, field := range []string{"tpm_limit", "rpm_limit", "budget_duration", "allowed_models"} {
|
||||
for _, field := range []string{"max_budget_in_team", "tpm_limit", "rpm_limit", "budget_duration", "allowed_models"} {
|
||||
if _, ok := addPayload[field]; ok {
|
||||
t.Fatalf("member_add payload must not carry unset %s, got %v", field, addPayload[field])
|
||||
}
|
||||
|
|
@ -216,11 +219,14 @@ func runTeamMemberUpdate(t *testing.T, d *schema.ResourceData) []map[string]inte
|
|||
|
||||
func TestTeamMemberAddUpdateSendsChangedSettings(t *testing.T) {
|
||||
d := newTeamMemberUpdateResourceData(t,
|
||||
map[string]string{"tpm_limit": "1000", "rpm_limit": "10", "budget_duration": "30d"},
|
||||
map[string]string{"tpm_limit": "500", "rpm_limit": "5", "budget_duration": "7d", "allowed_models.#": "1", "allowed_models.0": "gpt-5.2"},
|
||||
map[string]string{"max_budget_in_team": "25", "tpm_limit": "1000", "rpm_limit": "10", "budget_duration": "30d"},
|
||||
map[string]string{"max_budget_in_team": "50", "tpm_limit": "500", "rpm_limit": "5", "budget_duration": "7d", "allowed_models.#": "1", "allowed_models.0": "gpt-5.2"},
|
||||
)
|
||||
|
||||
update := runTeamMemberUpdate(t, d)[0]
|
||||
if update["max_budget_in_team"] != float64(50) {
|
||||
t.Fatalf("member_update payload max_budget_in_team = %v, want 50", update["max_budget_in_team"])
|
||||
}
|
||||
if update["tpm_limit"] != float64(500) || update["rpm_limit"] != float64(5) {
|
||||
t.Fatalf("member_update payload limits = %v/%v, want 500/5", update["tpm_limit"], update["rpm_limit"])
|
||||
}
|
||||
|
|
@ -237,12 +243,12 @@ func TestTeamMemberAddUpdateSendsChangedSettings(t *testing.T) {
|
|||
|
||||
func TestTeamMemberAddUpdateClearsRemovedSettings(t *testing.T) {
|
||||
d := newTeamMemberUpdateResourceData(t,
|
||||
map[string]string{"tpm_limit": "1000", "rpm_limit": "10", "budget_duration": "30d", "allowed_models.#": "1", "allowed_models.0": "gpt-5.2"},
|
||||
map[string]string{"max_budget_in_team": "25", "tpm_limit": "1000", "rpm_limit": "10", "budget_duration": "30d", "allowed_models.#": "1", "allowed_models.0": "gpt-5.2"},
|
||||
map[string]string{"allowed_models.#": "0"},
|
||||
)
|
||||
|
||||
update := runTeamMemberUpdate(t, d)[0]
|
||||
for _, field := range []string{"tpm_limit", "rpm_limit", "budget_duration"} {
|
||||
for _, field := range []string{"max_budget_in_team", "tpm_limit", "rpm_limit", "budget_duration"} {
|
||||
v, present := update[field]
|
||||
if !present {
|
||||
t.Fatalf("member_update payload omitted removed %s, so the proxy would keep the old value", field)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
|
||||
)
|
||||
|
||||
func TestTeamMemberUpdateSendsRole(t *testing.T) {
|
||||
|
|
@ -42,3 +43,97 @@ func TestTeamMemberUpdateSendsRole(t *testing.T) {
|
|||
t.Fatalf("update payload sent role %v, want user", role)
|
||||
}
|
||||
}
|
||||
|
||||
func teamMemberResourceData(t *testing.T, extra map[string]interface{}) *schema.ResourceData {
|
||||
t.Helper()
|
||||
raw := map[string]interface{}{
|
||||
"team_id": "team-1",
|
||||
"user_id": "user-1",
|
||||
"user_email": "user@example.com",
|
||||
"role": "user",
|
||||
}
|
||||
for k, v := range extra {
|
||||
raw[k] = v
|
||||
}
|
||||
return schema.TestResourceDataRaw(t, resourceLiteLLMTeamMember().Schema, raw)
|
||||
}
|
||||
|
||||
func newTeamMemberDiffResourceData(t *testing.T, old, new map[string]string) *schema.ResourceData {
|
||||
t.Helper()
|
||||
attrs := map[string]string{
|
||||
"team_id": "team-1",
|
||||
"user_id": "user-1",
|
||||
"user_email": "user@example.com",
|
||||
"role": "user",
|
||||
}
|
||||
for k, v := range old {
|
||||
attrs[k] = v
|
||||
}
|
||||
diffAttrs := map[string]*terraform.ResourceAttrDiff{}
|
||||
for k, v := range new {
|
||||
diffAttrs[k] = &terraform.ResourceAttrDiff{Old: attrs[k], New: v}
|
||||
}
|
||||
for k := range old {
|
||||
if _, ok := new[k]; !ok {
|
||||
diffAttrs[k] = &terraform.ResourceAttrDiff{Old: attrs[k], New: "", NewRemoved: true}
|
||||
}
|
||||
}
|
||||
state := &terraform.InstanceState{ID: "team-1:user-1", Attributes: attrs}
|
||||
d, err := schema.InternalMap(resourceLiteLLMTeamMember().Schema).Data(state, &terraform.InstanceDiff{Attributes: diffAttrs})
|
||||
if err != nil {
|
||||
t.Fatalf("building ResourceData returned error: %v", err)
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func captureTeamMemberPayload(t *testing.T, d *schema.ResourceData, apply func(*schema.ResourceData, interface{}) error) map[string]interface{} {
|
||||
t.Helper()
|
||||
var captured map[string]interface{}
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
body, _ := io.ReadAll(r.Body)
|
||||
json.Unmarshal(body, &captured)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`{}`))
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
if err := apply(d, NewClient(srv.URL, "test-key", true)); err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
return captured
|
||||
}
|
||||
|
||||
func TestTeamMemberCreateOmitsUnsetMaxBudget(t *testing.T) {
|
||||
payload := captureTeamMemberPayload(t, teamMemberResourceData(t, nil), resourceLiteLLMTeamMemberCreate)
|
||||
if v, ok := payload["max_budget_in_team"]; ok {
|
||||
t.Fatalf("member_add payload must not carry an unset max_budget_in_team, got %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTeamMemberCreateSendsMaxBudget(t *testing.T) {
|
||||
d := teamMemberResourceData(t, map[string]interface{}{"max_budget_in_team": 25.0})
|
||||
payload := captureTeamMemberPayload(t, d, resourceLiteLLMTeamMemberCreate)
|
||||
if payload["max_budget_in_team"] != float64(25) {
|
||||
t.Fatalf("member_add payload sent max_budget_in_team %v, want 25", payload["max_budget_in_team"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestTeamMemberUpdateOmitsUnsetMaxBudget(t *testing.T) {
|
||||
payload := captureTeamMemberPayload(t, teamMemberResourceData(t, nil), resourceLiteLLMTeamMemberUpdate)
|
||||
if v, ok := payload["max_budget_in_team"]; ok {
|
||||
t.Fatalf("member_update payload must not carry an unset max_budget_in_team, got %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTeamMemberUpdateClearsRemovedMaxBudget(t *testing.T) {
|
||||
d := newTeamMemberDiffResourceData(t, map[string]string{"max_budget_in_team": "25"}, nil)
|
||||
payload := captureTeamMemberPayload(t, d, resourceLiteLLMTeamMemberUpdate)
|
||||
v, ok := payload["max_budget_in_team"]
|
||||
if !ok {
|
||||
t.Fatal("member_update payload omitted removed max_budget_in_team, so the proxy would keep the old budget")
|
||||
}
|
||||
if v != nil {
|
||||
t.Fatalf("member_update payload max_budget_in_team = %v, want explicit null", v)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue