Skip to content

Commit 5484171

Browse files
include acceptance tests for org service account resource (#3755)
1 parent 841b19b commit 5484171

File tree

2 files changed

+195
-0
lines changed

2 files changed

+195
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package orgserviceaccountapi_test
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
"github.com/mongodb/terraform-provider-mongodbatlas/internal/testutil/acc"
8+
)
9+
10+
func TestMain(m *testing.M) {
11+
cleanup := acc.SetupSharedResources()
12+
exitCode := m.Run()
13+
cleanup()
14+
os.Exit(exitCode)
15+
}
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
package orgserviceaccountapi_test
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
"regexp"
8+
"strings"
9+
"testing"
10+
11+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
12+
"github.com/hashicorp/terraform-plugin-testing/terraform"
13+
"github.com/mongodb/terraform-provider-mongodbatlas/internal/testutil/acc"
14+
)
15+
16+
const resourceName = "mongodbatlas_org_service_account_api.test"
17+
18+
func TestAccOrgServiceAccountAPI_basic(t *testing.T) {
19+
var (
20+
orgID = os.Getenv("MONGODB_ATLAS_ORG_ID")
21+
name1 = acc.RandomName()
22+
name2 = fmt.Sprintf("%s-updated", name1)
23+
description1 = "Acceptance Test SA"
24+
description2 = "Updated Description"
25+
)
26+
27+
resource.ParallelTest(t, resource.TestCase{
28+
PreCheck: func() { acc.PreCheckBasic(t) },
29+
ProtoV6ProviderFactories: acc.TestAccProviderV6Factories,
30+
CheckDestroy: checkDestroy,
31+
Steps: []resource.TestStep{
32+
{
33+
Config: configBasic(orgID, name1, description1, []string{"ORG_OWNER"}, 24),
34+
Check: checkBasic(true),
35+
},
36+
{
37+
Config: configBasic(orgID, name2, description2, []string{"ORG_READ_ONLY"}, 24),
38+
Check: checkBasic(false),
39+
},
40+
{
41+
ResourceName: resourceName,
42+
ImportStateIdFunc: importStateIDFunc(resourceName),
43+
ImportStateVerifyIdentifierAttribute: "client_id",
44+
ImportState: true,
45+
ImportStateVerify: true,
46+
ImportStateVerifyIgnore: []string{"secret_expires_after_hours"}, // secretExpiresAfterHours is not returned in response, import UX to be revised in CLOUDP-349629
47+
},
48+
},
49+
})
50+
}
51+
52+
func TestAccOrgServiceAccountAPI_rolesOrdering(t *testing.T) {
53+
t.Skip("Roles is currently incorrectly defined as a List leading to inconsistent result after apply, to be addressed in CLOUDP-349935")
54+
var (
55+
orgID = os.Getenv("MONGODB_ATLAS_ORG_ID")
56+
name = acc.RandomName()
57+
)
58+
resource.ParallelTest(t, resource.TestCase{
59+
PreCheck: func() { acc.PreCheckBasic(t) },
60+
ProtoV6ProviderFactories: acc.TestAccProviderV6Factories,
61+
CheckDestroy: checkDestroy,
62+
Steps: []resource.TestStep{
63+
{
64+
Config: configBasic(orgID, name, "Roles Update", []string{"ORG_BILLING_ADMIN", "ORG_READ_ONLY"}, 24),
65+
},
66+
{
67+
// change order
68+
Config: configBasic(orgID, name, "Roles Update", []string{"ORG_READ_ONLY", "ORG_BILLING_ADMIN"}, 24),
69+
},
70+
},
71+
})
72+
}
73+
74+
func TestAccOrgServiceAccountAPI_createOnlyAttributes(t *testing.T) {
75+
var (
76+
orgID = os.Getenv("MONGODB_ATLAS_ORG_ID")
77+
name = acc.RandomName()
78+
)
79+
resource.ParallelTest(t, resource.TestCase{
80+
PreCheck: func() { acc.PreCheckBasic(t) },
81+
ProtoV6ProviderFactories: acc.TestAccProviderV6Factories,
82+
Steps: []resource.TestStep{
83+
{
84+
Config: configBasic(orgID, name, "description", []string{"ORG_READ_ONLY"}, 24),
85+
Check: checkExists(resourceName),
86+
},
87+
{
88+
Config: configBasic(orgID, name, "description", []string{"ORG_READ_ONLY"}, 48),
89+
PlanOnly: true,
90+
ExpectError: regexp.MustCompile("secret_expires_after_hours cannot be updated"),
91+
},
92+
{
93+
Config: configBasic("updated-org-id", name, "description", []string{"ORG_READ_ONLY"}, 24),
94+
PlanOnly: true,
95+
ExpectError: regexp.MustCompile("org_id cannot be updated"),
96+
},
97+
},
98+
})
99+
}
100+
101+
func configBasic(orgID, name, description string, roles []string, secretExpiresAfterHours int) string {
102+
rolesStr := fmt.Sprintf(`%q`, strings.Join(roles, `", "`))
103+
rolesHCL := fmt.Sprintf("[%s]", rolesStr)
104+
return fmt.Sprintf(`
105+
resource "mongodbatlas_org_service_account_api" "test" {
106+
org_id = %q
107+
name = %q
108+
description = %q
109+
roles = %s
110+
secret_expires_after_hours = %d
111+
}
112+
`, orgID, name, description, rolesHCL, secretExpiresAfterHours)
113+
}
114+
115+
func checkBasic(isCreate bool) resource.TestCheckFunc {
116+
setAttrsChecks := []string{"client_id", "created_at", "secrets.0.id", "secrets.0.created_at", "secrets.0.expires_at"}
117+
if isCreate {
118+
setAttrsChecks = append(setAttrsChecks, "secrets.0.secret") // secret value is only present in the first apply
119+
} else {
120+
setAttrsChecks = append(setAttrsChecks, "secrets.0.masked_secret_value")
121+
}
122+
mapChecks := map[string]string{"secrets.#": "1"}
123+
checks := acc.AddAttrSetChecks(resourceName, nil, setAttrsChecks...)
124+
checks = acc.AddAttrChecks(resourceName, checks, mapChecks)
125+
checks = append(checks, checkExists(resourceName))
126+
return resource.ComposeAggregateTestCheckFunc(checks...)
127+
}
128+
129+
func checkExists(resourceName string) resource.TestCheckFunc {
130+
return func(s *terraform.State) error {
131+
rs, ok := s.RootModule().Resources[resourceName]
132+
if !ok {
133+
return fmt.Errorf("not found: %s", resourceName)
134+
}
135+
orgID := rs.Primary.Attributes["org_id"]
136+
clientID := rs.Primary.Attributes["client_id"]
137+
if orgID == "" || clientID == "" {
138+
return fmt.Errorf("checkExists, attributes not found for: %s", resourceName)
139+
}
140+
_, _, err := acc.ConnV2().ServiceAccountsApi.GetOrgServiceAccount(context.Background(), orgID, clientID).Execute()
141+
if err == nil {
142+
return nil
143+
}
144+
return fmt.Errorf("org service account (%s/%s) does not exist", orgID, clientID)
145+
}
146+
}
147+
148+
func checkDestroy(s *terraform.State) error {
149+
for _, rs := range s.RootModule().Resources {
150+
if rs.Type != "mongodbatlas_org_service_account_api" {
151+
continue
152+
}
153+
orgID := rs.Primary.Attributes["org_id"]
154+
clientID := rs.Primary.Attributes["client_id"]
155+
if orgID == "" || clientID == "" {
156+
return fmt.Errorf("checkDestroy, attributes not found for: %s", resourceName)
157+
}
158+
159+
_, _, err := acc.ConnV2().ServiceAccountsApi.GetOrgServiceAccount(context.Background(), orgID, clientID).Execute()
160+
if err == nil {
161+
return fmt.Errorf("org service account (%s/%s) still exists", orgID, clientID)
162+
}
163+
}
164+
return nil
165+
}
166+
167+
func importStateIDFunc(resourceName string) resource.ImportStateIdFunc {
168+
return func(s *terraform.State) (string, error) {
169+
rs, ok := s.RootModule().Resources[resourceName]
170+
if !ok {
171+
return "", fmt.Errorf("not found: %s", resourceName)
172+
}
173+
orgID := rs.Primary.Attributes["org_id"]
174+
clientID := rs.Primary.Attributes["client_id"]
175+
if orgID == "" || clientID == "" {
176+
return "", fmt.Errorf("import, attributes not found for: %s", resourceName)
177+
}
178+
return fmt.Sprintf("%s/%s", orgID, clientID), nil
179+
}
180+
}

0 commit comments

Comments
 (0)