From f1323e8633c6f95c5a0c5f627607fc8bfbcb4396 Mon Sep 17 00:00:00 2001 From: jeffrey Date: Thu, 13 Feb 2025 10:39:12 -0600 Subject: [PATCH] Populate team_id for vercel_integration_project_access when using the team from the provider. (#270) --- client/integrations.go | 41 ++++++++++---- vercel/resource_integration_project_access.go | 53 ++++--------------- ...esource_integration_project_access_test.go | 48 +++++++++++++++-- 3 files changed, 86 insertions(+), 56 deletions(-) diff --git a/client/integrations.go b/client/integrations.go index 89c9c03..2fc3053 100644 --- a/client/integrations.go +++ b/client/integrations.go @@ -7,7 +7,12 @@ import ( "github.com/hashicorp/terraform-plugin-log/tflog" ) -func (c *Client) GetIntegrationProjectAccess(ctx context.Context, integrationID, projectID, teamID string) (bool, error) { +type IntegrationProjectAccess struct { + Allowed bool + TeamID string +} + +func (c *Client) GetIntegrationProjectAccess(ctx context.Context, integrationID, projectID, teamID string) (IntegrationProjectAccess, error) { url := fmt.Sprintf("%s/v1/integrations/configuration/%s/project/%s", c.baseURL, integrationID, projectID) if c.teamID(teamID) != "" { url = fmt.Sprintf("%s?teamId=%s", url, c.teamID(teamID)) @@ -28,12 +33,18 @@ func (c *Client) GetIntegrationProjectAccess(ctx context.Context, integrationID, url: url, body: "", }, &e); err != nil { - return false, err + return IntegrationProjectAccess{ + Allowed: false, + TeamID: c.teamID(teamID), + }, err } - return e.Allowed, nil + return IntegrationProjectAccess{ + Allowed: e.Allowed, + TeamID: c.teamID(teamID), + }, nil } -func (c *Client) GrantIntegrationProjectAccess(ctx context.Context, integrationID, projectID, teamID string) (bool, error) { +func (c *Client) GrantIntegrationProjectAccess(ctx context.Context, integrationID, projectID, teamID string) (IntegrationProjectAccess, error) { url := fmt.Sprintf("%s/v1/integrations/configuration/%s/project/%s", c.baseURL, integrationID, projectID) if c.teamID(teamID) != "" { url = fmt.Sprintf("%s?teamId=%s", url, c.teamID(teamID)) @@ -54,12 +65,18 @@ func (c *Client) GrantIntegrationProjectAccess(ctx context.Context, integrationI url: url, body: `{ "allowed": true }`, }, &e); err != nil { - return false, err + return IntegrationProjectAccess{ + Allowed: false, + TeamID: c.teamID(teamID), + }, err } - return true, nil + return IntegrationProjectAccess{ + Allowed: true, + TeamID: c.teamID(teamID), + }, nil } -func (c *Client) RevokeIntegrationProjectAccess(ctx context.Context, integrationID, projectID, teamID string) (bool, error) { +func (c *Client) RevokeIntegrationProjectAccess(ctx context.Context, integrationID, projectID, teamID string) (IntegrationProjectAccess, error) { url := fmt.Sprintf("%s/v1/integrations/configuration/%s/project/%s", c.baseURL, integrationID, projectID) if c.teamID(teamID) != "" { url = fmt.Sprintf("%s?teamId=%s", url, c.teamID(teamID)) @@ -80,7 +97,13 @@ func (c *Client) RevokeIntegrationProjectAccess(ctx context.Context, integration url: url, body: `{ "allowed": false }`, }, &e); err != nil { - return false, err + return IntegrationProjectAccess{ + Allowed: false, + TeamID: c.teamID(teamID), + }, err } - return false, nil + return IntegrationProjectAccess{ + Allowed: false, + TeamID: c.teamID(teamID), + }, nil } diff --git a/vercel/resource_integration_project_access.go b/vercel/resource_integration_project_access.go index d9a75a2..c66fcb7 100644 --- a/vercel/resource_integration_project_access.go +++ b/vercel/resource_integration_project_access.go @@ -88,7 +88,7 @@ func (r *integrationProjectAccessResource) Create(ctx context.Context, req resou return } - _, err := r.client.GrantIntegrationProjectAccess(ctx, plan.IntegrationID.ValueString(), plan.ProjectID.ValueString(), plan.TeamID.ValueString()) + ipa, err := r.client.GrantIntegrationProjectAccess(ctx, plan.IntegrationID.ValueString(), plan.ProjectID.ValueString(), plan.TeamID.ValueString()) if err != nil { resp.Diagnostics.AddError( "Error granting integration project access", @@ -98,7 +98,7 @@ func (r *integrationProjectAccessResource) Create(ctx context.Context, req resou } result := IntegrationProjectAccess{ - TeamID: plan.TeamID, + TeamID: types.StringValue(ipa.TeamID), IntegrationID: plan.IntegrationID, ProjectID: plan.ProjectID, } @@ -124,7 +124,7 @@ func (r *integrationProjectAccessResource) Read(ctx context.Context, req resourc return } - allowed, err := r.client.GetIntegrationProjectAccess(ctx, state.IntegrationID.ValueString(), state.ProjectID.ValueString(), state.TeamID.ValueString()) + ipa, err := r.client.GetIntegrationProjectAccess(ctx, state.IntegrationID.ValueString(), state.ProjectID.ValueString(), state.TeamID.ValueString()) if err != nil { resp.Diagnostics.AddError( "Error granting integration project access", @@ -134,7 +134,7 @@ func (r *integrationProjectAccessResource) Read(ctx context.Context, req resourc } result := IntegrationProjectAccess{ - TeamID: state.TeamID, + TeamID: types.StringValue(ipa.TeamID), IntegrationID: state.IntegrationID, ProjectID: state.ProjectID, } @@ -142,10 +142,10 @@ func (r *integrationProjectAccessResource) Read(ctx context.Context, req resourc "team_id": result.TeamID.ValueString(), "integration_id": result.IntegrationID.ValueString(), "project_id": result.ProjectID.ValueString(), - "allowed": allowed, + "allowed": ipa.Allowed, }) - if allowed { + if ipa.Allowed { diags = resp.State.Set(ctx, result) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { @@ -157,40 +157,7 @@ func (r *integrationProjectAccessResource) Read(ctx context.Context, req resourc } func (r *integrationProjectAccessResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { - var plan IntegrationProjectAccess - diags := req.Plan.Get(ctx, &plan) - resp.Diagnostics.Append(diags...) - if resp.Diagnostics.HasError() { - return - } - - allowed, err := r.client.GrantIntegrationProjectAccess(ctx, plan.IntegrationID.ValueString(), plan.ProjectID.ValueString(), plan.TeamID.ValueString()) - if err != nil { - resp.Diagnostics.AddError( - "Error granting integration project access", - "Could not grant integration project access, unexpected error: "+err.Error(), - ) - return - } - - result := IntegrationProjectAccess{ - TeamID: plan.TeamID, - IntegrationID: plan.IntegrationID, - ProjectID: plan.ProjectID, - } - - tflog.Info(ctx, "granted integration project access", map[string]interface{}{ - "team_id": result.TeamID.ValueString(), - "integration_id": result.IntegrationID.ValueString(), - "project_id": result.ProjectID.ValueString(), - "allowed": allowed, - }) - - diags = resp.State.Set(ctx, result) - resp.Diagnostics.Append(diags...) - if resp.Diagnostics.HasError() { - return - } + resp.Diagnostics.AddError("Access should always be recreated", "Something incorrectly caused an Update, this should always be recreated instead of updated.") } func (r *integrationProjectAccessResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { @@ -201,7 +168,7 @@ func (r *integrationProjectAccessResource) Delete(ctx context.Context, req resou return } - allowed, err := r.client.RevokeIntegrationProjectAccess(ctx, plan.IntegrationID.ValueString(), plan.ProjectID.ValueString(), plan.TeamID.ValueString()) + ipa, err := r.client.RevokeIntegrationProjectAccess(ctx, plan.IntegrationID.ValueString(), plan.ProjectID.ValueString(), plan.TeamID.ValueString()) if err != nil { resp.Diagnostics.AddError( "Error revoking integration project access", @@ -211,7 +178,7 @@ func (r *integrationProjectAccessResource) Delete(ctx context.Context, req resou } result := IntegrationProjectAccess{ - TeamID: plan.TeamID, + TeamID: types.StringValue(ipa.TeamID), IntegrationID: plan.IntegrationID, ProjectID: plan.ProjectID, } @@ -220,6 +187,6 @@ func (r *integrationProjectAccessResource) Delete(ctx context.Context, req resou "team_id": result.TeamID.ValueString(), "integration_id": result.IntegrationID.ValueString(), "project_id": result.ProjectID.ValueString(), - "allowed": allowed, + "allowed": ipa.Allowed, }) } diff --git a/vercel/resource_integration_project_access_test.go b/vercel/resource_integration_project_access_test.go index 70e7683..c48682e 100644 --- a/vercel/resource_integration_project_access_test.go +++ b/vercel/resource_integration_project_access_test.go @@ -17,11 +17,11 @@ func testCheckIntegrationProjectAccessDestroyed(n, teamID string) resource.TestC return fmt.Errorf("not found: %s", n) } - allowed, err := testClient().GetIntegrationProjectAccess(context.TODO(), rs.Primary.Attributes["integration_id"], rs.Primary.Attributes["project_id"], teamID) + ipa, err := testClient().GetIntegrationProjectAccess(context.TODO(), rs.Primary.Attributes["integration_id"], rs.Primary.Attributes["project_id"], teamID) if err != nil { return err } - if allowed { + if ipa.Allowed { return fmt.Errorf("expected project to not allow access to integration") } @@ -36,11 +36,11 @@ func testCheckIntegrationProjectAccessExists(n, teamID string) resource.TestChec return fmt.Errorf("not found: %s", n) } - allowed, err := testClient().GetIntegrationProjectAccess(context.TODO(), rs.Primary.Attributes["integration_id"], rs.Primary.Attributes["project_id"], teamID) + ipa, err := testClient().GetIntegrationProjectAccess(context.TODO(), rs.Primary.Attributes["integration_id"], rs.Primary.Attributes["project_id"], teamID) if err != nil { return err } - if !allowed { + if !ipa.Allowed { return fmt.Errorf("expected project to allow access to integration") } @@ -59,6 +59,25 @@ func TestAcc_IntegrationProjectAccess(t *testing.T) { Config: testAccIntegrationProjectAccess(name, teamIDConfig(), testExistingIntegration()), Check: resource.ComposeAggregateTestCheckFunc( testCheckIntegrationProjectAccessExists("vercel_integration_project_access.test_integration_access", testTeam()), + resource.TestCheckResourceAttr("vercel_integration_project_access.test_integration_access", "team_id", testTeam()), + ), + }, + }, + }) +} + +func TestAcc_IntegrationProjectAccessWithoutExplicitTeam(t *testing.T) { + name := acctest.RandString(16) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + CheckDestroy: testCheckIntegrationProjectAccessDestroyed("vercel_integration_project_access.test_integration_access", testTeam()), + Steps: []resource.TestStep{ + { + Config: testAccIntegrationProjectAccessUsingProvider(name, testTeam(), testExistingIntegration()), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckIntegrationProjectAccessExists("vercel_integration_project_access.test_integration_access", testTeam()), + resource.TestCheckResourceAttr("vercel_integration_project_access.test_integration_access", "team_id", testTeam()), ), }, }, @@ -81,5 +100,26 @@ resource "vercel_integration_project_access" "test_integration_access" { project_id = vercel_project.test.id %[2]s } +`, name, team, integration, testTeam()) +} + +func testAccIntegrationProjectAccessUsingProvider(name, team, integration string) string { + //lintignore:AT004 + return fmt.Sprintf(` +provider "vercel" { + team = "%[2]s" +} + +data "vercel_endpoint_verification" "test" { +} + +resource "vercel_project" "test" { + name = "test-acc-%[1]s" +} + +resource "vercel_integration_project_access" "test_integration_access" { + integration_id = "%[3]s" + project_id = vercel_project.test.id +} `, name, team, integration) }