From 119d4d8e6f1089fa6152f2e99d9f453daf44bbcb Mon Sep 17 00:00:00 2001 From: arcturusZhang Date: Mon, 3 Aug 2020 15:27:11 +0800 Subject: [PATCH 1/4] Add identity support for postgre server resource and data source --- .teamcity/components/generated/services.kt | 1 + .../postgres/postgresql_server_data_source.go | 27 ++++++ .../postgres/postgresql_server_resource.go | 85 ++++++++++++++++--- .../tests/postgresql_server_resource_test.go | 50 +++++++++++ .../docs/d/postgresql_server.html.markdown | 12 +++ .../docs/r/postgresql_server.html.markdown | 20 ++++- 6 files changed, 181 insertions(+), 14 deletions(-) diff --git a/.teamcity/components/generated/services.kt b/.teamcity/components/generated/services.kt index dfca6b2f203f..69be66a697d0 100644 --- a/.teamcity/components/generated/services.kt +++ b/.teamcity/components/generated/services.kt @@ -73,6 +73,7 @@ var services = mapOf( "storage" to "Storage", "streamanalytics" to "Stream Analytics", "subscription" to "Subscription", + "synapse" to "Synapse", "iottimeseriesinsights" to "Time Series Insights", "trafficmanager" to "Traffic Manager", "web" to "Web" diff --git a/azurerm/internal/services/postgres/postgresql_server_data_source.go b/azurerm/internal/services/postgres/postgresql_server_data_source.go index 1fec26075e60..694895f17a8c 100644 --- a/azurerm/internal/services/postgres/postgresql_server_data_source.go +++ b/azurerm/internal/services/postgres/postgresql_server_data_source.go @@ -53,6 +53,29 @@ func dataSourcePostgreSqlServer() *schema.Resource { Computed: true, }, + "identity": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Computed: true, + }, + + "principal_id": { + Type: schema.TypeString, + Computed: true, + }, + + "tenant_id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "tags": tags.SchemaDataSource(), }, } @@ -85,6 +108,10 @@ func dataSourceArmPostgreSqlServerRead(d *schema.ResourceData, meta interface{}) d.Set("location", azure.NormalizeLocation(*location)) } + if err := d.Set("identity", flattenServerIdentity(resp.Identity)); err != nil { + return fmt.Errorf("setting `identity`: %+v", err) + } + if props := resp.ServerProperties; props != nil { d.Set("fqdn", props.FullyQualifiedDomainName) d.Set("version", props.Version) diff --git a/azurerm/internal/services/postgres/postgresql_server_resource.go b/azurerm/internal/services/postgres/postgresql_server_resource.go index 936133227dd7..b88bf1f63cb9 100644 --- a/azurerm/internal/services/postgres/postgresql_server_resource.go +++ b/azurerm/internal/services/postgres/postgresql_server_resource.go @@ -17,7 +17,6 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/postgres/parse" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/postgres/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" @@ -217,6 +216,33 @@ func resourceArmPostgreSQLServer() *schema.Resource { ValidateFunc: validate.PostgresServerServerID, }, + "identity": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(postgresql.SystemAssigned), + }, false), + }, + + "principal_id": { + Type: schema.TypeString, + Computed: true, + }, + + "tenant_id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "infrastructure_encryption_enabled": { Type: schema.TypeBool, Optional: true, @@ -379,17 +405,15 @@ func resourceArmPostgreSQLServerCreate(d *schema.ResourceData, meta interface{}) location := azure.NormalizeLocation(d.Get("location").(string)) resourceGroup := d.Get("resource_group_name").(string) - if features.ShouldResourcesBeImported() { - existing, err := client.Get(ctx, resourceGroup, name) - if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("checking for presence of existing PostgreSQL Server %q (Resource Group %q): %+v", name, resourceGroup, err) - } + existing, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("checking for presence of existing PostgreSQL Server %q (Resource Group %q): %+v", name, resourceGroup, err) } + } - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_postgresql_server", *existing.ID) - } + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_postgresql_server", *existing.ID) } mode := postgresql.CreateMode(d.Get("create_mode").(string)) @@ -492,6 +516,7 @@ func resourceArmPostgreSQLServerCreate(d *schema.ResourceData, meta interface{}) } server := postgresql.ServerForCreate{ + Identity: expandServerIdentity(d.Get("identity").([]interface{})), Location: &location, Properties: props, Sku: sku, @@ -566,6 +591,7 @@ func resourceArmPostgreSQLServerUpdate(d *schema.ResourceData, meta interface{}) } properties := postgresql.ServerUpdateParameters{ + Identity: expandServerIdentity(d.Get("identity").([]interface{})), ServerUpdateParametersProperties: &postgresql.ServerUpdateParametersProperties{ AdministratorLoginPassword: utils.String(d.Get("administrator_login_password").(string)), PublicNetworkAccess: publicAccess, @@ -638,6 +664,10 @@ func resourceArmPostgreSQLServerRead(d *schema.ResourceData, meta interface{}) e tier = sku.Tier } + if err := d.Set("identity", flattenServerIdentity(resp.Identity)); err != nil { + return fmt.Errorf("setting `identity`: %+v", err) + } + if props := resp.ServerProperties; props != nil { d.Set("administrator_login", props.AdministratorLogin) d.Set("ssl_enforcement", string(props.SslEnforcement)) @@ -881,3 +911,38 @@ func flattenSecurityAlertPolicy(props *postgresql.SecurityAlertPolicyProperties, return []interface{}{block} } + +func expandServerIdentity(input []interface{}) *postgresql.ResourceIdentity { + if len(input) == 0 { + return nil + } + + v := input[0].(map[string]interface{}) + return &postgresql.ResourceIdentity{ + Type: postgresql.IdentityType(v["type"].(string)), + } +} + +func flattenServerIdentity(input *postgresql.ResourceIdentity) []interface{} { + if input == nil { + return []interface{}{} + } + + principalID := "" + if input.PrincipalID != nil { + principalID = input.PrincipalID.String() + } + + tenantID := "" + if input.TenantID != nil { + tenantID = input.TenantID.String() + } + + return []interface{}{ + map[string]interface{}{ + "type": string(input.Type), + "principal_id": principalID, + "tenant_id": tenantID, + }, + } +} diff --git a/azurerm/internal/services/postgres/tests/postgresql_server_resource_test.go b/azurerm/internal/services/postgres/tests/postgresql_server_resource_test.go index a5318eac2896..9baa0c789502 100644 --- a/azurerm/internal/services/postgres/tests/postgresql_server_resource_test.go +++ b/azurerm/internal/services/postgres/tests/postgresql_server_resource_test.go @@ -145,6 +145,24 @@ func TestAccAzureRMPostgreSQLServer_basicEleven(t *testing.T) { }) } +func TestAccAzureRMPostgreSQLServer_basicWithIdentity(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_postgresql_server", "test") + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMPostgreSQLServerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMPostgreSQLServer_basicWithIdentity(data, "11"), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPostgreSQLServerExists(data.ResourceName), + ), + }, + data.ImportStep("administrator_login_password"), + }, + }) +} + func TestAccAzureRMPostgreSQLServer_autogrowOnly(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_postgresql_server", "test") @@ -481,6 +499,38 @@ func testAccAzureRMPostgreSQLServer_basic(data acceptance.TestData, version stri return testAccAzureRMPostgreSQLServer_template(data, "B_Gen5_1", version) } +func testAccAzureRMPostgreSQLServer_basicWithIdentity(data acceptance.TestData, version string) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-psql-%d" + location = "%s" +} + +resource "azurerm_postgresql_server" "test" { + name = "acctest-psql-server-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + administrator_login = "acctestun" + administrator_login_password = "H@Sh1CoR3!" + + sku_name = "B_Gen5_1" + version = "%s" + storage_mb = 51200 + + ssl_enforcement_enabled = true + + identity { + type = "SystemAssigned" + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, version) +} + func testAccAzureRMPostgreSQLServer_mo(data acceptance.TestData, version string) string { return testAccAzureRMPostgreSQLServer_template(data, "MO_Gen5_2", version) } diff --git a/website/docs/d/postgresql_server.html.markdown b/website/docs/d/postgresql_server.html.markdown index be8059d7b2bb..90e57c9322cc 100644 --- a/website/docs/d/postgresql_server.html.markdown +++ b/website/docs/d/postgresql_server.html.markdown @@ -35,6 +35,8 @@ output "postgresql_server_id" { * `fqdn` - The fully qualified domain name of the PostgreSQL Server. +* `identity` - An `identity` block as defined below. + * `version` - The version of the PostgreSQL Server. * `administrator_login` - The administrator username of the PostgreSQL Server. @@ -43,6 +45,16 @@ output "postgresql_server_id" { * `tags` - A mapping of tags assigned to the resource. +--- + +An `identity` block exports the following: + +* `principal_id` - The ID of the System Managed Service Principal assigned to the PostgreSQL Server. + +* `tenant_id` - The ID of the Tenant of the System Managed Service Principal assigned to the PostgreSQL Server. + +* `type` - The identity type of the Managed Identity assigned to the PostgreSQL Server. + ## Timeouts The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: diff --git a/website/docs/r/postgresql_server.html.markdown b/website/docs/r/postgresql_server.html.markdown index 8794a5022761..ef1061a5bad0 100644 --- a/website/docs/r/postgresql_server.html.markdown +++ b/website/docs/r/postgresql_server.html.markdown @@ -13,10 +13,6 @@ Manages a PostgreSQL Server. ## Example Usage ```hcl -provider "azurerm" { - features {} -} - resource "azurerm_resource_group" "example" { name = "example-resources" location = "West Europe" @@ -72,6 +68,8 @@ The following arguments are supported: * `geo_redundant_backup_enabled` - (Optional) Turn Geo-redundant server backups on/off. This allows you to choose between locally redundant or geo-redundant backup storage in the General Purpose and Memory Optimized tiers. When the backups are stored in geo-redundant backup storage, they are not only stored within the region in which your server is hosted, but are also replicated to a paired data center. This provides better protection and ability to restore your server in a different region in the event of a disaster. This is not support for the Basic tier. +* `identity` - (Optional) An `identity` block as defined below. + * `infrastructure_encryption_enabled` - (Optional) Whether or not infrastructure is encrypted for this server. Defaults to `false`. Changing this forces a new resource to be created. ~> **NOTE:** This property is currently still in development and not supported by Microsoft. If the `infrastructure_encryption_enabled` attribute is set to `true` the postgreSQL instance will incur a substantial performance degradation due to a second encryption pass on top of the existing default encryption that is already provided by Azure Storage. It is strongly suggested to leave this value `false` as not doing so can lead to unclear error messages. @@ -92,6 +90,12 @@ The following arguments are supported: --- +A `identity` block supports the following: + +* `type` - (Required) The Type of Identity which should be used for this PostgreSQL Server. At this time the only possible value is `SystemAssigned`. + +--- + a `threat_detection_policy` block supports the following: * `enabled` - (Required) Is the policy enabled? @@ -117,6 +121,14 @@ The following attributes are exported: * `fqdn` - The FQDN of the PostgreSQL Server. +--- + +A `identity` block exports the following: + +* `principal_id` - The (Client) ID of the Service Principal. + +* `tenant_id` - The ID of the Tenant the Service Principal is assigned in. + ## Timeouts The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: From de9139d14c7afbb866771087e905a1eb27b24f3c Mon Sep 17 00:00:00 2001 From: arcturusZhang Date: Mon, 3 Aug 2020 15:34:40 +0800 Subject: [PATCH 2/4] gofmt --- .../services/postgres/postgresql_server_data_source.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/azurerm/internal/services/postgres/postgresql_server_data_source.go b/azurerm/internal/services/postgres/postgresql_server_data_source.go index 694895f17a8c..b0c38299f9bc 100644 --- a/azurerm/internal/services/postgres/postgresql_server_data_source.go +++ b/azurerm/internal/services/postgres/postgresql_server_data_source.go @@ -59,17 +59,17 @@ func dataSourcePostgreSqlServer() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "type": { - Type: schema.TypeString, + Type: schema.TypeString, Computed: true, }, "principal_id": { - Type: schema.TypeString, + Type: schema.TypeString, Computed: true, }, "tenant_id": { - Type: schema.TypeString, + Type: schema.TypeString, Computed: true, }, }, From e976e8713374974f722babfe378f5bccc32a9676 Mon Sep 17 00:00:00 2001 From: arcturusZhang Date: Mon, 10 Aug 2020 10:39:11 +0800 Subject: [PATCH 3/4] resolve comments --- website/docs/r/postgresql_server.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/postgresql_server.html.markdown b/website/docs/r/postgresql_server.html.markdown index ef1061a5bad0..d7df1a062e30 100644 --- a/website/docs/r/postgresql_server.html.markdown +++ b/website/docs/r/postgresql_server.html.markdown @@ -125,7 +125,7 @@ The following attributes are exported: A `identity` block exports the following: -* `principal_id` - The (Client) ID of the Service Principal. +* `principal_id` - The Client ID of the Service Principal assigned to this PostgreSQL Server. * `tenant_id` - The ID of the Tenant the Service Principal is assigned in. From db1e00b40c6acc04d65ccd9d0b9afdc41a23af6d Mon Sep 17 00:00:00 2001 From: arcturusZhang Date: Mon, 10 Aug 2020 14:47:33 +0800 Subject: [PATCH 4/4] Add a missing entry of the computed identity --- website/docs/r/postgresql_server.html.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/docs/r/postgresql_server.html.markdown b/website/docs/r/postgresql_server.html.markdown index d7df1a062e30..eb2630bda987 100644 --- a/website/docs/r/postgresql_server.html.markdown +++ b/website/docs/r/postgresql_server.html.markdown @@ -121,6 +121,8 @@ The following attributes are exported: * `fqdn` - The FQDN of the PostgreSQL Server. +* `identity` - An `identity` block as documented below. + --- A `identity` block exports the following: