diff --git a/tfe/data_source_team.go b/tfe/data_source_team.go index 21bcc6ebf..493928295 100644 --- a/tfe/data_source_team.go +++ b/tfe/data_source_team.go @@ -21,6 +21,10 @@ func dataSourceTFETeam() *schema.Resource { Type: schema.TypeString, Required: true, }, + "sso_team_id": { + Type: schema.TypeString, + Computed: true, + }, }, } } @@ -44,6 +48,7 @@ func dataSourceTFETeamRead(d *schema.ResourceData, meta interface{}) error { for _, tm := range l.Items { if tm.Name == name { d.SetId(tm.ID) + d.Set("sso_team_id", tm.SSOTeamID) return nil } } diff --git a/tfe/data_source_team_test.go b/tfe/data_source_team_test.go index 7179f2d02..e4153af0d 100644 --- a/tfe/data_source_team_test.go +++ b/tfe/data_source_team_test.go @@ -14,13 +14,12 @@ func TestAccTFETeamDataSource_basic(t *testing.T) { rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int() orgName := fmt.Sprintf("tst-terraform-%d", rInt) - resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccTFETeamDataSourceConfig(rInt), + Config: testAccTFETeamDataSourceConfig_basic(rInt), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr( "data.tfe_team.foobar", "name", fmt.Sprintf("team-test-%d", rInt)), @@ -33,7 +32,33 @@ func TestAccTFETeamDataSource_basic(t *testing.T) { }) } -func testAccTFETeamDataSourceConfig(rInt int) string { +func TestAccTFETeamDataSource_ssoTeamId(t *testing.T) { + skipIfFreeOnly(t) + + rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int() + orgName := fmt.Sprintf("tst-terraform-%d", rInt) + testSsoTeamId := fmt.Sprintf("sso-team-id-%d", rInt) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccTFETeamDataSourceConfig_ssoTeamId(rInt, testSsoTeamId), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr( + "data.tfe_team.sso_team", "name", fmt.Sprintf("team-test-%d", rInt)), + resource.TestCheckResourceAttr( + "data.tfe_team.sso_team", "organization", orgName), + resource.TestCheckResourceAttrSet("data.tfe_team.sso_team", "id"), + resource.TestCheckResourceAttr( + "data.tfe_team.sso_team", "sso_team_id", testSsoTeamId), + ), + }, + }, + }) +} + +func testAccTFETeamDataSourceConfig_basic(rInt int) string { return fmt.Sprintf(` resource "tfe_organization" "foobar" { name = "tst-terraform-%d" @@ -50,3 +75,22 @@ data "tfe_team" "foobar" { organization = tfe_team.foobar.organization }`, rInt, rInt) } + +func testAccTFETeamDataSourceConfig_ssoTeamId(rInt int, ssoTeamId string) string { + return fmt.Sprintf(` +resource "tfe_organization" "foobar" { + name = "tst-terraform-%d" + email = "admin@company.com" +} + +resource "tfe_team" "sso_team" { + name = "team-test-%d" + organization = tfe_organization.foobar.id + sso_team_id = "%s" +} + +data "tfe_team" "sso_team" { + name = tfe_team.sso_team.name + organization = tfe_team.sso_team.organization +}`, rInt, rInt, ssoTeamId) +} diff --git a/tfe/resource_tfe_team.go b/tfe/resource_tfe_team.go index c8f195612..66aede983 100644 --- a/tfe/resource_tfe_team.go +++ b/tfe/resource_tfe_team.go @@ -81,6 +81,10 @@ func resourceTFETeam() *schema.Resource { "organization", }, false), }, + "sso_team_id": { + Type: schema.TypeString, + Optional: true, + }, }, } } @@ -114,6 +118,10 @@ func resourceTFETeamCreate(d *schema.ResourceData, meta interface{}) error { options.Visibility = tfe.String(v.(string)) } + if v, ok := d.GetOk("sso_team_id"); ok { + options.SSOTeamID = tfe.String(v.(string)) + } + log.Printf("[DEBUG] Create team %s for organization: %s", name, organization) team, err := tfeClient.Teams.Create(ctx, organization, options) if err != nil { @@ -164,6 +172,7 @@ func resourceTFETeamRead(d *schema.ResourceData, meta interface{}) error { } } d.Set("visibility", team.Visibility) + d.Set("sso_team_id", team.SSOTeamID) return nil } @@ -196,6 +205,12 @@ func resourceTFETeamUpdate(d *schema.ResourceData, meta interface{}) error { options.Visibility = tfe.String(v.(string)) } + if v, ok := d.GetOk("sso_team_id"); ok { + options.SSOTeamID = tfe.String(v.(string)) + } else { + options.SSOTeamID = tfe.String("") + } + log.Printf("[DEBUG] Update team: %s", d.Id()) _, err := tfeClient.Teams.Update(ctx, d.Id(), options) if err != nil { diff --git a/tfe/resource_tfe_team_test.go b/tfe/resource_tfe_team_test.go index 0df4d8313..e048f57cb 100644 --- a/tfe/resource_tfe_team_test.go +++ b/tfe/resource_tfe_team_test.go @@ -126,6 +126,33 @@ func TestAccTFETeam_full_update(t *testing.T) { "tfe_team.foobar", "organization_access.0.manage_providers", "false"), resource.TestCheckResourceAttr( "tfe_team.foobar", "organization_access.0.manage_modules", "false"), + resource.TestCheckResourceAttr( + "tfe_team.foobar", "sso_team_id", "changed-sso-id"), + ), + }, + { + Config: testAccTFETeam_full_update_clear(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckTFETeamExists( + "tfe_team.foobar", team), + resource.TestCheckResourceAttr( + "tfe_team.foobar", "name", "team-test-1"), + resource.TestCheckResourceAttr( + "tfe_team.foobar", "visibility", "secret"), + resource.TestCheckResourceAttr( + "tfe_team.foobar", "organization_access.0.manage_policies", "false"), + resource.TestCheckResourceAttr( + "tfe_team.foobar", "organization_access.0.manage_policy_overrides", "false"), + resource.TestCheckResourceAttr( + "tfe_team.foobar", "organization_access.0.manage_workspaces", "false"), + resource.TestCheckResourceAttr( + "tfe_team.foobar", "organization_access.0.manage_vcs_settings", "false"), + resource.TestCheckResourceAttr( + "tfe_team.foobar", "organization_access.0.manage_providers", "false"), + resource.TestCheckResourceAttr( + "tfe_team.foobar", "organization_access.0.manage_modules", "false"), + resource.TestCheckResourceAttr( + "tfe_team.foobar", "sso_team_id", ""), ), }, }, @@ -213,6 +240,9 @@ func testAccCheckTFETeamAttributes_full( if !team.OrganizationAccess.ManageWorkspaces { return fmt.Errorf("OrganizationAccess.ManageWorkspaces should be true") } + if *team.SSOTeamID != "team-test-sso-id" { + return fmt.Errorf("Bad SSO Team ID: %s", *team.SSOTeamID) + } return nil } @@ -239,6 +269,10 @@ func testAccCheckTFETeamAttributes_full_update( return fmt.Errorf("OrganizationAccess.ManageWorkspaces should be false") } + if *team.SSOTeamID != "changed-sso-id" { + return fmt.Errorf("Bad SSO Team ID: %s", *team.SSOTeamID) + } + return nil } } @@ -298,6 +332,7 @@ resource "tfe_team" "foobar" { manage_providers = true manage_modules = true } + sso_team_id = "team-test-sso-id" }`, rInt) } @@ -322,5 +357,21 @@ resource "tfe_team" "foobar" { manage_providers = false manage_modules = false } + + sso_team_id = "changed-sso-id" +}`, rInt) +} + +// unsets values to check that they are properly cleared +func testAccTFETeam_full_update_clear(rInt int) string { + return fmt.Sprintf(` +resource "tfe_organization" "foobar" { + name = "tst-terraform-%d" + email = "admin@company.com" +} + +resource "tfe_team" "foobar" { + name = "team-test-1" + organization = tfe_organization.foobar.id }`, rInt) } diff --git a/website/docs/d/team.html.markdown b/website/docs/d/team.html.markdown index 44e36d81a..ae872fd92 100644 --- a/website/docs/d/team.html.markdown +++ b/website/docs/d/team.html.markdown @@ -31,3 +31,4 @@ The following arguments are supported: In addition to all arguments above, the following attributes are exported: * `id` - The ID of the team. +* `sso_team_id` - (Optional) The [SSO Team ID](https://www.terraform.io/cloud-docs/users-teams-organizations/single-sign-on#team-names-and-sso-team-ids) of the team, if it has been defined diff --git a/website/docs/r/team.html.markdown b/website/docs/r/team.html.markdown index a9eac511a..4d97d61e8 100644 --- a/website/docs/r/team.html.markdown +++ b/website/docs/r/team.html.markdown @@ -41,6 +41,7 @@ The following arguments are supported: * `organization` - (Required) Name of the organization. * `visibility` - (Optional) The visibility of the team ("secret" or "organization"). Defaults to "secret". * `organization_access` - (Optional) Settings for the team's [organization access](https://www.terraform.io/docs/cloud/users-teams-organizations/permissions.html#organization-level-permissions). +* `sso_team_id` - (Optional) Unique Identifier to control [team membership](https://www.terraform.io/cloud-docs/users-teams-organizations/single-sign-on#team-names-and-sso-team-ids) via SAML. Defaults to `null` The `organization_access` block supports: