-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add
team_access
resource (#398)
* Fix payloads finally * Test team access for users * Fix description to show team_access * Validate 'user' or 'service_account' values * Add examples * Touch up description
- Loading branch information
1 parent
9383bda
commit c319331
Showing
9 changed files
with
621 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
--- | ||
# generated by https://github.com/hashicorp/terraform-plugin-docs | ||
page_title: "prefect_team_access Resource - prefect" | ||
subcategory: "" | ||
description: |- | ||
The resource team_access grants access to a team for a user or service account. For more information, see manage teams https://docs.prefect.io/v3/manage/cloud/manage-users/manage-teams. | ||
--- | ||
|
||
# prefect_team_access (Resource) | ||
|
||
The resource `team_access` grants access to a team for a user or service account. For more information, see [manage teams](https://docs.prefect.io/v3/manage/cloud/manage-users/manage-teams). | ||
|
||
## Example Usage | ||
|
||
```terraform | ||
# Example: granting access to a service account. | ||
resource "prefect_service_account" "test" { | ||
name = "my-service-account" | ||
} | ||
resource "prefect_team" "test" { | ||
name = "my-team" | ||
description = "test-team-description" | ||
} | ||
resource "prefect_team_access" "test" { | ||
member_type = "service_account" | ||
member_id = prefect_service_account.test.id | ||
member_actor_id = prefect_service_account.test.actor_id | ||
team_id = prefect_team.test.id | ||
} | ||
# Example: granting access to a user. | ||
data "prefect_account_member" "test" { | ||
email = "[email protected]" | ||
} | ||
resource "prefect_team" "test" { | ||
name = "my-team" | ||
description = "test-team-description" | ||
} | ||
resource "prefect_team_access" "test" { | ||
team_id = prefect_team.test.id | ||
member_type = "user" | ||
member_id = data.prefect_account_member.test.user_id | ||
member_actor_id = data.prefect_account_member.test.actor_id | ||
} | ||
``` | ||
|
||
<!-- schema generated by tfplugindocs --> | ||
## Schema | ||
|
||
### Required | ||
|
||
- `member_actor_id` (String) Member Actor ID (UUID) | ||
- `member_id` (String) Member ID (UUID) | ||
- `member_type` (String) Member Type (user | service_account) | ||
- `team_id` (String) Team ID (UUID) | ||
|
||
### Optional | ||
|
||
- `account_id` (String) Account ID (UUID) | ||
|
||
### Read-Only | ||
|
||
- `id` (String) Team Access ID |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# Example: granting access to a service account. | ||
|
||
resource "prefect_service_account" "test" { | ||
name = "my-service-account" | ||
} | ||
|
||
resource "prefect_team" "test" { | ||
name = "my-team" | ||
description = "test-team-description" | ||
} | ||
|
||
resource "prefect_team_access" "test" { | ||
member_type = "service_account" | ||
member_id = prefect_service_account.test.id | ||
member_actor_id = prefect_service_account.test.actor_id | ||
team_id = prefect_team.test.id | ||
} | ||
|
||
|
||
# Example: granting access to a user. | ||
|
||
data "prefect_account_member" "test" { | ||
email = "[email protected]" | ||
} | ||
|
||
resource "prefect_team" "test" { | ||
name = "my-team" | ||
description = "test-team-description" | ||
} | ||
|
||
resource "prefect_team_access" "test" { | ||
team_id = prefect_team.test.id | ||
member_type = "user" | ||
member_id = data.prefect_account_member.test.user_id | ||
member_actor_id = data.prefect_account_member.test.actor_id | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package api | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/google/uuid" | ||
) | ||
|
||
// TeamAccessClient is a client for the TeamAccess resource. | ||
type TeamAccessClient interface { | ||
Read(ctx context.Context, teamID, memberID, memberActorID uuid.UUID) (*TeamAccess, error) | ||
Upsert(ctx context.Context, memberType string, memberID uuid.UUID) error | ||
Delete(ctx context.Context, memberID uuid.UUID) error | ||
} | ||
|
||
// TeamAccess is a representation of a team access. | ||
type TeamAccess struct { | ||
BaseModel | ||
|
||
TeamID uuid.UUID `json:"team_id"` | ||
|
||
MemberID uuid.UUID `json:"member_id"` | ||
MemberActorID uuid.UUID `json:"member_actor_id"` | ||
MemberType string `json:"member_type"` | ||
} | ||
|
||
// TeamAccessUpsert defines the payload for an upsert request. | ||
type TeamAccessUpsert struct { | ||
Members []TeamAccessMember `json:"members"` | ||
} | ||
|
||
// TeamAccessMember is a representation of a team access member. | ||
type TeamAccessMember struct { | ||
MemberID uuid.UUID `json:"member_id"` | ||
MemberType string `json:"member_type"` | ||
} | ||
|
||
// TeamAccessRead defines the response payload for a get request. | ||
type TeamAccessRead struct { | ||
Memberships []Membership `json:"memberships"` | ||
} | ||
|
||
// Membership is a representation of a team access membership. | ||
type Membership struct { | ||
ActorID uuid.UUID `json:"id"` | ||
Type string `json:"type"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package client | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"net/http" | ||
|
||
"github.com/google/uuid" | ||
"github.com/prefecthq/terraform-provider-prefect/internal/api" | ||
) | ||
|
||
var _ = api.TeamAccessClient(&TeamAccessClient{}) | ||
|
||
// TeamAccessClient is a client for the TeamAccess resource. | ||
type TeamAccessClient struct { | ||
hc *http.Client | ||
apiKey string | ||
basicAuthKey string | ||
routePrefix string | ||
} | ||
|
||
// TeamAccess is a factory that initializes and returns a TeamAccessClient. | ||
// | ||
//nolint:ireturn // required to support PrefectClient mocking | ||
func (c *Client) TeamAccess(accountID uuid.UUID, teamID uuid.UUID) (api.TeamAccessClient, error) { | ||
if accountID == uuid.Nil { | ||
accountID = c.defaultAccountID | ||
} | ||
|
||
return &TeamAccessClient{ | ||
hc: c.hc, | ||
apiKey: c.apiKey, | ||
basicAuthKey: c.basicAuthKey, | ||
routePrefix: fmt.Sprintf("%s/accounts/%s/teams/%s", c.endpoint, accountID.String(), teamID.String()), | ||
}, nil | ||
} | ||
|
||
// Upsert creates or updates access to a team for a member. | ||
func (c *TeamAccessClient) Upsert(ctx context.Context, memberType string, memberID uuid.UUID) error { | ||
payload := api.TeamAccessUpsert{ | ||
Members: []api.TeamAccessMember{ | ||
{ | ||
MemberID: memberID, | ||
MemberType: memberType, | ||
}, | ||
}, | ||
} | ||
|
||
cfg := requestConfig{ | ||
method: http.MethodPut, | ||
url: fmt.Sprintf("%s/members", c.routePrefix), | ||
body: &payload, | ||
apiKey: c.apiKey, | ||
basicAuthKey: c.basicAuthKey, | ||
successCodes: successCodesStatusOK, | ||
} | ||
|
||
resp, err := request(ctx, c.hc, cfg) | ||
if err != nil { | ||
return fmt.Errorf("failed to upsert team access: %w", err) | ||
} | ||
defer resp.Body.Close() | ||
|
||
return nil | ||
} | ||
|
||
// Read fetches a team access by member actor ID. | ||
func (c *TeamAccessClient) Read(ctx context.Context, teamID, memberID, memberActorID uuid.UUID) (*api.TeamAccess, error) { | ||
cfg := requestConfig{ | ||
method: http.MethodGet, | ||
url: c.routePrefix, | ||
apiKey: c.apiKey, | ||
basicAuthKey: c.basicAuthKey, | ||
successCodes: successCodesStatusOK, | ||
} | ||
|
||
var teamAccessRead api.TeamAccessRead | ||
if err := requestWithDecodeResponse(ctx, c.hc, cfg, &teamAccessRead); err != nil { | ||
return nil, fmt.Errorf("failed to get team access: %w", err) | ||
} | ||
|
||
// Find the memberships entry that matches the member ID. | ||
var teamAccess *api.TeamAccess | ||
for _, membership := range teamAccessRead.Memberships { | ||
if membership.ActorID == memberActorID { | ||
teamAccess = &api.TeamAccess{ | ||
TeamID: teamID, | ||
MemberID: memberID, | ||
MemberActorID: memberActorID, | ||
MemberType: membership.Type, | ||
} | ||
|
||
break | ||
} | ||
} | ||
|
||
if teamAccess == nil { | ||
return nil, fmt.Errorf("client.Read: team access not found for member ID: %s", memberActorID.String()) | ||
} | ||
|
||
return teamAccess, nil | ||
} | ||
|
||
// Delete deletes a team access by member ID. | ||
func (c *TeamAccessClient) Delete(ctx context.Context, memberID uuid.UUID) error { | ||
cfg := requestConfig{ | ||
method: http.MethodDelete, | ||
url: fmt.Sprintf("%s/members/%s", c.routePrefix, memberID.String()), | ||
body: http.NoBody, | ||
apiKey: c.apiKey, | ||
basicAuthKey: c.basicAuthKey, | ||
successCodes: successCodesStatusNoContent, | ||
} | ||
|
||
resp, err := request(ctx, c.hc, cfg) | ||
if err != nil { | ||
return fmt.Errorf("failed to delete team access: %w", err) | ||
} | ||
defer resp.Body.Close() | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.