Skip to content

Commit

Permalink
r\linux_virtual_machine r\windows_virual_machine: Add support for…
Browse files Browse the repository at this point in the history
… `termination_notification` (#14933)
  • Loading branch information
myc2h6o authored Mar 22, 2022
1 parent 1d8d0ad commit 97b5128
Show file tree
Hide file tree
Showing 7 changed files with 395 additions and 0 deletions.
19 changes: 19 additions & 0 deletions internal/services/compute/linux_virtual_machine_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ func resourceLinuxVirtualMachine() *pluginsdk.Resource {

"tags": tags.Schema(),

"termination_notification": virtualMachineTerminationNotificationSchema(),

"user_data": {
Type: pluginsdk.TypeString,
Optional: true,
Expand Down Expand Up @@ -497,6 +499,10 @@ func resourceLinuxVirtualMachineCreate(d *pluginsdk.ResourceData, meta interface
params.VirtualMachineProperties.SecurityProfile.UefiSettings.SecureBootEnabled = utils.Bool(secureBootEnabled.(bool))
}

if v, ok := d.GetOk("termination_notification"); ok {
params.VirtualMachineProperties.ScheduledEventsProfile = expandVirtualMachineScheduledEventsProfile(v.([]interface{}))
}

if vtpmEnabled, ok := d.GetOk("vtpm_enabled"); ok && vtpmEnabled.(bool) {
if params.VirtualMachineProperties.SecurityProfile == nil {
params.VirtualMachineProperties.SecurityProfile = &compute.SecurityProfile{}
Expand Down Expand Up @@ -781,6 +787,12 @@ func resourceLinuxVirtualMachineRead(d *pluginsdk.ResourceData, meta interface{}
}
}

if scheduleProfile := props.ScheduledEventsProfile; scheduleProfile != nil {
if err := d.Set("termination_notification", flattenVirtualMachineScheduledEventsProfile(scheduleProfile)); err != nil {
return fmt.Errorf("setting `termination_notification`: %+v", err)
}
}

encryptionAtHostEnabled := false
vtpmEnabled := false
secureBootEnabled := false
Expand Down Expand Up @@ -1090,6 +1102,13 @@ func resourceLinuxVirtualMachineUpdate(d *pluginsdk.ResourceData, meta interface
update.OsProfile.AllowExtensionOperations = utils.Bool(allowExtensionOperations)
}

if d.HasChange("termination_notification") {
shouldUpdate = true

notificationRaw := d.Get("termination_notification").([]interface{})
update.ScheduledEventsProfile = expandVirtualMachineScheduledEventsProfile(notificationRaw)
}

if d.HasChange("tags") {
shouldUpdate = true

Expand Down
137 changes: 137 additions & 0 deletions internal/services/compute/linux_virtual_machine_resource_other_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,66 @@ func TestAccLinuxVirtualMachine_otherTags(t *testing.T) {
})
}

func TestAccLinuxVirtualMachine_otherTerminationNotification(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_linux_virtual_machine", "test")
r := LinuxVirtualMachineResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
// turn termination notification on
{
Config: r.otherTerminationNotification(data, true),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("termination_notification.#").HasValue("1"),
check.That(data.ResourceName).Key("termination_notification.0.enabled").HasValue("true"),
),
},
data.ImportStep("admin_password"),
// turn termination notification off
{
Config: r.otherTerminationNotification(data, false),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("termination_notification.#").HasValue("1"),
check.That(data.ResourceName).Key("termination_notification.0.enabled").HasValue("false"),
),
},
data.ImportStep("admin_password"),
// turn termination notification on again
{
Config: r.otherTerminationNotification(data, true),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("termination_notification.#").HasValue("1"),
check.That(data.ResourceName).Key("termination_notification.0.enabled").HasValue("true"),
),
},
data.ImportStep("admin_password"),
})
}

func TestAccLinuxVirtualMachine_otherTerminationNotificationTimeout(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_linux_virtual_machine", "test")
r := LinuxVirtualMachineResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.otherTerminationNotification(data, true),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("admin_password"),
{
Config: r.otherTerminationNotificationTimeout(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("admin_password"),
})
}

func TestAccLinuxVirtualMachine_otherUltraSsdDefault(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_linux_virtual_machine", "test")
r := LinuxVirtualMachineResource{}
Expand Down Expand Up @@ -1773,6 +1833,83 @@ resource "azurerm_linux_virtual_machine" "test" {
`, r.template(data), data.RandomInteger)
}

func (r LinuxVirtualMachineResource) otherTerminationNotification(data acceptance.TestData, enabled bool) string {
return fmt.Sprintf(`
%s
resource "azurerm_linux_virtual_machine" "test" {
name = "acctestVM-%d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
size = "Standard_F2"
admin_username = "adminuser"
network_interface_ids = [
azurerm_network_interface.test.id,
]
admin_ssh_key {
username = "adminuser"
public_key = local.first_public_key
}
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "16.04-LTS"
version = "latest"
}
termination_notification {
enabled = %t
}
}
`, r.template(data), data.RandomInteger, enabled)
}

func (r LinuxVirtualMachineResource) otherTerminationNotificationTimeout(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
resource "azurerm_linux_virtual_machine" "test" {
name = "acctestVM-%d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
size = "Standard_F2"
admin_username = "adminuser"
network_interface_ids = [
azurerm_network_interface.test.id,
]
admin_ssh_key {
username = "adminuser"
public_key = local.first_public_key
}
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "16.04-LTS"
version = "latest"
}
termination_notification {
enabled = true
timeout = "PT15M"
}
}
`, r.template(data), data.RandomInteger)
}

