Skip to content

Commit

Permalink
Add team data source and resource tests (those that could be added now)
Browse files Browse the repository at this point in the history
  • Loading branch information
michal-futurice committed Jul 24, 2024
1 parent 9fd535d commit 6c16175
Show file tree
Hide file tree
Showing 6 changed files with 484 additions and 27 deletions.
113 changes: 113 additions & 0 deletions internal/provider/team/team_data_source_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package team_test

import (
"fmt"
"github.com/futurice/terraform-provider-dependencytrack/internal/testutils"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"strings"
"testing"
)

func TestAccTeamDataSource_basic(t *testing.T) {
teamName := acctest.RandomWithPrefix("test-team")
teamDataSourceName := createTeamDataSourceName("test")

resource.Test(t, resource.TestCase{
PreCheck: func() { testutils.TestAccPreCheck(t) },
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccTeamDataSourceConfigBasic(testDependencyTrack, teamName),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(teamDataSourceName, "name", teamName),
),
},
},
})
}

func TestAccTeamDataSource_permissions(t *testing.T) {
teamName := acctest.RandomWithPrefix("test-team")
permissionNames := []string{"ACCESS_MANAGEMENT", "BOM_UPLOAD"}
teamDataSourceName := createTeamDataSourceName("test")

resource.Test(t, resource.TestCase{
PreCheck: func() { testutils.TestAccPreCheck(t) },
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccTeamDataSourceConfigPermissions(testDependencyTrack, teamName, permissionNames),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(teamDataSourceName, "permissions.#", "2"),
resource.TestCheckTypeSetElemAttr(teamDataSourceName, "permissions.*", "ACCESS_MANAGEMENT"),
resource.TestCheckTypeSetElemAttr(teamDataSourceName, "permissions.*", "BOM_UPLOAD"),
),
},
},
})
}

func TestAccTeamDataSource_mappedOIDCGroups(t *testing.T) {
// TODO either add the required resources or add test mappings with direct API calls to complete this test
t.Skip("Currently adding mappings is not supported")
}

func testAccTeamDataSourceConfigBasic(testDependencyTrack *testutils.TestDependencyTrack, teamName string) string {
return testDependencyTrack.AddProviderConfiguration(
fmt.Sprintf(`
resource "dependencytrack_team" "test" {
name = %[1]q
}
data "dependencytrack_team" "test" {
id = dependencytrack_team.test.id
}
`,
teamName,
),
)
}

func testAccTeamDataSourceConfigPermissions(testDependencyTrack *testutils.TestDependencyTrack, teamName string, permissionNames []string) string {
permissionResourceNames := make([]string, len(permissionNames))
permissionResources := make([]string, len(permissionNames))

for i, permissionName := range permissionNames {
permissionResourceNames[i] = fmt.Sprintf("dependencytrack_team_permission.test-%[1]s", permissionName)

permissionResources[i] = fmt.Sprintf(`
resource "dependencytrack_team_permission" "test-%[1]s" {
team_id = dependencytrack_team.test.id
name = %[1]q
}
`,
permissionName,
)
}

return testDependencyTrack.AddProviderConfiguration(
testutils.ComposeConfigs(
fmt.Sprintf(`
resource "dependencytrack_team" "test" {
name = %[1]q
}
`,
teamName,
),
testutils.ComposeConfigs(permissionResources...),
fmt.Sprintf(`
data "dependencytrack_team" "test" {
id = dependencytrack_team.test.id
depends_on = [%[1]s]
}
`,
strings.Join(permissionResourceNames, ", "),
),
),
)
}

func createTeamDataSourceName(localName string) string {
return fmt.Sprintf("data.dependencytrack_team.%s", localName)
}
84 changes: 57 additions & 27 deletions internal/provider/team/team_resource.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package team

