Skip to content

Commit

Permalink
Add team permission tests, fix issues in import and update
Browse files Browse the repository at this point in the history
  • Loading branch information
michal-futurice committed Jul 25, 2024
1 parent 08da040 commit 479659e
Show file tree
Hide file tree
Showing 10 changed files with 455 additions and 199 deletions.
2 changes: 1 addition & 1 deletion internal/provider/aclmapping/acl_mapping_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ func (r *ACLMappingResource) Delete(ctx context.Context, req resource.DeleteRequ
func (r *ACLMappingResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
parts := strings.Split(req.ID, "/")
if len(parts) != 2 {
resp.Diagnostics.AddError("Invalid import ID", "Expected ID in the format 'team_id/project_id'")
resp.Diagnostics.AddError("Invalid import ID", fmt.Sprintf("Expected ID in the format 'team_id/project_id', got [%s]", req.ID))
return
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ func (r *NotificationRuleProjectResource) Delete(ctx context.Context, req resour
func (r *NotificationRuleProjectResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
parts := strings.Split(req.ID, "/")
if len(parts) != 2 {
resp.Diagnostics.AddError("Invalid import ID", "Expected ID in the format 'project_id/rule_id'")
resp.Diagnostics.AddError("Invalid import ID", fmt.Sprintf("Expected ID in the format 'project_id/rule_id', got [%s]", req.ID))
return
}

Expand Down
114 changes: 19 additions & 95 deletions internal/provider/project/project_resource_test.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
package project_test

import (
"context"
"errors"
"fmt"
dtrack "github.com/futurice/dependency-track-client-go"
"github.com/futurice/terraform-provider-dependencytrack/internal/testutils"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/futurice/terraform-provider-dependencytrack/internal/testutils/projecttestutils"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
"os"
"strconv"
"testing"
Expand All @@ -34,7 +30,7 @@ func TestAccProjectResource_basic(t *testing.T) {

projectName := acctest.RandomWithPrefix("test-project")
otherProjectName := acctest.RandomWithPrefix("other-test-project")
projectResourceName := createProjectResourceName("test")
projectResourceName := projecttestutils.CreateProjectResourceName("test")

testProject := dtrack.Project{
Name: projectName,
Expand All @@ -52,7 +48,7 @@ func TestAccProjectResource_basic(t *testing.T) {
{
Config: testAccProjectConfigBasic(testDependencyTrack, projectName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckProjectExistsAndHasExpectedData(ctx, testDependencyTrack, projectResourceName, testProject),
projecttestutils.TestAccCheckProjectExistsAndHasExpectedData(ctx, testDependencyTrack, projectResourceName, testProject),
resource.TestCheckResourceAttrSet(projectResourceName, "id"),
resource.TestCheckResourceAttr(projectResourceName, "name", projectName),
resource.TestCheckResourceAttr(projectResourceName, "classifier", testProject.Classifier),
Expand All @@ -69,20 +65,20 @@ func TestAccProjectResource_basic(t *testing.T) {
{
Config: testAccProjectConfigBasic(testDependencyTrack, otherProjectName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckProjectExistsAndHasExpectedData(ctx, testDependencyTrack, projectResourceName, testUpdatedProject),
projecttestutils.TestAccCheckProjectExistsAndHasExpectedData(ctx, testDependencyTrack, projectResourceName, testUpdatedProject),
resource.TestCheckResourceAttr(projectResourceName, "name", otherProjectName),
),
},
},
CheckDestroy: testAccCheckProjectDoesNotExists(ctx, testDependencyTrack, projectResourceName),
CheckDestroy: projecttestutils.TestAccCheckProjectDoesNotExists(ctx, testDependencyTrack, projectResourceName),
})
}

func TestAccProjectResource_description(t *testing.T) {
ctx := testutils.CreateTestContext(t)

projectName := acctest.RandomWithPrefix("test-project")
projectResourceName := createProjectResourceName("test")
projectResourceName := projecttestutils.CreateProjectResourceName("test")

testProject := dtrack.Project{
Name: projectName,
Expand All @@ -101,14 +97,14 @@ func TestAccProjectResource_description(t *testing.T) {
{
Config: testAccProjectConfigDescription(testDependencyTrack, projectName, testProject.Description),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckProjectExistsAndHasExpectedData(ctx, testDependencyTrack, projectResourceName, testProject),
projecttestutils.TestAccCheckProjectExistsAndHasExpectedData(ctx, testDependencyTrack, projectResourceName, testProject),
resource.TestCheckResourceAttr(projectResourceName, "description", testProject.Description),
),
},
{
Config: testAccProjectConfigDescription(testDependencyTrack, projectName, testUpdatedProject.Description),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckProjectExistsAndHasExpectedData(ctx, testDependencyTrack, projectResourceName, testUpdatedProject),
projecttestutils.TestAccCheckProjectExistsAndHasExpectedData(ctx, testDependencyTrack, projectResourceName, testUpdatedProject),
resource.TestCheckResourceAttr(projectResourceName, "description", testUpdatedProject.Description),
),
},
Expand All @@ -120,7 +116,7 @@ func TestAccProjectResource_inactive(t *testing.T) {
ctx := testutils.CreateTestContext(t)

projectName := acctest.RandomWithPrefix("test-project")
projectResourceName := createProjectResourceName("test")
projectResourceName := projecttestutils.CreateProjectResourceName("test")

testProject := dtrack.Project{
Name: projectName,
Expand All @@ -138,14 +134,14 @@ func TestAccProjectResource_inactive(t *testing.T) {
{
Config: testAccProjectConfigActivity(testDependencyTrack, projectName, testProject.Active),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckProjectExistsAndHasExpectedData(ctx, testDependencyTrack, projectResourceName, testProject),
projecttestutils.TestAccCheckProjectExistsAndHasExpectedData(ctx, testDependencyTrack, projectResourceName, testProject),
resource.TestCheckResourceAttr(projectResourceName, "active", strconv.FormatBool(testProject.Active)),
),
},
{
Config: testAccProjectConfigActivity(testDependencyTrack, projectName, testUpdatedProject.Active),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckProjectExistsAndHasExpectedData(ctx, testDependencyTrack, projectResourceName, testUpdatedProject),
projecttestutils.TestAccCheckProjectExistsAndHasExpectedData(ctx, testDependencyTrack, projectResourceName, testUpdatedProject),
resource.TestCheckResourceAttr(projectResourceName, "active", strconv.FormatBool(testUpdatedProject.Active)),
),
},
Expand All @@ -157,7 +153,7 @@ func TestAccProjectResource_classifier(t *testing.T) {
ctx := testutils.CreateTestContext(t)

projectName := acctest.RandomWithPrefix("test-project")
projectResourceName := createProjectResourceName("test")
projectResourceName := projecttestutils.CreateProjectResourceName("test")

testProject := dtrack.Project{
Name: projectName,
Expand All @@ -175,14 +171,14 @@ func TestAccProjectResource_classifier(t *testing.T) {
{
Config: testAccProjectConfigClassifier(testDependencyTrack, testProject.Name, testProject.Classifier),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckProjectExistsAndHasExpectedData(ctx, testDependencyTrack, projectResourceName, testProject),
projecttestutils.TestAccCheckProjectExistsAndHasExpectedData(ctx, testDependencyTrack, projectResourceName, testProject),
resource.TestCheckResourceAttr(projectResourceName, "classifier", testProject.Classifier),
),
},
{
Config: testAccProjectConfigClassifier(testDependencyTrack, testProject.Name, testUpdatedProject.Classifier),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckProjectExistsAndHasExpectedData(ctx, testDependencyTrack, projectResourceName, testUpdatedProject),
projecttestutils.TestAccCheckProjectExistsAndHasExpectedData(ctx, testDependencyTrack, projectResourceName, testUpdatedProject),
resource.TestCheckResourceAttr(projectResourceName, "classifier", testUpdatedProject.Classifier),
),
},
Expand All @@ -193,9 +189,9 @@ func TestAccProjectResource_classifier(t *testing.T) {
func TestAccProjectResource_parent(t *testing.T) {
ctx := testutils.CreateTestContext(t)

projectResourceName := createProjectResourceName("test")
parentProjectResourceName := createProjectResourceName("parent")
otherParentProjectResourceName := createProjectResourceName("other_parent")
projectResourceName := projecttestutils.CreateProjectResourceName("test")
parentProjectResourceName := projecttestutils.CreateProjectResourceName("parent")
otherParentProjectResourceName := projecttestutils.CreateProjectResourceName("other_parent")

projectName := acctest.RandomWithPrefix("test-project")

Expand All @@ -218,15 +214,15 @@ func TestAccProjectResource_parent(t *testing.T) {
Config: testAccProjectConfigParent(testDependencyTrack, projectName),
Check: resource.ComposeAggregateTestCheckFunc(
testutils.TestAccCheckGetResourceID(parentProjectResourceName, &parentProjectID),
testAccCheckProjectExistsAndHasExpectedLazyData(ctx, testDependencyTrack, projectResourceName, func() dtrack.Project { return createTestProject(&parentProjectID) }),
projecttestutils.TestAccCheckProjectExistsAndHasExpectedLazyData(ctx, testDependencyTrack, projectResourceName, func() dtrack.Project { return createTestProject(&parentProjectID) }),
resource.TestCheckResourceAttrPtr(projectResourceName, "parent_id", &parentProjectID),
),
},
{
Config: testAccProjectConfigOtherParent(testDependencyTrack, projectName),
Check: resource.ComposeAggregateTestCheckFunc(
testutils.TestAccCheckGetResourceID(otherParentProjectResourceName, &otherParentProjectID),
testAccCheckProjectExistsAndHasExpectedLazyData(ctx, testDependencyTrack, projectResourceName, func() dtrack.Project { return createTestProject(&otherParentProjectID) }),
projecttestutils.TestAccCheckProjectExistsAndHasExpectedLazyData(ctx, testDependencyTrack, projectResourceName, func() dtrack.Project { return createTestProject(&otherParentProjectID) }),
resource.TestCheckResourceAttrPtr(projectResourceName, "parent_id", &otherParentProjectID),
),
},
Expand Down Expand Up @@ -349,75 +345,3 @@ resource "dependencytrack_project" "test" {
),
)
}

func testAccCheckProjectExistsAndHasExpectedData(ctx context.Context, testDependencyTrack *testutils.TestDependencyTrack, resourceName string, expectedProject dtrack.Project) resource.TestCheckFunc {
return testAccCheckProjectExistsAndHasExpectedLazyData(ctx, testDependencyTrack, resourceName, func() dtrack.Project { return expectedProject })
}

func testAccCheckProjectExistsAndHasExpectedLazyData(ctx context.Context, testDependencyTrack *testutils.TestDependencyTrack, resourceName string, expectedProjectCreator func() dtrack.Project) resource.TestCheckFunc {
return func(state *terraform.State) error {
expectedProject := expectedProjectCreator()

project, err := findProjectByResourceName(ctx, testDependencyTrack, state, resourceName)
if err != nil {
return err
}
if project == nil {
return fmt.Errorf("project for resource %s does not exist in Dependency-Track", resourceName)
}

diff := cmp.Diff(project, &expectedProject, cmpopts.IgnoreFields(dtrack.Project{}, "UUID", "Properties", "Tags", "Metrics"))
if diff != "" {
return fmt.Errorf("project for resource %s is different than expected: %s", resourceName, diff)
}

return nil
}
}

func testAccCheckProjectDoesNotExists(ctx context.Context, testDependencyTrack *testutils.TestDependencyTrack, resourceName string) resource.TestCheckFunc {
return func(state *terraform.State) error {
project, err := findProjectByResourceName(ctx, testDependencyTrack, state, resourceName)
if err != nil {
return err
}
if project != nil {
return fmt.Errorf("project for resource %s exists in Dependency-Track, even though it shouldn't: %v", resourceName, project)
}

return nil
}
}

func findProjectByResourceName(ctx context.Context, testDependencyTrack *testutils.TestDependencyTrack, state *terraform.State, resourceName string) (*dtrack.Project, error) {
projectID, err := testutils.GetResourceID(state, resourceName)
if err != nil {
return nil, err
}

project, err := findProject(ctx, testDependencyTrack, projectID)
if err != nil {
return nil, fmt.Errorf("failed to get project for resource %s: %w", resourceName, err)
}

return project, nil
}

func findProject(ctx context.Context, testDependencyTrack *testutils.TestDependencyTrack, projectID uuid.UUID) (*dtrack.Project, error) {
project, err := testDependencyTrack.Client.Project.Get(ctx, projectID)
if err != nil {
var apiErr *dtrack.APIError
ok := errors.As(err, &apiErr)
if !ok || apiErr.StatusCode != 404 {
return nil, fmt.Errorf("failed to get project from Dependency-Track: %w", err)
}

return nil, nil
}

return &project, nil
}

func createProjectResourceName(localName string) string {
return fmt.Sprintf("dependencytrack_project.%s", localName)
}
95 changes: 7 additions & 88 deletions internal/provider/team/team_resource_test.go
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
package team_test

import (
"context"
"errors"
"fmt"
"testing"

dtrack "github.com/futurice/dependency-track-client-go"
"github.com/futurice/terraform-provider-dependencytrack/internal/testutils"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/google/uuid"
"github.com/futurice/terraform-provider-dependencytrack/internal/testutils/teamtestutils"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
"testing"
)

func TestAccTeamResource_basic(t *testing.T) {
ctx := testutils.CreateTestContext(t)

teamName := acctest.RandomWithPrefix("test-team")
otherTeamName := acctest.RandomWithPrefix("other-test-team")
teamResourceName := createTeamResourceName("test")
teamResourceName := teamtestutils.CreateTeamResourceName("test")

testTeam := dtrack.Team{
Name: teamName,
Expand All @@ -36,7 +32,7 @@ func TestAccTeamResource_basic(t *testing.T) {
{
Config: testAccTeamConfigBasic(testDependencyTrack, teamName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckTeamExistsAndHasExpectedData(ctx, testDependencyTrack, teamResourceName, testTeam),
teamtestutils.TestAccCheckTeamExistsAndHasExpectedData(ctx, testDependencyTrack, teamResourceName, testTeam),
resource.TestCheckResourceAttrSet(teamResourceName, "id"),
resource.TestCheckResourceAttr(teamResourceName, "name", teamName),
),
Expand All @@ -49,12 +45,12 @@ func TestAccTeamResource_basic(t *testing.T) {
{
Config: testAccTeamConfigBasic(testDependencyTrack, otherTeamName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckTeamExistsAndHasExpectedData(ctx, testDependencyTrack, teamResourceName, testUpdatedTeam),
teamtestutils.TestAccCheckTeamExistsAndHasExpectedData(ctx, testDependencyTrack, teamResourceName, testUpdatedTeam),
resource.TestCheckResourceAttr(teamResourceName, "name", otherTeamName),
),
},
},
CheckDestroy: testAccCheckTeamDoesNotExists(ctx, testDependencyTrack, teamResourceName),
CheckDestroy: teamtestutils.TestAccCheckTeamDoesNotExists(ctx, testDependencyTrack, teamResourceName),
})
}

Expand All @@ -69,80 +65,3 @@ resource "dependencytrack_team" "test" {
),
)
}

func testAccCheckTeamExistsAndHasExpectedData(ctx context.Context, testDependencyTrack *testutils.TestDependencyTrack, resourceName string, expectedTeam dtrack.Team) resource.TestCheckFunc {
return testAccCheckTeamExistsAndHasExpectedLazyData(ctx, testDependencyTrack, resourceName, func() dtrack.Team { return expectedTeam })
}

func testAccCheckTeamExistsAndHasExpectedLazyData(ctx context.Context, testDependencyTrack *testutils.TestDependencyTrack, resourceName string, expectedTeamCreator func() dtrack.Team) resource.TestCheckFunc {
return func(state *terraform.State) error {
expectedTeam := expectedTeamCreator()

team, err := findTeamByResourceName(ctx, testDependencyTrack, state, resourceName)
if err != nil {
return err
}
if team == nil {
return fmt.Errorf("team for resource %s does not exist in Dependency-Track", resourceName)
}

diff := cmp.Diff(team, &expectedTeam, cmpopts.IgnoreFields(dtrack.Team{}, "UUID"))
if diff != "" {
return fmt.Errorf("team for resource %s is different than expected: %s", resourceName, diff)
}

return nil
}
}

func testAccCheckTeamDoesNotExists(ctx context.Context, testDependencyTrack *testutils.TestDependencyTrack, resourceName string) resource.TestCheckFunc {
return func(state *terraform.State) error {
team, err := findTeamByResourceName(ctx, testDependencyTrack, state, resourceName)
if err != nil {
return err
}
if team != nil {
return fmt.Errorf("team for resource %s exists in Dependency-Track, even though it shouldn't: %v", resourceName, team)
}

return nil
}
}

func findTeamByResourceName(ctx context.Context, testDependencyTrack *testutils.TestDependencyTrack, state *terraform.State, resourceName string) (*dtrack.Team, error) {
teamID, err := testutils.GetResourceID(state, resourceName)
if err != nil {
return nil, err
}

team, err := findTeam(ctx, testDependencyTrack, teamID)
if err != nil {
return nil, fmt.Errorf("failed to get team for resource %s: %w", resourceName, err)
}

return team, nil
}

func findTeam(ctx context.Context, testDependencyTrack *testutils.TestDependencyTrack, teamID uuid.UUID) (*dtrack.Team, error) {
team, err := testDependencyTrack.Client.Team.Get(ctx, teamID)
if err != nil {
var apiErr *dtrack.APIError
ok := errors.As(err, &apiErr)
if !ok || apiErr.StatusCode != 404 {
return nil, fmt.Errorf("failed to get team from Dependency-Track: %w", err)
}

return nil, nil
}

// normalize the returned object not to contain an empty array reference
if len(team.Permissions) == 0 {
team.Permissions = nil
}

return &team, nil
}

func createTeamResourceName(localName string) string {
return fmt.Sprintf("dependencytrack_team.%s", localName)
}
2 changes: 1 addition & 1 deletion internal/provider/teamapikey/team_api_key_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ func (r *TeamAPIKeyResource) Delete(ctx context.Context, req resource.DeleteRequ
func (r *TeamAPIKeyResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
parts := strings.Split(req.ID, "/")
if len(parts) != 2 {
resp.Diagnostics.AddError("Invalid import ID", "Expected ID in the format 'team_id/api_key'")
resp.Diagnostics.AddError("Invalid import ID", fmt.Sprintf("Expected ID in the format 'team_id/api_key', got [%s]", req.ID))
return
}

Expand Down
Loading

0 comments on commit 479659e

Please sign in to comment.