Files
terraform-provider-threshold/internal/provider/resource_project_test.go
T
Todd Knight 5bb8c82819 Create Watchtower Project Resources (#1)
* Add watchtower provider using the auto generated go sdk.

* Add read and create for project resources.

* Add provider internal validate test.

* Update the project module to be terraform-provider-watchtower

* Organize the ResourceData to Project and vis versa logic into their own helper methods.

* Adding tests for going ResourceData to Project and vis versa.

* provider_update

* Single acceptance test written and correctly failing.

* Implement update and delete. Always run Acceptance Testing

* Move project field names into constants.

* Allow tests to use the apiError response for checking error code.

* Correcting the naming of key value consts.

* Rely on "make testacc" for acceptance testing instead of always running it.

* Updating dependencies to use the new TestController creation.
2020-05-29 09:13:31 -07:00

250 lines
6.2 KiB
Go

package provider
import (
"fmt"
"net/http"
"strings"
"testing"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
"github.com/hashicorp/watchtower/api"
"github.com/hashicorp/watchtower/api/scopes"
"github.com/hashicorp/watchtower/testing/controller"
"github.com/stretchr/testify/assert"
)
func TestAccProjectCreation(t *testing.T) {
tc := controller.NewTestController(t, controller.WithDefaultOrgId("o_0000000000"))
defer tc.Shutdown()
url := tc.ApiAddrs()[0]
resource.Test(t, resource.TestCase{
Providers: testProviders,
CheckDestroy: testAccCheckProjectResourceDestroy(t),
Steps: []resource.TestStep{
{
Config: testConfig(url, firstProjectBar, secondProject),
Check: resource.ComposeTestCheckFunc(
testAccCheckProjectResourceExists("watchtower_project.project1"),
resource.TestCheckResourceAttr("watchtower_project.project1", projectDescriptionKey, "bar"),
resource.TestCheckResourceAttr("watchtower_project.project2", projectDescriptionKey, "project2"),
),
},
// Updates the first project to have description foo
{
Config: testConfig(url, firstProjectFoo, secondProject),
Check: resource.ComposeTestCheckFunc(
testAccCheckProjectResourceExists("watchtower_project.project1"),
resource.TestCheckResourceAttr("watchtower_project.project1", projectDescriptionKey, "foo"),
resource.TestCheckResourceAttr("watchtower_project.project2", projectDescriptionKey, "project2"),
),
},
// Remove second project
{
Config: testConfig(url, firstProjectFoo),
Check: resource.ComposeTestCheckFunc(
testAccCheckProjectResourceExists("watchtower_project.project1"),
resource.TestCheckResourceAttr("watchtower_project.project1", projectDescriptionKey, "foo"),
),
},
},
})
}
func testAccCheckProjectResourceExists(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}
id := rs.Primary.ID
if id == "" {
return fmt.Errorf("No ID is set")
}
if !strings.HasPrefix(id, "p_") {
return fmt.Errorf("ID not formatted as expected")
}
md := testProvider.Meta().(*metaData)
o := scopes.Organization{
Client: md.client,
}
if _, _, err := o.ReadProject(md.ctx, &scopes.Project{Id: id}); err != nil {
return fmt.Errorf("Got an error when reading project %q: %v", id, err)
}
return nil
}
}
func testAccCheckProjectResourceDestroy(t *testing.T) resource.TestCheckFunc {
return func(s *terraform.State) error {
// retrieve the connection established in Provider configuration
md := testProvider.Meta().(*metaData)
o := scopes.Organization{
Client: md.client,
}
for _, rs := range s.RootModule().Resources {
id := rs.Primary.ID
switch rs.Type {
case "watchtower_project":
if _, apiErr, _ := o.ReadProject(md.ctx, &scopes.Project{Id: id}); apiErr == nil || *apiErr.Status != http.StatusNotFound {
return fmt.Errorf("Didn't get a 404 when reading destroyed project %q: %v", id, apiErr)
}
default:
t.Logf("Got unknown resource type %q", rs.Type)
}
}
return nil
}
}
func TestResourceDataToProject(t *testing.T) {
rp := resourceProject()
testCases := []struct {
name string
rData map[string]interface{}
expected *scopes.Project
}{
{
name: "Fully populated",
rData: map[string]interface{}{
projectNameKey: "name",
projectDescriptionKey: "desc",
},
expected: &scopes.Project{
Name: api.String("name"),
Description: api.String("desc"),
},
},
{
name: "Name populated",
rData: map[string]interface{}{
projectNameKey: "name",
},
expected: &scopes.Project{
Name: api.String("name"),
},
},
{
name: "Description populated",
rData: map[string]interface{}{
projectDescriptionKey: "desc",
},
expected: &scopes.Project{
Description: api.String("desc"),
},
},
{
name: "Not populated",
rData: map[string]interface{}{},
expected: &scopes.Project{},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
rd := rp.TestResourceData()
for k, v := range tc.rData {
err := rd.Set(k, v)
assert.NoError(t, err)
}
assert.Equal(t, tc.expected, convertResourceDataToProject(rd))
})
}
}
func TestProjectToResourceData(t *testing.T) {
rp := resourceProject()
testCases := []struct {
name string
expected map[string]interface{}
proj *scopes.Project
}{
{
name: "Fully populated",
proj: &scopes.Project{
Id: "someid",
Name: api.String("name"),
Description: api.String("desc"),
},
expected: map[string]interface{}{
projectNameKey: "name",
projectDescriptionKey: "desc",
},
},
{
name: "Name populated",
proj: &scopes.Project{
Id: "someid",
Name: api.String("name"),
},
expected: map[string]interface{}{
projectNameKey: "name",
},
},
{
name: "Description populated",
proj: &scopes.Project{
Id: "someid",
Description: api.String("desc"),
},
expected: map[string]interface{}{
projectDescriptionKey: "desc",
},
},
{
name: "Not populated",
proj: &scopes.Project{
Id: "someid",
},
expected: map[string]interface{}{},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
expectedRd := rp.TestResourceData()
expectedRd.SetId("someid")
for k, v := range tc.expected {
err := expectedRd.Set(k, v)
assert.NoError(t, err)
}
actual := rp.TestResourceData()
err := convertProjectToResourceData(tc.proj, actual)
assert.NoError(t, err)
assert.Equal(t, expectedRd, actual)
})
}
}
const (
firstProjectFoo = `
resource "watchtower_project" "project1" {
description = "foo"
}`
firstProjectBar = `
resource "watchtower_project" "project1" {
description = "bar"
}`
secondProject = `
resource "watchtower_project" "project2" {
description = "project2"
}
`
)
func testConfig(url string, res ...string) string {
provider := fmt.Sprintf(`
provider "watchtower" {
base_url = "%s"
default_organization = "o_0000000000"
}`, url)
c := []string{provider}
c = append(c, res...)
return strings.Join(c, "\n")
}