From d2efd0c9dcd4948d986358fdca31da9752aefb72 Mon Sep 17 00:00:00 2001 From: Tomer Heber Date: Wed, 27 Mar 2024 08:14:46 -0500 Subject: [PATCH] Feat: Organization Role assignments for Team (#813) * Feat: Organization Role assignments for Team * wording changes * updated example --- client/api_client.go | 3 + client/api_client_mock.go | 44 ++++ client/team_organization_assignment.go | 59 +++++ client/team_organization_assignment_test.go | 142 ++++++++++++ env0/provider.go | 1 + env0/resource_team_organization_assignment.go | 112 ++++++++++ ...ource_team_organization_assignment_test.go | 205 ++++++++++++++++++ .../resource.tf | 16 ++ tests/integration/009_team/main.tf | 22 +- 9 files changed, 603 insertions(+), 1 deletion(-) create mode 100644 client/team_organization_assignment.go create mode 100644 client/team_organization_assignment_test.go create mode 100644 env0/resource_team_organization_assignment.go create mode 100644 env0/resource_team_organization_assignment_test.go create mode 100644 examples/resources/env0_team_organization_assignment/resource.tf diff --git a/client/api_client.go b/client/api_client.go index 0b0dedb5..45695e7a 100644 --- a/client/api_client.go +++ b/client/api_client.go @@ -141,6 +141,9 @@ type ApiClientInterface interface { AssignTeamRoleToEnvironment(payload *AssignTeamRoleToEnvironmentPayload) (*TeamRoleEnvironmentAssignment, error) RemoveTeamRoleFromEnvironment(environmentId string, teamId string) error TeamRoleEnvironmentAssignments(environmentId string) ([]TeamRoleEnvironmentAssignment, error) + AssignOrganizationRoleToTeam(payload *AssignOrganizationRoleToTeamPayload) (*OrganizationRoleTeamAssignment, error) + RemoveOrganizationRoleFromTeam(teamId string) error + OrganizationRoleTeamAssignments() ([]OrganizationRoleTeamAssignment, error) ApprovalPolicies(name string) ([]ApprovalPolicy, error) ApprovalPolicyAssign(assignment *ApprovalPolicyAssignment) (*ApprovalPolicyAssignment, error) ApprovalPolicyUnassign(scope string, scopeId string) error diff --git a/client/api_client_mock.go b/client/api_client_mock.go index 7ac32f6a..9f6e8ad2 100644 --- a/client/api_client_mock.go +++ b/client/api_client_mock.go @@ -245,6 +245,21 @@ func (mr *MockApiClientInterfaceMockRecorder) AssignCostCredentialsToProject(arg return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AssignCostCredentialsToProject", reflect.TypeOf((*MockApiClientInterface)(nil).AssignCostCredentialsToProject), arg0, arg1) } +// AssignOrganizationRoleToTeam mocks base method. +func (m *MockApiClientInterface) AssignOrganizationRoleToTeam(arg0 *AssignOrganizationRoleToTeamPayload) (*OrganizationRoleTeamAssignment, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AssignOrganizationRoleToTeam", arg0) + ret0, _ := ret[0].(*OrganizationRoleTeamAssignment) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// AssignOrganizationRoleToTeam indicates an expected call of AssignOrganizationRoleToTeam. +func (mr *MockApiClientInterfaceMockRecorder) AssignOrganizationRoleToTeam(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AssignOrganizationRoleToTeam", reflect.TypeOf((*MockApiClientInterface)(nil).AssignOrganizationRoleToTeam), arg0) +} + // AssignTeamRoleToEnvironment mocks base method. func (m *MockApiClientInterface) AssignTeamRoleToEnvironment(arg0 *AssignTeamRoleToEnvironmentPayload) (*TeamRoleEnvironmentAssignment, error) { m.ctrl.T.Helper() @@ -1192,6 +1207,21 @@ func (mr *MockApiClientInterfaceMockRecorder) OrganizationPolicyUpdate(arg0 any) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OrganizationPolicyUpdate", reflect.TypeOf((*MockApiClientInterface)(nil).OrganizationPolicyUpdate), arg0) } +// OrganizationRoleTeamAssignments mocks base method. +func (m *MockApiClientInterface) OrganizationRoleTeamAssignments() ([]OrganizationRoleTeamAssignment, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "OrganizationRoleTeamAssignments") + ret0, _ := ret[0].([]OrganizationRoleTeamAssignment) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// OrganizationRoleTeamAssignments indicates an expected call of OrganizationRoleTeamAssignments. +func (mr *MockApiClientInterfaceMockRecorder) OrganizationRoleTeamAssignments() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OrganizationRoleTeamAssignments", reflect.TypeOf((*MockApiClientInterface)(nil).OrganizationRoleTeamAssignments)) +} + // OrganizationUserUpdateRole mocks base method. func (m *MockApiClientInterface) OrganizationUserUpdateRole(arg0, arg1 string) error { m.ctrl.T.Helper() @@ -1559,6 +1589,20 @@ func (mr *MockApiClientInterfaceMockRecorder) RemoveCostCredentialsFromProject(a return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveCostCredentialsFromProject", reflect.TypeOf((*MockApiClientInterface)(nil).RemoveCostCredentialsFromProject), arg0, arg1) } +// RemoveOrganizationRoleFromTeam mocks base method. +func (m *MockApiClientInterface) RemoveOrganizationRoleFromTeam(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RemoveOrganizationRoleFromTeam", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// RemoveOrganizationRoleFromTeam indicates an expected call of RemoveOrganizationRoleFromTeam. +func (mr *MockApiClientInterfaceMockRecorder) RemoveOrganizationRoleFromTeam(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveOrganizationRoleFromTeam", reflect.TypeOf((*MockApiClientInterface)(nil).RemoveOrganizationRoleFromTeam), arg0) +} + // RemoveTeamRoleFromEnvironment mocks base method. func (m *MockApiClientInterface) RemoveTeamRoleFromEnvironment(arg0, arg1 string) error { m.ctrl.T.Helper() diff --git a/client/team_organization_assignment.go b/client/team_organization_assignment.go new file mode 100644 index 00000000..1ab62252 --- /dev/null +++ b/client/team_organization_assignment.go @@ -0,0 +1,59 @@ +package client + +type AssignOrganizationRoleToTeamPayload struct { + TeamId string `json:"teamId"` + Role string `json:"role" tfschema:"role_id"` +} + +type OrganizationRoleTeamAssignment struct { + TeamId string `json:"teamId"` + Role string `json:"role" tfschema:"role_id"` + Id string `json:"id"` +} + +func (client *ApiClient) AssignOrganizationRoleToTeam(payload *AssignOrganizationRoleToTeamPayload) (*OrganizationRoleTeamAssignment, error) { + var result OrganizationRoleTeamAssignment + + organizationId, err := client.OrganizationId() + if err != nil { + return nil, err + } + + payloadWithOrganizationId := struct { + *AssignOrganizationRoleToTeamPayload + OrganizationId string `json:"organizationId"` + }{ + payload, + organizationId, + } + + if err := client.http.Put("/roles/assignments/teams", payloadWithOrganizationId, &result); err != nil { + return nil, err + } + + return &result, nil +} + +func (client *ApiClient) RemoveOrganizationRoleFromTeam(teamId string) error { + organizationId, err := client.OrganizationId() + if err != nil { + return err + } + + return client.http.Delete("/roles/assignments/teams", map[string]string{"organizationId": organizationId, "teamId": teamId}) +} + +func (client *ApiClient) OrganizationRoleTeamAssignments() ([]OrganizationRoleTeamAssignment, error) { + organizationId, err := client.OrganizationId() + if err != nil { + return nil, err + } + + var result []OrganizationRoleTeamAssignment + + if err := client.http.Get("/roles/assignments/teams", map[string]string{"organizationId": organizationId}, &result); err != nil { + return nil, err + } + + return result, nil +} diff --git a/client/team_organization_assignment_test.go b/client/team_organization_assignment_test.go new file mode 100644 index 00000000..6795c626 --- /dev/null +++ b/client/team_organization_assignment_test.go @@ -0,0 +1,142 @@ +package client_test + +import ( + "errors" + + . "github.com/env0/terraform-provider-env0/client" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "go.uber.org/mock/gomock" +) + +var _ = Describe("Team Orgnization Assignment", func() { + organizationId := "organizationId" + teamId := "teamId" + + assignPayload := &AssignOrganizationRoleToTeamPayload{ + TeamId: teamId, + Role: "role1", + } + + assignPayloadWithOrganizationId := struct { + *AssignOrganizationRoleToTeamPayload + OrganizationId string `json:"organizationId"` + }{ + assignPayload, + organizationId, + } + + expectedResponse := &OrganizationRoleTeamAssignment{ + Id: "id", + } + + errorMock := errors.New("error") + + Describe("AssignTeamToOrganization", func() { + + Describe("Successful", func() { + var actualResult *OrganizationRoleTeamAssignment + var err error + + BeforeEach(func() { + mockOrganizationIdCall(organizationId).Times(1) + httpCall = mockHttpClient.EXPECT(). + Put("/roles/assignments/teams", assignPayloadWithOrganizationId, gomock.Any()). + Do(func(path string, request interface{}, response *OrganizationRoleTeamAssignment) { + *response = *expectedResponse + }).Times(1) + actualResult, err = apiClient.AssignOrganizationRoleToTeam(assignPayload) + + }) + + It("Should send POST request with params", func() {}) + + It("should return the PUT result", func() { + Expect(*actualResult).To(Equal(*expectedResponse)) + }) + + It("Should not return error", func() { + Expect(err).To(BeNil()) + }) + }) + + Describe("Failure", func() { + var actualResult *OrganizationRoleTeamAssignment + var err error + + BeforeEach(func() { + mockOrganizationIdCall(organizationId).Times(1) + httpCall = mockHttpClient.EXPECT(). + Put("/roles/assignments/teams", gomock.Any(), gomock.Any()).Return(errorMock).Times(1) + actualResult, err = apiClient.AssignOrganizationRoleToTeam(assignPayload) + }) + + It("Should fail if API call fails", func() { + Expect(err).To(Equal(errorMock)) + }) + + It("Should not return results", func() { + Expect(actualResult).To(BeNil()) + }) + }) + }) + + Describe("RemoveTeamFromOrganization", func() { + BeforeEach(func() { + mockOrganizationIdCall(organizationId).Times(1) + httpCall = mockHttpClient.EXPECT().Delete("/roles/assignments/teams", map[string]string{"organizationId": organizationId, "teamId": teamId}).Times(1) + apiClient.RemoveOrganizationRoleFromTeam(teamId) + }) + + It("Should send DELETE request with assignment id", func() {}) + }) + + Describe("TeamOrganizationAssignments", func() { + + Describe("Successful", func() { + var actualResult []OrganizationRoleTeamAssignment + var err error + + BeforeEach(func() { + mockOrganizationIdCall(organizationId).Times(1) + httpCall = mockHttpClient.EXPECT(). + Get("/roles/assignments/teams", map[string]string{"organizationId": organizationId}, gomock.Any()). + Do(func(path string, request interface{}, response *[]OrganizationRoleTeamAssignment) { + *response = []OrganizationRoleTeamAssignment{*expectedResponse} + }).Times(1) + actualResult, err = apiClient.OrganizationRoleTeamAssignments() + + }) + + It("Should send GET request with params", func() {}) + + It("should return the GET result", func() { + Expect(actualResult).To(Equal([]OrganizationRoleTeamAssignment{*expectedResponse})) + }) + + It("Should not return error", func() { + Expect(err).To(BeNil()) + }) + }) + + Describe("Failure", func() { + var actualResult []OrganizationRoleTeamAssignment + var err error + + BeforeEach(func() { + mockOrganizationIdCall(organizationId).Times(1) + httpCall = mockHttpClient.EXPECT(). + Get("/roles/assignments/teams", map[string]string{"organizationId": organizationId}, gomock.Any()).Return(errorMock).Times(1) + actualResult, err = apiClient.OrganizationRoleTeamAssignments() + }) + + It("Should fail if API call fails", func() { + Expect(err).To(Equal(errorMock)) + }) + + It("Should not return results", func() { + Expect(actualResult).To(BeNil()) + }) + }) + }) +}) diff --git a/env0/provider.go b/env0/provider.go index 9777b31c..f3783466 100644 --- a/env0/provider.go +++ b/env0/provider.go @@ -143,6 +143,7 @@ func Provider(version string) plugin.ProviderFunc { "env0_provider": resourceProvider(), "env0_user_environment_assignment": resourceUserEnvironmentAssignment(), "env0_team_environment_assignment": resourceTeamEnvironmentAssignment(), + "env0_team_organization_assignment": resourceTeamOrganizationAssignment(), "env0_approval_policy": resourceApprovalPolicy(), "env0_approval_policy_assignment": resourceApprovalPolicyAssignment(), "env0_project_budget": resourceProjectBudget(), diff --git a/env0/resource_team_organization_assignment.go b/env0/resource_team_organization_assignment.go new file mode 100644 index 00000000..513523c2 --- /dev/null +++ b/env0/resource_team_organization_assignment.go @@ -0,0 +1,112 @@ +package env0 + +import ( + "context" + + "github.com/env0/terraform-provider-env0/client" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func resourceTeamOrganizationAssignment() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceTeamOrganizationAssignmentCreate, + UpdateContext: resourceTeamOrganizationAssignmentUpdate, + ReadContext: resourceTeamOrganizationAssignmentRead, + DeleteContext: resourceTeamOrganizationAssignmentDelete, + + Description: "assigns an organization role to a team", + + Schema: map[string]*schema.Schema{ + "team_id": { + Type: schema.TypeString, + Description: "id of the team", + Required: true, + ForceNew: true, + }, + "role_id": { + Type: schema.TypeString, + Description: "id of the assigned role", + Required: true, + ValidateDiagFunc: ValidateNotEmptyString, + }, + }, + } +} + +func resourceTeamOrganizationAssignmentCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + api_client := meta.(client.ApiClientInterface) + + var newAssignment client.AssignOrganizationRoleToTeamPayload + if err := readResourceData(&newAssignment, d); err != nil { + return diag.Errorf("schema resource data deserialization failed: %v", err) + } + + assignment, err := api_client.AssignOrganizationRoleToTeam(&newAssignment) + if err != nil { + return diag.Errorf("could not create assignment: %v", err) + } + + d.SetId(assignment.Id) + + return nil +} + +func resourceTeamOrganizationAssignmentRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + api_client := meta.(client.ApiClientInterface) + + assignments, err := api_client.OrganizationRoleTeamAssignments() + if err != nil { + return diag.Errorf("could not get assignments: %v", err) + } + + id := d.Id() + + for _, assignment := range assignments { + if assignment.Id == id { + if err := writeResourceData(&assignment, d); err != nil { + return diag.Errorf("schema resource data serialization failed: %v", err) + } + + d.Set("role_id", assignment.Role) + + return nil + } + } + + tflog.Warn(ctx, "Drift Detected: Terraform will remove id from state", map[string]interface{}{"id": d.Id()}) + d.SetId("") + + return nil +} + +func resourceTeamOrganizationAssignmentUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + api_client := meta.(client.ApiClientInterface) + + var payload client.AssignOrganizationRoleToTeamPayload + if err := readResourceData(&payload, d); err != nil { + return diag.Errorf("schema resource data deserialization failed: %v", err) + } + + assignment, err := api_client.AssignOrganizationRoleToTeam(&payload) + if err != nil { + return diag.Errorf("could not update assignment: %v", err) + } + + d.SetId(assignment.Id) + + return nil +} + +func resourceTeamOrganizationAssignmentDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + api_client := meta.(client.ApiClientInterface) + + teamId := d.Get("team_id").(string) + + if err := api_client.RemoveOrganizationRoleFromTeam(teamId); err != nil { + return diag.Errorf("could not delete assignment: %v", err) + } + + return nil +} diff --git a/env0/resource_team_organization_assignment_test.go b/env0/resource_team_organization_assignment_test.go new file mode 100644 index 00000000..63dce5ed --- /dev/null +++ b/env0/resource_team_organization_assignment_test.go @@ -0,0 +1,205 @@ +package env0 + +import ( + "errors" + "regexp" + "testing" + + "github.com/env0/terraform-provider-env0/client" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "go.uber.org/mock/gomock" +) + +func TestUnitTeamOrganizationAssignmentResource(t *testing.T) { + teamId := "tid" + + id := "id" + role := "rid1" + updatedRole := "rid2" + + createPayload := client.AssignOrganizationRoleToTeamPayload{ + TeamId: teamId, + Role: role, + } + + updatePayload := client.AssignOrganizationRoleToTeamPayload{ + TeamId: teamId, + Role: updatedRole, + } + + createResponse := client.OrganizationRoleTeamAssignment{ + Id: id, + TeamId: teamId, + Role: role, + } + + updateResponse := client.OrganizationRoleTeamAssignment{ + Id: id, + TeamId: teamId, + Role: updatedRole, + } + + otherResponse := client.OrganizationRoleTeamAssignment{ + Id: "id2", + TeamId: "teamId2", + Role: "dasdasd", + } + + resourceType := "env0_team_organization_assignment" + resourceName := "test" + accessor := resourceAccessor(resourceType, resourceName) + + t.Run("Create assignment and update role", func(t *testing.T) { + testCase := resource.TestCase{ + Steps: []resource.TestStep{ + { + Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{ + "team_id": teamId, + "role_id": role, + }), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(accessor, "id", id), + resource.TestCheckResourceAttr(accessor, "team_id", teamId), + resource.TestCheckResourceAttr(accessor, "role_id", role), + ), + }, + { + Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{ + "team_id": teamId, + "role_id": updatedRole, + }), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(accessor, "id", id), + resource.TestCheckResourceAttr(accessor, "team_id", teamId), + resource.TestCheckResourceAttr(accessor, "role_id", updatedRole), + ), + }, + }, + } + + runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) { + gomock.InOrder( + mock.EXPECT().AssignOrganizationRoleToTeam(&createPayload).Times(1).Return(&createResponse, nil), + mock.EXPECT().OrganizationRoleTeamAssignments().Times(2).Return([]client.OrganizationRoleTeamAssignment{otherResponse, createResponse}, nil), + mock.EXPECT().AssignOrganizationRoleToTeam(&updatePayload).Times(1).Return(&updateResponse, nil), + mock.EXPECT().OrganizationRoleTeamAssignments().Times(1).Return([]client.OrganizationRoleTeamAssignment{otherResponse, updateResponse}, nil), + mock.EXPECT().RemoveOrganizationRoleFromTeam(teamId).Times(1).Return(nil), + ) + }) + }) + + t.Run("Create Assignment - drift detected", func(t *testing.T) { + testCase := resource.TestCase{ + Steps: []resource.TestStep{ + { + Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{ + "team_id": teamId, + "role_id": role, + }), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(accessor, "id", id), + resource.TestCheckResourceAttr(accessor, "team_id", teamId), + resource.TestCheckResourceAttr(accessor, "role_id", role), + ), + ExpectNonEmptyPlan: true, + }, + { + Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{ + "team_id": teamId, + "role_id": role, + }), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(accessor, "id", id), + resource.TestCheckResourceAttr(accessor, "team_id", teamId), + resource.TestCheckResourceAttr(accessor, "role_id", role), + ), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + }, + } + + runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) { + gomock.InOrder( + mock.EXPECT().AssignOrganizationRoleToTeam(&createPayload).Times(1).Return(&createResponse, nil), + mock.EXPECT().OrganizationRoleTeamAssignments().Times(1).Return([]client.OrganizationRoleTeamAssignment{otherResponse}, nil), + ) + }) + }) + + t.Run("Create Assignment - failed to create", func(t *testing.T) { + testCase := resource.TestCase{ + Steps: []resource.TestStep{ + { + Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{ + "team_id": teamId, + "role_id": role, + }), + ExpectError: regexp.MustCompile("could not create assignment: error"), + }, + }, + } + + runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) { + gomock.InOrder( + mock.EXPECT().AssignOrganizationRoleToTeam(&createPayload).Times(1).Return(nil, errors.New("error")), + ) + }) + }) + + t.Run("Create Assignment - failed to list assignments", func(t *testing.T) { + testCase := resource.TestCase{ + Steps: []resource.TestStep{ + { + Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{ + "team_id": teamId, + "role_id": role, + }), + ExpectError: regexp.MustCompile("could not get assignments: error"), + }, + }, + } + + runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) { + gomock.InOrder( + mock.EXPECT().AssignOrganizationRoleToTeam(&createPayload).Times(1).Return(&createResponse, nil), + mock.EXPECT().OrganizationRoleTeamAssignments().Times(1).Return(nil, errors.New("error")), + mock.EXPECT().RemoveOrganizationRoleFromTeam(teamId).Times(1).Return(nil), + ) + }) + }) + + t.Run("Create Assignment and update role - failed to update role", func(t *testing.T) { + testCase := resource.TestCase{ + Steps: []resource.TestStep{ + { + Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{ + "team_id": teamId, + "role_id": role, + }), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(accessor, "id", id), + resource.TestCheckResourceAttr(accessor, "team_id", teamId), + resource.TestCheckResourceAttr(accessor, "role_id", role), + ), + }, + { + Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{ + "team_id": teamId, + "role_id": updatedRole, + }), + ExpectError: regexp.MustCompile("could not update assignment: error"), + }, + }, + } + + runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) { + gomock.InOrder( + mock.EXPECT().AssignOrganizationRoleToTeam(&createPayload).Times(1).Return(&createResponse, nil), + mock.EXPECT().OrganizationRoleTeamAssignments().Times(2).Return([]client.OrganizationRoleTeamAssignment{otherResponse, createResponse}, nil), + mock.EXPECT().AssignOrganizationRoleToTeam(&updatePayload).Times(1).Return(nil, errors.New("error")), + mock.EXPECT().RemoveOrganizationRoleFromTeam(teamId).Times(1).Return(nil), + ) + }) + }) +} diff --git a/examples/resources/env0_team_organization_assignment/resource.tf b/examples/resources/env0_team_organization_assignment/resource.tf new file mode 100644 index 00000000..ea225cd4 --- /dev/null +++ b/examples/resources/env0_team_organization_assignment/resource.tf @@ -0,0 +1,16 @@ +resource "env0_team" "team" { + name = "team" +} + +resource "env0_custom_role" "custom_role" { + name = "custom-role-sample" + permissions = [ + "VIEW_ORGANIZATION", + "VIEW_DASHBOARD" + ] +} + +resource "env0_team_organization_assignment" "assignment" { + team_id = env0_team.team.id + role_id = env0_custom_role.custom_role.id +} diff --git a/tests/integration/009_team/main.tf b/tests/integration/009_team/main.tf index 532ad369..374c62c2 100644 --- a/tests/integration/009_team/main.tf +++ b/tests/integration/009_team/main.tf @@ -22,4 +22,24 @@ output "team_resource_description" { output "team_data_description" { value = data.env0_team.team_data.description -} \ No newline at end of file +} + +resource "env0_custom_role" "custom_role1" { + name = "custom-role-${random_string.random.result}" + permissions = [ + "CREATE_PROJECT" + ] +} + +resource "env0_custom_role" "custom_role2" { + name = "custom-role-${random_string.random.result}2" + permissions = [ + "RUN_PLAN" + ] +} + +resource "env0_team_organization_assignment" "organization_role_assignment" { + team_id = env0_team.team_resource.id + role_id = var.second_run ? env0_custom_role.custom_role1.id : env0_custom_role.custom_role2.id +} +