func (r LinuxVirtualMachineResource) otherUltraSsd(data acceptance.TestData, ultraSsdEnabled bool) string {
return fmt.Sprintf(`
%s
Expand Down
67 changes: 67 additions & 0 deletions internal/services/compute/virtual_machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2021-11-01/compute"
"github.com/hashicorp/go-azure-helpers/resourcemanager/identity"
azValidate "github.com/hashicorp/terraform-provider-azurerm/helpers/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
Expand Down Expand Up @@ -349,3 +350,69 @@ func flattenVirtualMachineOSDisk(ctx context.Context, disksClient *compute.Disks
},
}, nil
}

func virtualMachineTerminationNotificationSchema() *pluginsdk.Schema {
return &pluginsdk.Schema{
Type: pluginsdk.TypeList,
Optional: true,
Computed: true,
MaxItems: 1,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"enabled": {
Type: pluginsdk.TypeBool,
Required: true,
},
"timeout": {
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: azValidate.ISO8601DurationBetween("PT5M", "PT15M"),
Default: "PT5M",
},
},
},
}
}

func expandVirtualMachineScheduledEventsProfile(input []interface{}) *compute.ScheduledEventsProfile {
if len(input) == 0 {
return &compute.ScheduledEventsProfile{
TerminateNotificationProfile: &compute.TerminateNotificationProfile{
Enable: utils.Bool(false),
},
}
}

raw := input[0].(map[string]interface{})
enabled := raw["enabled"].(bool)
timeout := raw["timeout"].(string)

return &compute.ScheduledEventsProfile{
TerminateNotificationProfile: &compute.TerminateNotificationProfile{
Enable: &enabled,
NotBeforeTimeout: &timeout,
},
}
}

func flattenVirtualMachineScheduledEventsProfile(input *compute.ScheduledEventsProfile) []interface{} {
// if enabled is set to false, there will be no ScheduledEventsProfile in response, to avoid plan non empty when
// a user explicitly set enabled to false, we need to assign a default block to this field

enabled := false
if input != nil && input.TerminateNotificationProfile != nil && input.TerminateNotificationProfile.Enable != nil {
enabled = *input.TerminateNotificationProfile.Enable
}

timeout := "PT5M"
if input != nil && input.TerminateNotificationProfile != nil && input.TerminateNotificationProfile.NotBeforeTimeout != nil {
timeout = *input.TerminateNotificationProfile.NotBeforeTimeout
}

return []interface{}{
map[string]interface{}{
"enabled": enabled,
"timeout": timeout,
},
}
}
19 changes: 19 additions & 0 deletions internal/services/compute/windows_virtual_machine_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@ func resourceWindowsVirtualMachine() *pluginsdk.Resource {

"tags": tags.Schema(),

"termination_notification": virtualMachineTerminationNotificationSchema(),

"timezone": {
Type: pluginsdk.TypeString,
Optional: true,
Expand Down Expand Up @@ -647,6 +649,10 @@ func resourceWindowsVirtualMachineCreate(d *pluginsdk.ResourceData, meta interfa
params.PlatformFaultDomain = utils.Int32(int32(platformFaultDomain))
}

if v, ok := d.GetOk("termination_notification"); ok {
params.VirtualMachineProperties.ScheduledEventsProfile = expandVirtualMachineScheduledEventsProfile(v.([]interface{}))
}

if v, ok := d.GetOk("timezone"); ok {
params.VirtualMachineProperties.OsProfile.WindowsConfiguration.TimeZone = utils.String(v.(string))
}
Expand Down Expand Up @@ -847,6 +853,12 @@ func resourceWindowsVirtualMachineRead(d *pluginsdk.ResourceData, meta interface
}
}

if scheduleProfile := props.ScheduledEventsProfile; scheduleProfile != nil {
if err := d.Set("termination_notification", flattenVirtualMachineScheduledEventsProfile(scheduleProfile)); err != nil {
return fmt.Errorf("setting `termination_notification`: %+v", err)
}
}

encryptionAtHostEnabled := false
vtpmEnabled := false
secureBootEnabled := false
Expand Down Expand Up @@ -1170,6 +1182,13 @@ func resourceWindowsVirtualMachineUpdate(d *pluginsdk.ResourceData, meta interfa
update.Tags = tags.Expand(tagsRaw)
}

if d.HasChange("termination_notification") {
shouldUpdate = true

notificationRaw := d.Get("termination_notification").([]interface{})
update.ScheduledEventsProfile = expandVirtualMachineScheduledEventsProfile(notificationRaw)
}

if d.HasChange("additional_capabilities") {
shouldUpdate = true

Expand Down
Loading

0 comments on commit 97b5128

Please sign in to comment.