Skip to content

Commit a3b6dd5

Browse files
committed
Add user_token_enabled attribute to organizations
1 parent 9a372fb commit a3b6dd5

File tree

3 files changed

+126
-0
lines changed

3 files changed

+126
-0
lines changed

internal/provider/provider_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,19 @@ func getClientUsingEnv() (*tfe.Client, error) {
157157
return tfeClient, nil
158158
}
159159

160+
func getClientWithToken(token string) (*tfe.Client, error) {
161+
hostname := client.DefaultHostname
162+
if os.Getenv("TFE_HOSTNAME") != "" {
163+
hostname = os.Getenv("TFE_HOSTNAME")
164+
}
165+
166+
tfeClient, err := client.GetClient(hostname, token, defaultSSLSkipVerify)
167+
if err != nil {
168+
return nil, fmt.Errorf("Error getting client: %w", err)
169+
}
170+
return tfeClient, nil
171+
}
172+
160173
func TestProvider(t *testing.T) {
161174
if err := Provider().InternalValidate(); err != nil {
162175
t.Fatalf("err: %s", err)

internal/provider/resource_tfe_organization.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ func resourceTFEOrganization() *schema.Resource {
108108
Optional: true,
109109
Default: true,
110110
},
111+
"user_tokens_enabled": {
112+
Type: schema.TypeBool,
113+
Default: true,
114+
Optional: true,
115+
},
111116

112117
"enforce_hyok": {
113118
Type: schema.TypeBool,
@@ -172,6 +177,10 @@ func resourceTFEOrganizationRead(d *schema.ResourceData, meta interface{}) error
172177
d.Set("speculative_plan_management_enabled", org.SpeculativePlanManagementEnabled)
173178
d.Set("enforce_hyok", org.EnforceHYOK)
174179

180+
if org.UserTokensEnabled != nil {
181+
d.Set("user_tokens_enabled", org.UserTokensEnabled)
182+
}
183+
175184
if org.DefaultProject != nil {
176185
d.Set("default_project_id", org.DefaultProject.ID)
177186
}
@@ -240,6 +249,11 @@ func resourceTFEOrganizationUpdate(d *schema.ResourceData, meta interface{}) err
240249
options.SpeculativePlanManagementEnabled = tfe.Bool(speculativePlanManagementEnabled.(bool))
241250
}
242251

252+
// If user_tokens_enabled is supplied, set it using the options struct.
253+
if userTokensEnabled, ok := d.GetOkExists("user_tokens_enabled"); ok {
254+
options.UserTokensEnabled = tfe.Bool(userTokensEnabled.(bool))
255+
}
256+
243257
// If enforce_hyok is supplied, set it using the options struct.
244258
if enforceHYOK, ok := d.GetOkExists("enforce_hyok"); ok {
245259
options.EnforceHYOK = tfe.Bool(enforceHYOK.(bool))

internal/provider/resource_tfe_organization_test.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ func TestAccTFEOrganization_full(t *testing.T) {
8585
"tfe_organization.foobar", "allow_force_delete_workspaces", "false"),
8686
resource.TestCheckResourceAttr(
8787
"tfe_organization.foobar", "speculative_plan_management_enabled", "true"),
88+
resource.TestCheckResourceAttr(
89+
"tfe_organization.foobar", "user_tokens_enabled", "true"),
8890
),
8991
},
9092
},
@@ -205,6 +207,80 @@ func TestAccTFEOrganization_update_costEstimation(t *testing.T) {
205207
})
206208
}
207209

