diff --git a/env0/resource_team_project_assignment.go b/env0/resource_team_project_assignment.go index b4619f7d..cabdee2b 100644 --- a/env0/resource_team_project_assignment.go +++ b/env0/resource_team_project_assignment.go @@ -2,7 +2,9 @@ package env0 import ( "context" + "fmt" "log" + "strings" "github.com/env0/terraform-provider-env0/client" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -16,6 +18,8 @@ func resourceTeamProjectAssignment() *schema.Resource { UpdateContext: resourceTeamProjectAssignmentCreateOrUpdate, DeleteContext: resourceTeamProjectAssignmentDelete, + Importer: &schema.ResourceImporter{StateContext: resourceTeamProjectAssignmentImport}, + Schema: map[string]*schema.Schema{ "team_id": { Type: schema.TypeString, @@ -114,3 +118,37 @@ func resourceTeamProjectAssignmentDelete(ctx context.Context, d *schema.Resource return nil } + +func resourceTeamProjectAssignmentImport(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + splitTeamProject := strings.Split(d.Id(), "_") + if len(splitTeamProject) != 2 { + return nil, fmt.Errorf("the id %v is invalid must be _", d.Id()) + } + + teamId := splitTeamProject[0] + projectId := splitTeamProject[1] + + apiClient := meta.(client.ApiClientInterface) + + assignments, err := apiClient.TeamProjectAssignments(projectId) + if err != nil { + return nil, err + } + + for _, assignment := range assignments { + if assignment.TeamId == teamId { + if err := writeResourceData(&assignment, d); err != nil { + return nil, fmt.Errorf("schema resource data serialization failed: %w", err) + } + + if client.IsBuiltinProjectRole(assignment.ProjectRole) { + d.Set("role", assignment.ProjectRole) + } else { + d.Set("custom_role_id", assignment.ProjectRole) + } + return []*schema.ResourceData{d}, nil + } + } + + return nil, fmt.Errorf("assignment with id %v not found", d.Id()) +} diff --git a/env0/resource_team_project_assignment_test.go b/env0/resource_team_project_assignment_test.go index 12a92d4d..5cf76e70 100644 --- a/env0/resource_team_project_assignment_test.go +++ b/env0/resource_team_project_assignment_test.go @@ -1,6 +1,7 @@ package env0 import ( + "regexp" "testing" "github.com/env0/terraform-provider-env0/client" @@ -11,6 +12,7 @@ import ( func TestUnitTeamProjectAssignmentResource(t *testing.T) { resourceType := "env0_team_project_assignment" resourceName := "test" + resourceNameImport := resourceType + "." + resourceName accessor := resourceAccessor(resourceType, resourceName) @@ -168,4 +170,83 @@ func TestUnitTeamProjectAssignmentResource(t *testing.T) { }) }) + t.Run("import - built-in role", func(t *testing.T) { + testCase := resource.TestCase{ + Steps: []resource.TestStep{ + { + Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{ + "team_id": assignment.TeamId, + "project_id": assignment.ProjectId, + "role": assignment.ProjectRole, + }), + }, + { + ResourceName: resourceNameImport, + ImportState: true, + ImportStateId: assignment.TeamId + "_" + assignment.ProjectId, + ImportStateVerify: true, + }, + }, + } + + runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) { + mock.EXPECT().TeamProjectAssignmentCreateOrUpdate(client.TeamProjectAssignmentPayload{TeamId: assignment.TeamId, ProjectId: assignment.ProjectId, ProjectRole: assignment.ProjectRole}).Times(1).Return(assignment, nil) + mock.EXPECT().TeamProjectAssignments(assignment.ProjectId).Times(3).Return([]client.TeamProjectAssignment{assignment}, nil) + mock.EXPECT().TeamProjectAssignmentDelete(assignment.Id).Times(1).Return(nil) + }) + }) + + t.Run("import - custom role", func(t *testing.T) { + testCase := resource.TestCase{ + Steps: []resource.TestStep{ + { + Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{ + "team_id": assignmentCustom.TeamId, + "project_id": assignmentCustom.ProjectId, + "custom_role_id": assignmentCustom.ProjectRole, + }), + }, + { + ResourceName: resourceNameImport, + ImportState: true, + ImportStateId: assignmentCustom.TeamId + "_" + assignmentCustom.ProjectId, + ImportStateVerify: true, + }, + }, + } + + runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) { + mock.EXPECT().TeamProjectAssignmentCreateOrUpdate(client.TeamProjectAssignmentPayload{TeamId: assignmentCustom.TeamId, ProjectId: assignmentCustom.ProjectId, ProjectRole: assignmentCustom.ProjectRole}).Times(1).Return(assignmentCustom, nil) + mock.EXPECT().TeamProjectAssignments(assignmentCustom.ProjectId).Times(3).Return([]client.TeamProjectAssignment{assignmentCustom}, nil) + mock.EXPECT().TeamProjectAssignmentDelete(assignmentCustom.Id).Times(1).Return(nil) + }) + }) + + t.Run("Import role - not found", func(t *testing.T) { + testCase := resource.TestCase{ + Steps: []resource.TestStep{ + { + Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{ + "team_id": assignment.TeamId, + "project_id": assignment.ProjectId, + "role": assignment.ProjectRole, + }), + }, + { + ResourceName: resourceNameImport, + ImportState: true, + ImportStateId: assignment.TeamId + "_" + assignment.ProjectId, + ImportStateVerify: true, + ExpectError: regexp.MustCompile("not found"), + }, + }, + } + + runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) { + mock.EXPECT().TeamProjectAssignmentCreateOrUpdate(client.TeamProjectAssignmentPayload{TeamId: assignment.TeamId, ProjectId: assignment.ProjectId, ProjectRole: assignment.ProjectRole}).Times(1).Return(assignment, nil) + mock.EXPECT().TeamProjectAssignments(assignment.ProjectId).Times(1).Return([]client.TeamProjectAssignment{assignment}, nil) + mock.EXPECT().TeamProjectAssignments(assignment.ProjectId).Times(1).Return([]client.TeamProjectAssignment{}, nil) + mock.EXPECT().TeamProjectAssignmentDelete(assignment.Id).Times(1) + }) + }) } diff --git a/examples/resources/env0_team_project_assignment/import.sh b/examples/resources/env0_team_project_assignment/import.sh new file mode 100644 index 00000000..b56805e0 --- /dev/null +++ b/examples/resources/env0_team_project_assignment/import.sh @@ -0,0 +1 @@ +terraform import env0_team_project_assignment.example team-id_project-id \ No newline at end of file