import (
"context"
"fmt"

dtrack "github.com/futurice/dependency-track-client-go"
"github.com/google/uuid"
"github.com/futurice/terraform-provider-dependencytrack/internal/utils"
"github.com/hashicorp/terraform-plugin-framework/diag"

"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
Expand Down Expand Up @@ -81,40 +78,47 @@ func (r *TeamResource) Configure(ctx context.Context, req resource.ConfigureRequ
}

func (r *TeamResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var plan TeamResourceModel
var plan, state TeamResourceModel

resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)

if resp.Diagnostics.HasError() {
return
}

team := dtrack.Team{
Name: plan.Name.ValueString(),
dtTeam, diags := TFTeamToDTTeam(ctx, plan)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

respTeam, err := r.client.Team.Create(ctx, team)
respTeam, err := r.client.Team.Create(ctx, dtTeam)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create API key, got error: %s", err))
return
}

plan.ID = types.StringValue(respTeam.UUID.String())
plan.Name = types.StringValue(respTeam.Name)
state, diags = DTTeamToTFTeam(ctx, respTeam)
resp.Diagnostics.Append(diags...)

resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
}

func (r *TeamResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var state TeamResourceModel
var diags diag.Diagnostics

resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}

teamUUID, teamUUIDDiags := utils.ParseUUID(state.ID.ValueString())
resp.Diagnostics.Append(teamUUIDDiags...)
if resp.Diagnostics.HasError() {
return
}

respTeam, err := r.client.Team.Get(ctx, uuid.MustParse(state.ID.ValueString()))
respTeam, err := r.client.Team.Get(ctx, teamUUID)
if err != nil {
if apiErr, ok := err.(*dtrack.APIError); ok && apiErr.StatusCode == 404 {
resp.State.RemoveResource(ctx)
Expand All @@ -125,8 +129,8 @@ func (r *TeamResource) Read(ctx context.Context, req resource.ReadRequest, resp
return
}

state.ID = types.StringValue(respTeam.UUID.String())
state.Name = types.StringValue(respTeam.Name)
state, diags = DTTeamToTFTeam(ctx, respTeam)
resp.Diagnostics.Append(diags...)

resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
}
Expand All @@ -136,24 +140,24 @@ func (r *TeamResource) Update(ctx context.Context, req resource.UpdateRequest, r

resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)

if resp.Diagnostics.HasError() {
return
}

team := dtrack.Team{
Name: plan.Name.ValueString(),
UUID: uuid.MustParse(state.ID.ValueString()),
dtTeam, diags := TFTeamToDTTeam(ctx, plan)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

respTeam, err := r.client.Team.Update(ctx, team)
respTeam, err := r.client.Team.Update(ctx, dtTeam)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to update team, got error: %s", err))
return
}

state.ID = types.StringValue(respTeam.UUID.String())
state.Name = types.StringValue(respTeam.Name)
state, diags = DTTeamToTFTeam(ctx, respTeam)
resp.Diagnostics.Append(diags...)

resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
}
Expand All @@ -162,16 +166,17 @@ func (r *TeamResource) Delete(ctx context.Context, req resource.DeleteRequest, r
var state TeamResourceModel

resp.Diagnostics.Append(req.State.Get(ctx, &state)...)

if resp.Diagnostics.HasError() {
return
}

team := dtrack.Team{
UUID: uuid.MustParse(state.ID.ValueString()),
dtTeam, diags := TFTeamToDTTeam(ctx, state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

err := r.client.Team.Delete(ctx, team)
err := r.client.Team.Delete(ctx, dtTeam)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to delete team, got error: %s", err))
return
Expand All @@ -183,3 +188,28 @@ func (r *TeamResource) Delete(ctx context.Context, req resource.DeleteRequest, r
func (r *TeamResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
}

func DTTeamToTFTeam(ctx context.Context, dtTeam dtrack.Team) (TeamResourceModel, diag.Diagnostics) {
var diags diag.Diagnostics
team := TeamResourceModel{
ID: types.StringValue(dtTeam.UUID.String()),
Name: types.StringValue(dtTeam.Name),
}

return team, diags
}

func TFTeamToDTTeam(ctx context.Context, tfTeam TeamResourceModel) (dtrack.Team, diag.Diagnostics) {
var diags diag.Diagnostics
team := dtrack.Team{
Name: tfTeam.Name.ValueString(),
}

if tfTeam.ID.ValueString() != "" {
teamUUID, teamUUIDDiags := utils.ParseUUID(tfTeam.ID.ValueString())
team.UUID = teamUUID
diags.Append(teamUUIDDiags...)
}

return team, diags
}
Loading

0 comments on commit 6c16175

Please sign in to comment.