210+
func TestAccTFEOrganization_user_tokens_enabled(t *testing.T) {
211+
// this test is a bit tricky because once user tokens are disabled, we cannot use a user token to re-enable them
212+
// through the API.
213+
// Therefore, we need to create an org, generate an owners team token for that org, and then use that token
214+
// in the go-tfe client to test the user_tokens_enabled setting.
215+
216+
org := &tfe.Organization{}
217+
rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int()
218+
orgName := fmt.Sprintf("tst-terraform-%d", rInt)
219+
220+
resource.Test(t, resource.TestCase{
221+
PreCheck: func() { testAccPreCheck(t) },
222+
ProtoV6ProviderFactories: testAccMuxedProviders,
223+
CheckDestroy: testAccCheckTFEOrganizationDestroy,
224+
Steps: []resource.TestStep{
225+
{
226+
Config: testAccTFEOrganization_basic(rInt),
227+
Check: resource.ComposeTestCheckFunc(
228+
testAccCheckTFEOrganizationExists(
229+
"tfe_organization.foobar", org),
230+
testAccCheckTFEOrganizationAttributesBasic(org, orgName),
231+
resource.TestCheckResourceAttr(
232+
"tfe_organization.foobar", "user_tokens_enabled", "true"),
233+
),
234+
},
235+
{
236+
PreConfig: func() {
237+
// create a team token for the owners team in the org,
238+
// then set the provider token to that value
239+
ownersTeams, err := testAccConfiguredClient.Client.Teams.List(ctx, org.Name, &tfe.TeamListOptions{
240+
Names: []string{"owners"},
241+
})
242+
if err != nil {
243+
t.Fatal(err)
244+
}
245+
if len(ownersTeams.Items) != 1 {
246+
t.Fatalf("expected to find 1 owners team, found %d", len(ownersTeams.Items))
247+
}
248+
ownersTeam := ownersTeams.Items[0]
249+
250+
teamToken, err := testAccConfiguredClient.Client.TeamTokens.Create(ctx, ownersTeam.ID)
251+
if err != nil {
252+
t.Fatal(err)
253+
}
254+
255+
tfeClient, err := getClientWithToken(teamToken.ID)
256+
if err != nil {
257+
t.Fatal(err)
258+
}
259+
260+
testAccConfiguredClient = &ConfiguredClient{
261+
Client: tfeClient,
262+
Organization: org.Name,
263+
}
264+
},
265+
Config: testAccTFEOrganization_userTokensEnabled(rInt, false),
266+
Check: resource.ComposeTestCheckFunc(
267+
resource.TestCheckResourceAttr(
268+
"tfe_organization.foobar", "user_tokens_enabled", "false"),
269+
testAccCheckTFEOrganizationUserTokensEnabled(org, orgName, false),
270+
),
271+
},
272+
{
273+
Config: testAccTFEOrganization_userTokensEnabled(rInt, true),
274+
Check: resource.ComposeTestCheckFunc(
275+
resource.TestCheckResourceAttr(
276+
"tfe_organization.foobar", "user_tokens_enabled", "true"),
277+
testAccCheckTFEOrganizationUserTokensEnabled(org, orgName, true),
278+
),
279+
},
280+
},
281+
})
282+
}
283+
208284
func TestAccTFEOrganization_EnforceHYOK(t *testing.T) {
209285
skipUnlessHYOKEnabled(t)
210286

@@ -381,6 +457,20 @@ func testAccCheckTFEOrganizationAttributesFull(
381457
}
382458
}
383459

460+
func testAccCheckTFEOrganizationUserTokensEnabled(
461+
org *tfe.Organization, expectedOrgName string, expectedUserTokensEnabled bool) resource.TestCheckFunc {
462+
return func(s *terraform.State) error {
463+
if org.Name != expectedOrgName {
464+
return fmt.Errorf("Bad name: %s", org.Name)
465+
}
466+
467+
if org.UserTokensEnabled != nil && *org.UserTokensEnabled != expectedUserTokensEnabled {
468+
return fmt.Errorf("Bad user tokens enabled: %v", org.UserTokensEnabled)
469+
}
470+
return nil
471+
}
472+
}
473+
384474
func testAccCheckTFEOrganizationAttributesUpdated(
385475
org *tfe.Organization, expectedOrgName string, expectedCostEstimationEnabled bool) resource.TestCheckFunc {
386476
return func(s *terraform.State) error {
@@ -480,6 +570,15 @@ resource "tfe_organization" "foobar" {
480570
}`, orgName, orgEmail, costEstimationEnabled, assessmentsEnforced, allowForceDeleteWorkspaces)
481571
}
482572

573+
func testAccTFEOrganization_userTokensEnabled(rInt int, userTokensEnabled bool) string {
574+
return fmt.Sprintf(`
575+
resource "tfe_organization" "foobar" {
576+
name = "tst-terraform-%d"
577+
578+
user_tokens_enabled = %t
579+
}`, rInt, userTokensEnabled)
580+
}
581+
483582
func testAccTFEOrganization_updateEnforceHYOK(orgName string, enforceHYOK bool) string {
484583
return fmt.Sprintf(`
485584
resource "tfe_organization" "foobar" {

0 commit comments

Comments
 (0)