Skip to content

Commit

Permalink
Merge pull request #5344 from terraform-providers/e_keyvault_puge_sof…
Browse files Browse the repository at this point in the history
…tdelete

Enhancement: `azurerm_key_vault`: Add support for soft delete, purge protection, and purge on destroy
  • Loading branch information
tombuildsstuff authored Feb 21, 2020
2 parents d4c6dd4 + 7bf15ef commit 2e17f74
Show file tree
Hide file tree
Showing 15 changed files with 1,081 additions and 193 deletions.
6 changes: 6 additions & 0 deletions azurerm/internal/features/user_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package features
type UserFeatures struct {
VirtualMachine VirtualMachineFeatures
VirtualMachineScaleSet VirtualMachineScaleSetFeatures
KeyVault KeyVaultFeatures
}

type VirtualMachineFeatures struct {
Expand All @@ -12,3 +13,8 @@ type VirtualMachineFeatures struct {
type VirtualMachineScaleSetFeatures struct {
RollInstancesWhenRequired bool
}

type KeyVaultFeatures struct {
PurgeSoftDeleteOnDestroy bool
RecoverSoftDeletedKeyVaults bool
}
38 changes: 38 additions & 0 deletions azurerm/internal/provider/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
)

func schemaFeatures() *schema.Schema {
// NOTE: if there's only one nested field these want to be Required (since there's no point
// specifying the block otherwise) - however for 2+ they should be optional
features := map[string]*schema.Schema{
"virtual_machine": {
Type: schema.TypeList,
Expand Down Expand Up @@ -36,6 +38,25 @@ func schemaFeatures() *schema.Schema {
},
},
},

"key_vault": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"recover_soft_deleted_key_vaults": {
Type: schema.TypeBool,
Optional: true,
},

"purge_soft_delete_on_destroy": {
Type: schema.TypeBool,
Optional: true,
},
},
},
},
}

runningAcceptanceTests := os.Getenv("TF_ACC") != ""
Expand Down Expand Up @@ -70,6 +91,10 @@ func expandFeatures(input []interface{}) features.UserFeatures {
VirtualMachineScaleSet: features.VirtualMachineScaleSetFeatures{
RollInstancesWhenRequired: true,
},
KeyVault: features.KeyVaultFeatures{
PurgeSoftDeleteOnDestroy: true,
RecoverSoftDeletedKeyVaults: true,
},
}

