Skip to content

Commit

Permalink
chore: use ephemeral workspaces in tests (#219)
Browse files Browse the repository at this point in the history
* Remove unnamedResult linter

Conflicts with 'nonamedreturns' linter, and named returns isn't always
used or recommended.

* Add helpers for creating ephemeral workspaces

Adds two helpers to create random values and random workspaces to be
used as ephemeral resources.

* Use ephemeral workspace for Block test

Uses the new ephemeral workspace helpers to create the new, random
workspace.

* Clarify errors when checking if resource exists

* Use ephemeral workspace for Variable tests

Needed to set '10' as a constant to work around the 'mnd' linter.

* Use ephemeral workspaces for Work Pool tests
  • Loading branch information
mitchnielsen authored Jul 18, 2024
1 parent f83d831 commit 01c2b9a
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 86 deletions.
1 change: 0 additions & 1 deletion .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ linters-settings:
- typeUnparen
- uncheckedInlineErr
- unlabelStmt
- unnamedResult
- unnecessaryBlock
- unnecessaryDefer
- weakCond
Expand Down
38 changes: 18 additions & 20 deletions internal/provider/resources/block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,36 @@ import (
"testing"

"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"
"github.com/prefecthq/terraform-provider-prefect/internal/api"
"github.com/prefecthq/terraform-provider-prefect/internal/testutils"
)

func fixtureAccBlock(name string, value string) string {
func fixtureAccBlock(workspace, workspaceName, blockName, blockValue string) string {
return fmt.Sprintf(`
resource "prefect_workspace" "workspace" {
name = "%s"
handle = "%s"
}
resource "prefect_block" "block" {
%s
resource "prefect_block" "%s" {
name = "%s"
type_slug = "secret"
workspace_id = prefect_workspace.workspace.id
data = jsonencode({
"value" = "%s"
})
depends_on = [prefect_workspace.workspace]
}
`, name, name, name, value)
workspace_id = prefect_workspace.%s.id
depends_on = [prefect_workspace.%s]
}`, workspace, blockName, blockName, blockValue, workspaceName, workspaceName)
}

//nolint:paralleltest // we use the resource.ParallelTest helper instead
func TestAccResource_block(t *testing.T) {
blockResourceName := "prefect_block.block"
workspaceResourceName := "prefect_workspace.workspace"
randomName := testutils.TestAccPrefix + acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
randomValue := testutils.TestAccPrefix + acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
randomValue2 := testutils.TestAccPrefix + acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
randomName := testutils.NewRandomPrefixedString()
randomValue := testutils.NewRandomPrefixedString()
randomValue2 := testutils.NewRandomPrefixedString()

workspace, workspaceName := testutils.NewEphemeralWorkspace()

blockResourceName := fmt.Sprintf("prefect_block.%s", randomName)
workspaceResourceName := fmt.Sprintf("prefect_workspace.%s", workspaceName)

// We use this variable to store the fetched block document resource from the API
// and it will be shared between the TestSteps via pointer.
Expand All @@ -50,7 +48,7 @@ func TestAccResource_block(t *testing.T) {
Steps: []resource.TestStep{
// Check creation + existence of the block resource
{
Config: fixtureAccBlock(randomName, randomValue),
Config: fixtureAccBlock(workspace, workspaceName, randomName, randomValue),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckBlockExists(blockResourceName, workspaceResourceName, &blockDocument),
testAccCheckBlockValues(&blockDocument, ExpectedBlockValues{
Expand All @@ -65,7 +63,7 @@ func TestAccResource_block(t *testing.T) {
},
// Check updating the value of the block resource
{
Config: fixtureAccBlock(randomName, randomValue2),
Config: fixtureAccBlock(workspace, workspaceName, randomName, randomValue2),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckBlockExists(blockResourceName, workspaceResourceName, &blockDocument),
testAccCheckBlockValues(&blockDocument, ExpectedBlockValues{
Expand Down Expand Up @@ -96,14 +94,14 @@ func testAccCheckBlockExists(blockResourceName string, workspaceResourceName str
// Get the block resource we just created from the state
blockResource, exists := s.RootModule().Resources[blockResourceName]
if !exists {
return fmt.Errorf("resource not found: %s", blockResourceName)
return fmt.Errorf("block resource not found: %s", blockResourceName)
}
blockID, _ := uuid.Parse(blockResource.Primary.ID)

// Get the workspace resource we just created from the state
workspaceResource, exists := s.RootModule().Resources[workspaceResourceName]
if !exists {
return fmt.Errorf("resource not found: %s", workspaceResourceName)
return fmt.Errorf("workspace resource not found: %s", workspaceResourceName)
}
workspaceID, _ := uuid.Parse(workspaceResource.Primary.ID)

Expand Down
76 changes: 38 additions & 38 deletions internal/provider/resources/variable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,50 @@ import (
"testing"

"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"
"github.com/prefecthq/terraform-provider-prefect/internal/api"
"github.com/prefecthq/terraform-provider-prefect/internal/testutils"
)

func fixtureAccVariableResource(name string, value string) string {
func fixtureAccVariableResource(workspace, workspaceName, name, value string) string {
return fmt.Sprintf(`
data "prefect_workspace" "evergreen" {
handle = "github-ci-tests"
}
resource "prefect_variable" "test" {
workspace_id = data.prefect_workspace.evergreen.id
%s
resource "prefect_variable" "%s" {
name = "%s"
value = "%s"
workspace_id = prefect_workspace.%s.id
depends_on = [prefect_workspace.%s]
}
`, name, value)
`, workspace, name, name, value, workspaceName, workspaceName)
}

func fixtureAccVariableResourceWithTags(name string, value string) string {
func fixtureAccVariableResourceWithTags(workspace, workspaceName, name, value string) string {
return fmt.Sprintf(`
data "prefect_workspace" "evergreen" {
handle = "github-ci-tests"
}
resource "prefect_variable" "test" {
workspace_id = data.prefect_workspace.evergreen.id
%s
resource "prefect_variable" "%s" {
name = "%s"
value = "%s"
tags = ["foo", "bar"]
workspace_id = prefect_workspace.%s.id
depends_on = [prefect_workspace.%s]
}
`, name, value)
`, workspace, name, name, value, workspaceName, workspaceName)
}

//nolint:paralleltest // we use the resource.ParallelTest helper instead
func TestAccResource_variable(t *testing.T) {
resourceName := "prefect_variable.test"
const workspaceDatsourceName = "data.prefect_workspace.evergreen"
randomName := testutils.NewRandomPrefixedString()
randomName2 := testutils.NewRandomPrefixedString()

resourceName := "prefect_variable." + randomName
resourceName2 := "prefect_variable." + randomName2

randomName := testutils.TestAccPrefix + acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
randomName2 := testutils.TestAccPrefix + acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
randomValue := testutils.NewRandomPrefixedString()
randomValue2 := testutils.NewRandomPrefixedString()

randomValue := testutils.TestAccPrefix + acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
randomValue2 := testutils.TestAccPrefix + acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
workspace, workspaceName := testutils.NewEphemeralWorkspace()
workspaceResourceName := "prefect_workspace." + workspaceName

// We use this variable to store the fetched resource from the API
// and it will be shared between TestSteps via a pointer.
Expand All @@ -61,54 +61,54 @@ func TestAccResource_variable(t *testing.T) {
Steps: []resource.TestStep{
{
// Check creation + existence of the variable resource
Config: fixtureAccVariableResource(randomName, randomValue),
Config: fixtureAccVariableResource(workspace, workspaceName, randomName, randomValue),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckVariableExists(resourceName, workspaceDatsourceName, &variable),
testAccCheckVariableExists(resourceName, workspaceResourceName, &variable),
testAccCheckVariableValues(&variable, &api.Variable{Name: randomName, Value: randomValue}),
resource.TestCheckResourceAttr(resourceName, "name", randomName),
resource.TestCheckResourceAttr(resourceName, "value", randomValue),
),
},
{
// Check updating name + value of the variable resource
Config: fixtureAccVariableResource(randomName2, randomValue2),
Config: fixtureAccVariableResource(workspace, workspaceName, randomName2, randomValue2),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckVariableExists(resourceName, workspaceDatsourceName, &variable),
testAccCheckVariableExists(resourceName2, workspaceResourceName, &variable),
testAccCheckVariableValues(&variable, &api.Variable{Name: randomName2, Value: randomValue2}),
resource.TestCheckResourceAttr(resourceName, "name", randomName2),
resource.TestCheckResourceAttr(resourceName, "value", randomValue2),
resource.TestCheckResourceAttr(resourceName2, "name", randomName2),
resource.TestCheckResourceAttr(resourceName2, "value", randomValue2),
),
},
{
// Check adding tags
Config: fixtureAccVariableResourceWithTags(randomName2, randomValue2),
Config: fixtureAccVariableResourceWithTags(workspace, workspaceName, randomName2, randomValue2),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckVariableExists(resourceName, workspaceDatsourceName, &variable),
testAccCheckVariableExists(resourceName2, workspaceResourceName, &variable),
testAccCheckVariableValues(&variable, &api.Variable{Name: randomName2, Value: randomValue2}),
resource.TestCheckResourceAttr(resourceName, "name", randomName2),
resource.TestCheckResourceAttr(resourceName, "value", randomValue2),
resource.TestCheckResourceAttr(resourceName, "tags.#", "2"),
resource.TestCheckResourceAttr(resourceName, "tags.0", "foo"),
resource.TestCheckResourceAttr(resourceName, "tags.1", "bar"),
resource.TestCheckResourceAttr(resourceName2, "name", randomName2),
resource.TestCheckResourceAttr(resourceName2, "value", randomValue2),
resource.TestCheckResourceAttr(resourceName2, "tags.#", "2"),
resource.TestCheckResourceAttr(resourceName2, "tags.0", "foo"),
resource.TestCheckResourceAttr(resourceName2, "tags.1", "bar"),
),
},
},
})
}

func testAccCheckVariableExists(variableResourceName string, workspaceDatasourceName string, variable *api.Variable) resource.TestCheckFunc {
func testAccCheckVariableExists(variableResourceName string, workspaceResourceName string, variable *api.Variable) resource.TestCheckFunc {
return func(state *terraform.State) error {
variableResource, exists := state.RootModule().Resources[variableResourceName]
if !exists {
return fmt.Errorf("Resource not found in state: %s", variableResourceName)
}
variableResourceID, _ := uuid.Parse(variableResource.Primary.ID)

workspaceDatsource, exists := state.RootModule().Resources[workspaceDatasourceName]
workspaceResource, exists := state.RootModule().Resources[workspaceResourceName]
if !exists {
return fmt.Errorf("Resource not found in state: %s", workspaceDatasourceName)
return fmt.Errorf("Resource not found in state: %s", workspaceResourceName)
}
workspaceID, _ := uuid.Parse(workspaceDatsource.Primary.ID)
workspaceID, _ := uuid.Parse(workspaceResource.Primary.ID)

// Create a new client, and use the default configurations from the environment
c, _ := testutils.NewTestClient()
Expand Down
49 changes: 25 additions & 24 deletions internal/provider/resources/work_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,36 @@ import (
"testing"

"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"
"github.com/prefecthq/terraform-provider-prefect/internal/api"
"github.com/prefecthq/terraform-provider-prefect/internal/testutils"
)

func fixtureAccWorkPoolCreate(name string, poolType string, paused bool) string {
func fixtureAccWorkPoolCreate(workspace, workspaceName, name, poolType string, paused bool) string {
return fmt.Sprintf(`
resource "prefect_workspace" "workspace" {
name = "%s"
handle = "%s"
}
resource "prefect_work_pool" "test" {
%s
resource "prefect_work_pool" "%s" {
name = "%s"
type = "%s"
workspace_id = prefect_workspace.workspace.id
paused = %t
depends_on = [prefect_workspace.workspace]
workspace_id = prefect_workspace.%s.id
depends_on = [prefect_workspace.%s]
}
`, name, name, name, poolType, paused)
`, workspace, name, name, poolType, paused, workspaceName, workspaceName)
}

//nolint:paralleltest // we use the resource.ParallelTest helper instead
func TestAccResource_work_pool(t *testing.T) {
workPoolResourceName := "prefect_work_pool.test"
workspaceResourceName := "prefect_workspace.workspace"
randomName := testutils.TestAccPrefix + acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
randomName2 := testutils.TestAccPrefix + acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
workspace, workspaceName := testutils.NewEphemeralWorkspace()
workspaceResourceName := "prefect_workspace." + workspaceName

randomName := testutils.NewRandomPrefixedString()
workPoolResourceName := "prefect_work_pool." + randomName

randomName2 := testutils.NewRandomPrefixedString()
workPoolResourceName2 := "prefect_work_pool." + randomName2

poolType := "kubernetes"
poolType2 := "ecs"

Expand All @@ -48,7 +49,7 @@ func TestAccResource_work_pool(t *testing.T) {
Steps: []resource.TestStep{
{
// Check creation + existence of the work pool resource
Config: fixtureAccWorkPoolCreate(randomName, poolType, true),
Config: fixtureAccWorkPoolCreate(workspace, workspaceName, randomName, poolType, true),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckWorkPoolExists(workPoolResourceName, workspaceResourceName, &workPool),
testAccCheckWorkPoolValues(&workPool, &api.WorkPool{Name: randomName, Type: poolType, IsPaused: true}),
Expand All @@ -59,7 +60,7 @@ func TestAccResource_work_pool(t *testing.T) {
},
{
// Check that changing the paused state will update the resource in place
Config: fixtureAccWorkPoolCreate(randomName, poolType, false),
Config: fixtureAccWorkPoolCreate(workspace, workspaceName, randomName, poolType, false),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckIDAreEqual(workPoolResourceName, &workPool),
testAccCheckWorkPoolExists(workPoolResourceName, workspaceResourceName, &workPool),
Expand All @@ -71,27 +72,27 @@ func TestAccResource_work_pool(t *testing.T) {
},
{
// Check that changing the name will re-create the resource
Config: fixtureAccWorkPoolCreate(randomName2, poolType, false),
Config: fixtureAccWorkPoolCreate(workspace, workspaceName, randomName2, poolType, false),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckIDsNotEqual(workPoolResourceName, &workPool),
testAccCheckWorkPoolExists(workPoolResourceName, workspaceResourceName, &workPool),
testAccCheckIDsNotEqual(workPoolResourceName2, &workPool),
testAccCheckWorkPoolExists(workPoolResourceName2, workspaceResourceName, &workPool),
testAccCheckWorkPoolValues(&workPool, &api.WorkPool{Name: randomName2, Type: poolType, IsPaused: false}),
),
},
{
// Check that changing the poolType will re-create the resource
Config: fixtureAccWorkPoolCreate(randomName2, poolType2, false),
Config: fixtureAccWorkPoolCreate(workspace, workspaceName, randomName2, poolType2, false),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckIDsNotEqual(workPoolResourceName, &workPool),
testAccCheckWorkPoolExists(workPoolResourceName, workspaceResourceName, &workPool),
testAccCheckIDsNotEqual(workPoolResourceName2, &workPool),
testAccCheckWorkPoolExists(workPoolResourceName2, workspaceResourceName, &workPool),
testAccCheckWorkPoolValues(&workPool, &api.WorkPool{Name: randomName2, Type: poolType2, IsPaused: false}),
),
},
// Import State checks - import by workspace_id,name (dynamic)
{
ImportState: true,
ResourceName: workPoolResourceName,
ImportStateIdFunc: getWorkPoolImportStateID(workPoolResourceName, workspaceResourceName),
ResourceName: workPoolResourceName2,
ImportStateIdFunc: getWorkPoolImportStateID(workPoolResourceName2, workspaceResourceName),
ImportStateVerify: true,
},
},
Expand Down
29 changes: 26 additions & 3 deletions internal/testutils/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,21 @@ import (
"github.com/hashicorp/terraform-plugin-framework/provider"
"github.com/hashicorp/terraform-plugin-framework/providerserver"
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/prefecthq/terraform-provider-prefect/internal/api"
"github.com/prefecthq/terraform-provider-prefect/internal/client"
prefectProvider "github.com/prefecthq/terraform-provider-prefect/internal/provider"
)

// TestAccPrefix is the prefix set for all resources created via acceptance testing,
// so that we can easily identify and clean them up in case of flakiness/failures.
const TestAccPrefix = "terraformacc"
const (
// TestAccPrefix is the prefix set for all resources created via acceptance testing,
// so that we can easily identify and clean them up in case of flakiness/failures.
TestAccPrefix = "terraformacc"

// RandomStringLength sets the length of the random string used when creating a new random
// name for a resource via NewRandomEphemeralWorkspace.
RandomStringLength = 10
)

// TestAccProvider defines the actual Provider, which is used during acceptance testing.
// This is the same Provider that is used by the CLI, and is used by
Expand Down Expand Up @@ -72,3 +79,19 @@ func NewTestClient() (api.PrefectClient, error) {

return prefectClient, nil
}

func NewRandomPrefixedString() string {
return TestAccPrefix + acctest.RandStringFromCharSet(RandomStringLength, acctest.CharSetAlphaNum)
}

func NewEphemeralWorkspace() (string, string) {
randomName := NewRandomPrefixedString()

workspace := fmt.Sprintf(`
resource "prefect_workspace" "%s" {
name = "%s"
handle = "%s"
}`, randomName, randomName, randomName)

return workspace, randomName
}

0 comments on commit 01c2b9a

Please sign in to comment.