Skip to content

Commit 516b301

Browse files
author
Nicholas Cecere
committed
Add support for team member permissions in team resource (v3.1.0)
1 parent a932028 commit 516b301

File tree

4 files changed

+98
-15
lines changed

4 files changed

+98
-15
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [3.1.0] - 2025-05-09
9+
10+
### Added
11+
- Support for team member permissions in the `litellm_team` resource
12+
813
## [0.3.0] - 2025-04-23
914

1015
### Fixed

docs/resources/team.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ resource "litellm_team" "engineering" {
1010
organization_id = "org_123456"
1111
models = ["gpt-4-proxy", "claude-2"]
1212
13+
team_member_permissions = [
14+
"/key/generate",
15+
"/key/update",
16+
"/key/info",
17+
"/key/list"
18+
]
19+
1320
metadata = {
1421
department = "Engineering"
1522
project = "AI Research"
@@ -49,6 +56,8 @@ The following arguments are supported:
4956
* `monthly`
5057
* `yearly`
5158

59+
* `team_member_permissions` - (Optional) List of permissions granted to team members. Available permissions can be retrieved from the API endpoint `/team/permissions_list`.
60+
5261
## Attribute Reference
5362

5463
In addition to the arguments above, the following attributes are exported:

litellm/resource_team.go

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ import (
1212
)
1313

1414
const (
15-
endpointTeamNew = "/team/new"
16-
endpointTeamInfo = "/team/info"
17-
endpointTeamUpdate = "/team/update"
18-
endpointTeamDelete = "/team/delete"
15+
endpointTeamNew = "/team/new"
16+
endpointTeamInfo = "/team/info"
17+
endpointTeamUpdate = "/team/update"
18+
endpointTeamDelete = "/team/delete"
19+
endpointTeamPermissionsList = "/team/permissions_list"
20+
endpointTeamPermissionsUpdate = "/team/permissions_update"
1921
)
2022

2123
func ResourceLiteLLMTeam() *schema.Resource {
@@ -64,6 +66,12 @@ func ResourceLiteLLMTeam() *schema.Resource {
6466
Type: schema.TypeBool,
6567
Optional: true,
6668
},
69+
"team_member_permissions": {
70+
Type: schema.TypeList,
71+
Optional: true,
72+
Elem: &schema.Schema{Type: schema.TypeString},
73+
Description: "List of permissions granted to team members",
74+
},
6775
},
6876
}
6977
}
@@ -139,6 +147,13 @@ func resourceLiteLLMTeamRead(d *schema.ResourceData, m interface{}) error {
139147

140148
d.Set("blocked", GetBoolValue(teamResp.Blocked, d.Get("blocked").(bool)))
141149

150+
// Handle team_member_permissions separately as it's a list
151+
if teamResp.TeamMemberPermissions != nil {
152+
d.Set("team_member_permissions", teamResp.TeamMemberPermissions)
153+
} else {
154+
d.Set("team_member_permissions", d.Get("team_member_permissions"))
155+
}
156+
142157
log.Printf("[INFO] Successfully read team with ID: %s", d.Id())
143158
return nil
144159
}
@@ -193,7 +208,7 @@ func buildTeamData(d *schema.ResourceData, teamID string) map[string]interface{}
193208
"team_alias": d.Get("team_alias").(string),
194209
}
195210

