Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update azurerm_postgresql_server - Add identity support #8044

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
},
}
Expand Down Expand Up @@ -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)
Expand Down
85 changes: 75 additions & 10 deletions azurerm/internal/services/postgres/postgresql_server_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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,
},
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand Down Expand Up @@ -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)
}
Expand Down
12 changes: 12 additions & 0 deletions website/docs/d/postgresql_server.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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:
Expand Down
22 changes: 18 additions & 4 deletions website/docs/r/postgresql_server.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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.
Expand All @@ -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?
Expand All @@ -117,6 +121,16 @@ 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:

* `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.

## Timeouts

The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions:
Expand Down