Skip to content

Commit

Permalink
Add support of classic orgs to vcd_tm_org (#1369)
Browse files Browse the repository at this point in the history
Signed-off-by: abarreiro <[email protected]>
  • Loading branch information
adambarreiro authored Dec 19, 2024
1 parent 0f94fac commit d7eebcf
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 22 deletions.
2 changes: 1 addition & 1 deletion .changes/v4.0.0/1345-features.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
* **New Resource:** `vcd_tm_org` to manage TM Organizations [GH-1345, GH-1351]
* **New Resource:** `vcd_tm_org` to manage TM Organizations [GH-1345, GH-1351, GH-1369]
* **New Data Source:** `vcd_tm_org` to read TM Organizations [GH-1345]
10 changes: 9 additions & 1 deletion .github/workflows/check-security.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
name: Run Gosec
on: [push, pull_request]
on:
push:
paths-ignore:
- '**.md'
- 'website/**'
pull_request:
paths-ignore:
- '**.md'
- 'website/**'
jobs:
gosec:
runs-on: ubuntu-latest
Expand Down
24 changes: 13 additions & 11 deletions vcd/resource_vcd_tm_org.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ func resourceVcdTmOrg() *schema.Resource {
Optional: true,
Description: fmt.Sprintf("Enables this organization to manage other %ss", labelTmOrg),
},
"is_classic_tenant": {
Type: schema.TypeBool,
Optional: true,
ForceNew: true, // Cannot be changed once created
Description: fmt.Sprintf("Defines whether the %s is a classic VRA-style tenant", labelTmOrg),
},
"managed_by_id": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -100,11 +106,6 @@ func resourceVcdTmOrg() *schema.Resource {
Computed: true,
Description: fmt.Sprintf("Number of directly managed %ss", labelTmOrg),
},
"is_classic_tenant": {
Type: schema.TypeBool,
Computed: true,
Description: fmt.Sprintf("Defines whether the %s is a classic VRA-style tenant", labelTmOrg),
},
},
}
}
Expand Down Expand Up @@ -160,7 +161,7 @@ func resourceVcdTmOrgDelete(ctx context.Context, d *schema.ResourceData, meta in
return deleteResource(ctx, d, meta, c)
}

// disableTmOrg disables Org which is usefull before deletion as a non-disabled Org cannot be
// disableTmOrg disables Org which is useful before deletion as a non-disabled Org cannot be
// removed
func disableTmOrg(t *govcd.TmOrg) error {
if t.TmOrg.IsEnabled {
Expand Down Expand Up @@ -204,11 +205,12 @@ func resourceVcdTmOrgImport(ctx context.Context, d *schema.ResourceData, meta in

func getTmOrgType(_ *VCDClient, d *schema.ResourceData) (*types.TmOrg, error) {
t := &types.TmOrg{
Name: d.Get("name").(string),
DisplayName: d.Get("display_name").(string),
Description: d.Get("description").(string),
IsEnabled: d.Get("is_enabled").(bool),
CanManageOrgs: d.Get("is_subprovider").(bool),
Name: d.Get("name").(string),
DisplayName: d.Get("display_name").(string),
Description: d.Get("description").(string),
IsEnabled: d.Get("is_enabled").(bool),
CanManageOrgs: d.Get("is_subprovider").(bool),
IsClassicTenant: d.Get("is_classic_tenant").(bool),
}

return t, nil
Expand Down
85 changes: 85 additions & 0 deletions vcd/resource_vcd_tm_org_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func TestAccVcdTmOrg(t *testing.T) {
resource.TestCheckResourceAttr("vcd_tm_org.test", "is_subprovider", "false"),
resource.TestMatchResourceAttr("vcd_tm_org.test", "managed_by_id", regexp.MustCompile("^urn:vcloud:org:")),
resource.TestCheckResourceAttr("vcd_tm_org.test", "managed_by_name", "System"),
resource.TestCheckResourceAttr("vcd_tm_org.test", "is_classic_tenant", "false"),
),
},
{
Expand All @@ -60,6 +61,7 @@ func TestAccVcdTmOrg(t *testing.T) {
resource.TestCheckResourceAttr("vcd_tm_org.test", "is_subprovider", "false"),
resource.TestMatchResourceAttr("vcd_tm_org.test", "managed_by_id", regexp.MustCompile("^urn:vcloud:org:")),
resource.TestCheckResourceAttr("vcd_tm_org.test", "managed_by_name", "System"),
resource.TestCheckResourceAttr("vcd_tm_org.test", "is_classic_tenant", "false"),
),
},
{
Expand Down Expand Up @@ -141,6 +143,7 @@ func TestAccVcdTmOrgSubProvider(t *testing.T) {
resource.TestCheckResourceAttr("vcd_tm_org.test", "is_subprovider", "true"),
resource.TestMatchResourceAttr("vcd_tm_org.test", "managed_by_id", regexp.MustCompile("^urn:vcloud:org:")),
resource.TestCheckResourceAttr("vcd_tm_org.test", "managed_by_name", "System"),
resource.TestCheckResourceAttr("vcd_tm_org.test", "is_classic_tenant", "false"),
),
},
{
Expand Down Expand Up @@ -176,3 +179,85 @@ data "vcd_tm_org" "test" {
name = vcd_tm_org.test.name
}
`

// TestAccVcdTmOrgClassicTenant tests a Tenant Manager Organization configured as "Classic Tenant"
func TestAccVcdTmOrgClassicTenant(t *testing.T) {
preTestChecks(t)

skipIfNotSysAdmin(t)
skipIfNotTm(t)

var params = StringMap{
"Testname": t.Name(),
"Tags": "tm",
}
testParamsNotEmpty(t, params)

configText1 := templateFill(testAccVcdTmOrgClassicStep1, params)
params["FuncName"] = t.Name() + "-step2"
configText2 := templateFill(testAccVcdTmOrgClassicStep2, params)

debugPrintf("#[DEBUG] CONFIGURATION step1: %s\n", configText1)
debugPrintf("#[DEBUG] CONFIGURATION step2: %s\n", configText2)
if vcdShortTest {
t.Skip(acceptanceTestsSkipped)
return
}

resource.Test(t, resource.TestCase{
ProviderFactories: testAccProviders,
Steps: []resource.TestStep{
{
Config: configText1,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("vcd_tm_org.test", "name", t.Name()),
resource.TestCheckResourceAttr("vcd_tm_org.test", "display_name", "terraform-test"),
resource.TestCheckResourceAttr("vcd_tm_org.test", "description", "terraform test"),
resource.TestCheckResourceAttr("vcd_tm_org.test", "is_enabled", "true"),
resource.TestCheckResourceAttr("vcd_tm_org.test", "is_subprovider", "false"),
resource.TestMatchResourceAttr("vcd_tm_org.test", "managed_by_id", regexp.MustCompile("^urn:vcloud:org:")),
resource.TestCheckResourceAttr("vcd_tm_org.test", "managed_by_name", "System"),
resource.TestCheckResourceAttr("vcd_tm_org.test", "is_classic_tenant", "true"),
),
},
{
Config: configText2,
Check: resource.ComposeTestCheckFunc(
resourceFieldsEqual("vcd_tm_org.test", "data.vcd_tm_org.test", nil),
),
},
{
ResourceName: "vcd_tm_org.test",
ImportState: true,
ImportStateVerify: true,
ImportStateId: params["Testname"].(string),
},
},
})

postTestChecks(t)
}

const testAccVcdTmOrgClassicStep1 = `
resource "vcd_tm_org" "test" {
name = "{{.Testname}}"
display_name = "terraform-test"
description = "terraform test"
is_enabled = true
is_classic_tenant = true
}
resource "vcd_tm_org" "test2" {
name = "{{.Testname}}2"
display_name = "terraform-test"
description = "terraform test"
is_enabled = true
is_classic_tenant = true
}
`

const testAccVcdTmOrgClassicStep2 = testAccVcdTmOrgClassicStep1 + `
data "vcd_tm_org" "test" {
name = vcd_tm_org.test.name
}
`
19 changes: 10 additions & 9 deletions website/docs/r/tm_org.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,23 @@ The following arguments are supported:
* `name` - (Required) A name for Organization with which users log in to it as it will be used in
the URL. The Org must be disabled to or transition from previous disabled state
(`is_enabled=false`) to change a name because it changes tenant login URL
* `display_name` - (Required) A human readable name for Organization
* `display_name` - (Required) A human-readable name for Organization
* `description` - (Optional) An optional description for Organization
* `is_enabled` - (Optional) Defines if Organization is enabled. Default `true`. **Note:**
Organization has to be disabled before removal and this resource will automatically disable it if
the resource is destroyed.
* `is_subprovider` - (Optional) Enables this Organization to manage other Organizations. **Note**:
This value cannot updated as there may be any number of Rights Bundles granting sub-provider rights
This value cannot be updated as there may be any number of Rights Bundles granting sub-provider rights
to this Org. Instead, unpublish any rights bundles that have the `Org Traverse` right from this Org.
This can be toggled to true to automatically perform the following steps:
* Publish the Default Sub-Provider Entitlement Rights Bundle to the Organization
* Publish the Sub-Provider Administrator global role (if it exists) to the Organization
* Create a Default Rights Bundle in the Organization containing all publishable rights that are
currently published to the Organization and mark that Rights Bundle as publish all.
* Clone all default roles currently published to the Organization into Global Roles in the
Organization and marks them all publish all.
* Publish the Default Sub-Provider Entitlement Rights Bundle to the Organization
* Publish the Sub-Provider Administrator global role (if it exists) to the Organization
* Create a Default Rights Bundle in the Organization containing all publishable rights that are
currently published to the Organization and mark that Rights Bundle as publish all.
* Clone all default roles currently published to the Organization into Global Roles in the
Organization and marks them all publish all.
* `is_classic_tenant` - (Optional) Defines if this Organization is a classic VRA style tenant. Defaults to `false`. Cannot be
changed after creation (changing it will force the re-creation of the Organization)

## Attribute Reference

Expand All @@ -70,7 +72,6 @@ The following attributes are exported on this resource:
* `disk_count` - Number of disks belonging to this Organization
* `can_publish` - Defines if this Organization can publish catalogs externally
* `directly_managed_org_count` - Number of directly managed Organizations
* `is_classic_tenant` - Defines if this Organization is a classic VRA style tenant

## Importing

Expand Down

0 comments on commit d7eebcf

Please sign in to comment.