if len(input) == 0 || input[0] == nil {
Expand All @@ -78,6 +103,19 @@ func expandFeatures(input []interface{}) features.UserFeatures {

val := input[0].(map[string]interface{})

if raw, ok := val["key_vault"]; ok {
items := raw.([]interface{})
if len(items) > 0 {
keyVaultRaw := items[0].(map[string]interface{})
if v, ok := keyVaultRaw["purge_soft_delete_on_destroy"]; ok {
features.KeyVault.PurgeSoftDeleteOnDestroy = v.(bool)
}
if v, ok := keyVaultRaw["recover_soft_deleted_key_vaults"]; ok {
features.KeyVault.RecoverSoftDeletedKeyVaults = v.(bool)
}
}
}

if raw, ok := val["virtual_machine"]; ok {
items := raw.([]interface{})
if len(items) > 0 {
Expand Down
121 changes: 120 additions & 1 deletion azurerm/internal/provider/features_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ func TestExpandFeatures(t *testing.T) {
Name: "Empty Block",
Input: []interface{}{},
Expected: features.UserFeatures{
KeyVault: features.KeyVaultFeatures{
PurgeSoftDeleteOnDestroy: true,
RecoverSoftDeletedKeyVaults: true,
},
VirtualMachine: features.VirtualMachineFeatures{
DeleteOSDiskOnDeletion: true,
},
Expand All @@ -27,7 +31,7 @@ func TestExpandFeatures(t *testing.T) {
},
},
{
Name: "Complete",
Name: "Complete Enabled",
Input: []interface{}{
map[string]interface{}{
"virtual_machine": []interface{}{
Expand All @@ -40,9 +44,19 @@ func TestExpandFeatures(t *testing.T) {
"roll_instances_when_required": true,
},
},
"key_vault": []interface{}{
map[string]interface{}{
"purge_soft_delete_on_destroy": true,
"recover_soft_deleted_key_vaults": true,
},
},
},
},
Expected: features.UserFeatures{
KeyVault: features.KeyVaultFeatures{
PurgeSoftDeleteOnDestroy: true,
RecoverSoftDeletedKeyVaults: true,
},
VirtualMachine: features.VirtualMachineFeatures{
DeleteOSDiskOnDeletion: true,
},
Expand All @@ -51,6 +65,41 @@ func TestExpandFeatures(t *testing.T) {
},
},
},
{
Name: "Complete Disabled",
Input: []interface{}{
map[string]interface{}{
"virtual_machine": []interface{}{
map[string]interface{}{
"delete_os_disk_on_deletion": false,
},
},
"virtual_machine_scale_set": []interface{}{
map[string]interface{}{
"roll_instances_when_required": false,
},
},
"key_vault": []interface{}{
map[string]interface{}{
"purge_soft_delete_on_destroy": false,
"recover_soft_deleted_key_vaults": false,
},
},
},
},
Expected: features.UserFeatures{
KeyVault: features.KeyVaultFeatures{
PurgeSoftDeleteOnDestroy: false,
RecoverSoftDeletedKeyVaults: false,
},
VirtualMachine: features.VirtualMachineFeatures{
DeleteOSDiskOnDeletion: false,
},
VirtualMachineScaleSet: features.VirtualMachineScaleSetFeatures{
RollInstancesWhenRequired: false,
},
},
},
}

for _, testCase := range testData {
Expand All @@ -62,6 +111,76 @@ func TestExpandFeatures(t *testing.T) {
}
}

func TestExpandFeaturesKeyVault(t *testing.T) {
testData := []struct {
Name string
Input []interface{}
EnvVars map[string]interface{}
Expected features.UserFeatures
}{
{
Name: "Empty Block",
Input: []interface{}{
map[string]interface{}{
"key_vault": []interface{}{},
},
},
Expected: features.UserFeatures{
KeyVault: features.KeyVaultFeatures{
PurgeSoftDeleteOnDestroy: true,
RecoverSoftDeletedKeyVaults: true,
},
},
},
{
Name: "Purge Soft Delete On Destroy and Recover Soft Deleted Key Vaults Enabled",
Input: []interface{}{
map[string]interface{}{
"key_vault": []interface{}{
map[string]interface{}{
"purge_soft_delete_on_destroy": true,
"recover_soft_deleted_key_vaults": true,
},
},
},
},
Expected: features.UserFeatures{
KeyVault: features.KeyVaultFeatures{
PurgeSoftDeleteOnDestroy: true,
RecoverSoftDeletedKeyVaults: true,
},
},
},
{
Name: "Purge Soft Delete On Destroy and Recover Soft Deleted Key Vaults Disabled",
Input: []interface{}{
map[string]interface{}{
"key_vault": []interface{}{
map[string]interface{}{
"purge_soft_delete_on_destroy": false,
"recover_soft_deleted_key_vaults": false,
},
},
},
},
Expected: features.UserFeatures{
KeyVault: features.KeyVaultFeatures{
PurgeSoftDeleteOnDestroy: false,
RecoverSoftDeletedKeyVaults: false,
},
},
},
}

for _, testCase := range testData {
t.Logf("[DEBUG] Test Case: %q", testCase.Name)
result := expandFeatures(testCase.Input)
if !reflect.DeepEqual(result.KeyVault, testCase.Expected.KeyVault) {
t.Fatalf("Expected %+v but got %+v", result.KeyVault, testCase.Expected.KeyVault)
}
}
}

func TestExpandFeaturesVirtualMachine(t *testing.T) {
testData := []struct {
Name string
Expand Down
15 changes: 14 additions & 1 deletion azurerm/internal/services/keyvault/data_source_key_vault.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/set"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/keyvault/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
Expand All @@ -26,7 +27,7 @@ func dataSourceArmKeyVault() *schema.Resource {
"name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: ValidateKeyVaultName,
ValidateFunc: validate.KeyVaultName,
},

"resource_group_name": azure.SchemaResourceGroupNameForDataSource(),
Expand Down Expand Up @@ -141,6 +142,16 @@ func dataSourceArmKeyVault() *schema.Resource {
},
},

"purge_protection_enabled": {
Type: schema.TypeBool,
Computed: true,
},

"soft_delete_enabled": {
Type: schema.TypeBool,
Computed: true,
},

"tags": tags.SchemaDataSource(),
},
}
Expand Down Expand Up @@ -175,6 +186,8 @@ func dataSourceArmKeyVaultRead(d *schema.ResourceData, meta interface{}) error {
d.Set("enabled_for_deployment", props.EnabledForDeployment)
d.Set("enabled_for_disk_encryption", props.EnabledForDiskEncryption)
d.Set("enabled_for_template_deployment", props.EnabledForTemplateDeployment)
d.Set("soft_delete_enabled", props.EnableSoftDelete)
d.Set("purge_protection_enabled", props.EnablePurgeProtection)
d.Set("vault_uri", props.VaultURI)

if sku := props.Sku; sku != nil {
Expand Down
Loading

0 comments on commit 2e17f74

Please sign in to comment.