196-
for _, key := range []string{"organization_id", "metadata", "tpm_limit", "rpm_limit", "max_budget", "budget_duration", "models", "blocked"} {
211+
for _, key := range []string{"organization_id", "metadata", "tpm_limit", "rpm_limit", "max_budget", "budget_duration", "models", "blocked", "team_member_permissions"} {
197212
if v, ok := d.GetOk(key); ok {
198213
teamData[key] = v
199214
}
@@ -209,3 +224,56 @@ func handleResponse(resp *http.Response, action string) error {
209224
}
210225
return nil
211226
}
227+
228+
// TeamPermissionsResponse represents a response from the API containing team permissions information.
229+
type TeamPermissionsResponse struct {
230+
TeamID string `json:"team_id"`
231+
TeamMemberPermissions []string `json:"team_member_permissions"`
232+
AllAvailablePermissions []string `json:"all_available_permissions"`
233+
}
234+
235+
// getTeamPermissions retrieves the current permissions and available permissions for a team.
236+
func getTeamPermissions(client *Client, teamID string) (*TeamPermissionsResponse, error) {
237+
log.Printf("[INFO] Getting permissions for team with ID: %s", teamID)
238+
239+
resp, err := MakeRequest(client, "GET", fmt.Sprintf("%s?team_id=%s", endpointTeamPermissionsList, teamID), nil)
240+
if err != nil {
241+
return nil, fmt.Errorf("error getting team permissions: %w", err)
242+
}
243+
defer resp.Body.Close()
244+
245+
if resp.StatusCode != http.StatusOK {
246+
body, _ := ioutil.ReadAll(resp.Body)
247+
return nil, fmt.Errorf("error getting team permissions: %s - %s", resp.Status, string(body))
248+
}
249+
250+
var permResp TeamPermissionsResponse
251+
if err := json.NewDecoder(resp.Body).Decode(&permResp); err != nil {
252+
return nil, fmt.Errorf("error decoding team permissions response: %w", err)
253+
}
254+
255+
return &permResp, nil
256+
}
257+
258+
// updateTeamPermissions updates the permissions for a team.
259+
func updateTeamPermissions(client *Client, teamID string, permissions []string) error {
260+
log.Printf("[INFO] Updating permissions for team with ID: %s", teamID)
261+
262+
permData := map[string]interface{}{
263+
"team_id": teamID,
264+
"team_member_permissions": permissions,
265+
}
266+
267+
resp, err := MakeRequest(client, "POST", endpointTeamPermissionsUpdate, permData)
268+
if err != nil {
269+
return fmt.Errorf("error updating team permissions: %w", err)
270+
}
271+
defer resp.Body.Close()
272+
273+
if err := handleResponse(resp, "updating team permissions"); err != nil {
274+
return err
275+
}
276+
277+
log.Printf("[INFO] Successfully updated permissions for team with ID: %s", teamID)
278+
return nil
279+
}

litellm/types.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,17 @@ type ModelRequest struct {
3131

3232
// TeamResponse represents a response from the API containing team information.
3333
type TeamResponse struct {
34-
TeamID string `json:"team_id,omitempty"`
35-
TeamAlias string `json:"team_alias,omitempty"`
36-
OrganizationID string `json:"organization_id,omitempty"`
37-
Metadata map[string]interface{} `json:"metadata,omitempty"`
38-
TPMLimit int `json:"tpm_limit,omitempty"`
39-
RPMLimit int `json:"rpm_limit,omitempty"`
40-
MaxBudget float64 `json:"max_budget,omitempty"`
41-
BudgetDuration string `json:"budget_duration,omitempty"`
42-
Models []string `json:"models"`
43-
Blocked bool `json:"blocked,omitempty"`
34+
TeamID string `json:"team_id,omitempty"`
35+
TeamAlias string `json:"team_alias,omitempty"`
36+
OrganizationID string `json:"organization_id,omitempty"`
37+
Metadata map[string]interface{} `json:"metadata,omitempty"`
38+
TPMLimit int `json:"tpm_limit,omitempty"`
39+
RPMLimit int `json:"rpm_limit,omitempty"`
40+
MaxBudget float64 `json:"max_budget,omitempty"`
41+
BudgetDuration string `json:"budget_duration,omitempty"`
42+
Models []string `json:"models"`
43+
Blocked bool `json:"blocked,omitempty"`
44+
TeamMemberPermissions []string `json:"team_member_permissions,omitempty"`
4445
}
4546

4647
// LiteLLMParams represents the parameters for LiteLLM.

0 commit comments

Comments
 (0)