Skip to content

Commit

Permalink
azurerm_[linux|windows]_virtual_machine_scale_set - support for `os…
Browse files Browse the repository at this point in the history
…_image_notification` property

Signed-off-by: Mathieu Ouellet <[email protected]>
  • Loading branch information
mouellet committed Aug 25, 2024
1 parent d0f916e commit a22c615
Show file tree
Hide file tree
Showing 7 changed files with 323 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -357,14 +357,28 @@ func resourceLinuxVirtualMachineScaleSetCreate(d *pluginsdk.ResourceData, meta i
return fmt.Errorf("an `eviction_policy` must be specified when `priority` is set to `Spot`")
}

var osImageNotificationProfile *virtualmachinescalesets.OSImageNotificationProfile
var terminateNotificationProfile *virtualmachinescalesets.TerminateNotificationProfile

if v, ok := d.GetOk("os_image_notification"); ok {
osImageNotificationProfile = ExpandVirtualMachineScaleSetOsImageNotificationProfile(v.([]interface{}))
}

if !features.FourPointOhBeta() {
if v, ok := d.GetOk("terminate_notification"); ok {
virtualMachineProfile.ScheduledEventsProfile = ExpandVirtualMachineScaleSetScheduledEventsProfile(v.([]interface{}))
terminateNotificationProfile = ExpandVirtualMachineScaleSetTerminateNotificationProfile(v.([]interface{}))
}
}

if v, ok := d.GetOk("termination_notification"); ok {
virtualMachineProfile.ScheduledEventsProfile = ExpandVirtualMachineScaleSetScheduledEventsProfile(v.([]interface{}))
terminateNotificationProfile = ExpandVirtualMachineScaleSetTerminateNotificationProfile(v.([]interface{}))
}

if terminateNotificationProfile != nil || osImageNotificationProfile != nil {
virtualMachineProfile.ScheduledEventsProfile = &virtualmachinescalesets.ScheduledEventsProfile{
OsImageNotificationProfile: osImageNotificationProfile,
TerminateNotificationProfile: terminateNotificationProfile,
}
}

automaticRepairsPolicyRaw := d.Get("automatic_instance_repair").([]interface{})
Expand Down Expand Up @@ -706,16 +720,29 @@ func resourceLinuxVirtualMachineScaleSetUpdate(d *pluginsdk.ResourceData, meta i

updateProps.ScaleInPolicy = updateScaleInPolicy
}
}

var osImageNotificationProfile *virtualmachinescalesets.OSImageNotificationProfile
var terminateNotificationProfile *virtualmachinescalesets.TerminateNotificationProfile

if d.HasChange("os_image_notification") {
osImageNotificationProfile = ExpandVirtualMachineScaleSetOsImageNotificationProfile(d.Get("os_image_notification").([]interface{}))
}

if !features.FourPointOhBeta() {
if d.HasChange("terminate_notification") {
notificationRaw := d.Get("terminate_notification").([]interface{})
updateProps.VirtualMachineProfile.ScheduledEventsProfile = ExpandVirtualMachineScaleSetScheduledEventsProfile(notificationRaw)
terminateNotificationProfile = ExpandVirtualMachineScaleSetTerminateNotificationProfile(d.Get("terminate_notification").([]interface{}))
}
}

if d.HasChange("termination_notification") {
notificationRaw := d.Get("termination_notification").([]interface{})
updateProps.VirtualMachineProfile.ScheduledEventsProfile = ExpandVirtualMachineScaleSetScheduledEventsProfile(notificationRaw)
terminateNotificationProfile = ExpandVirtualMachineScaleSetTerminateNotificationProfile(d.Get("termination_notification").([]interface{}))
}

if osImageNotificationProfile != nil || terminateNotificationProfile != nil {
updateProps.VirtualMachineProfile.ScheduledEventsProfile = &virtualmachinescalesets.ScheduledEventsProfile{
OsImageNotificationProfile: osImageNotificationProfile,
TerminateNotificationProfile: terminateNotificationProfile,
}
}

if d.HasChange("encryption_at_host_enabled") {
Expand Down Expand Up @@ -1027,16 +1054,18 @@ func resourceLinuxVirtualMachineScaleSetRead(d *pluginsdk.ResourceData, meta int
d.Set("health_probe_id", healthProbeId)
}

if !features.FourPointOhBeta() {
if scheduleProfile := profile.ScheduledEventsProfile; scheduleProfile != nil {
if err := d.Set("terminate_notification", FlattenVirtualMachineScaleSetScheduledEventsProfile(scheduleProfile)); err != nil {
if scheduleProfile := profile.ScheduledEventsProfile; scheduleProfile != nil {
if err := d.Set("os_image_notification", FlattenVirtualMachineScaleSetOsImageNotificationProfile(scheduleProfile.OsImageNotificationProfile)); err != nil {
return fmt.Errorf("setting `os_image_notification`: %+v", err)
}

if !features.FourPointOhBeta() {
if err := d.Set("terminate_notification", FlattenVirtualMachineScaleSetTerminateNotificationProfile(scheduleProfile.TerminateNotificationProfile)); err != nil {
return fmt.Errorf("setting `terminate_notification`: %+v", err)
}
}
}

if scheduleProfile := profile.ScheduledEventsProfile; scheduleProfile != nil {
if err := d.Set("termination_notification", FlattenVirtualMachineScaleSetScheduledEventsProfile(scheduleProfile)); err != nil {
if err := d.Set("termination_notification", FlattenVirtualMachineScaleSetTerminateNotificationProfile(scheduleProfile.TerminateNotificationProfile)); err != nil {
return fmt.Errorf("setting `termination_notification`: %+v", err)
}
}
Expand Down Expand Up @@ -1439,6 +1468,8 @@ func resourceLinuxVirtualMachineScaleSetSchema() map[string]*pluginsdk.Schema {

"spot_restore": VirtualMachineScaleSetSpotRestorePolicySchema(),

"os_image_notification": VirtualMachineScaleSetOsImageNotificationSchema(),

"termination_notification": VirtualMachineScaleSetTerminationNotificationSchema(),

"zones": commonschema.ZonesMultipleOptionalForceNew(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,37 @@ func TestAccLinuxVirtualMachineScaleSet_otherScaleIn(t *testing.T) {
})
}

func TestAccLinuxVirtualMachineScaleSet_otherOsImageNotification(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_linux_virtual_machine_scale_set", "test")
r := LinuxVirtualMachineScaleSetResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.otherOsImageNotification(data, true),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("os_image_notification.#").HasValue("1"),
),
},
data.ImportStep("admin_password"),
{
Config: r.otherOsImageNotification(data, false),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("admin_password"),
{
Config: r.otherOsImageNotification(data, true),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("os_image_notification.#").HasValue("1"),
),
},
data.ImportStep("admin_password"),
})
}

func TestAccLinuxVirtualMachineScaleSet_otherTerminationNotification(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_linux_virtual_machine_scale_set", "test")
r := LinuxVirtualMachineScaleSetResource{}
Expand Down Expand Up @@ -2294,6 +2325,55 @@ resource "azurerm_linux_virtual_machine_scale_set" "test" {
`, r.template(data), data.RandomInteger, enabled)
}

func (r LinuxVirtualMachineScaleSetResource) otherOsImageNotification(data acceptance.TestData, enabled bool) string {
osImageNotificationConfig := ""
if enabled {
osImageNotificationConfig = "os_image_notification {}"
}

return fmt.Sprintf(`
%s
resource "azurerm_linux_virtual_machine_scale_set" "test" {
name = "acctestvmss-%d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
sku = "Standard_F2"
instances = 1
admin_username = "adminuser"
admin_password = "P@ssword1234!"
disable_password_authentication = false
source_image_reference {
publisher = "Canonical"
offer = "0001-com-ubuntu-server-jammy"
sku = "22_04-lts"
version = "latest"
}
os_disk {
disk_size_gb = 30
storage_account_type = "Standard_LRS"
caching = "ReadWrite"
}
network_interface {
name = "example"
primary = true
ip_configuration {
name = "internal"
primary = true
subnet_id = azurerm_subnet.test.id
}
}
%s
}
`, r.template(data), data.RandomInteger, osImageNotificationConfig)
}

func (r LinuxVirtualMachineScaleSetResource) otherTerminationNotification(data acceptance.TestData, enabled bool) string {
return fmt.Sprintf(`
%s
Expand Down
73 changes: 62 additions & 11 deletions internal/services/compute/virtual_machine_scale_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -1834,6 +1834,26 @@ func FlattenVirtualMachineScaleSetRollingUpgradePolicy(input *virtualmachinescal
}
}

func VirtualMachineScaleSetOsImageNotificationSchema() *pluginsdk.Schema {
return &pluginsdk.Schema{
Type: pluginsdk.TypeList,
Optional: true,
MaxItems: 1,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"timeout": {
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
"PT15M",
}, false),
Default: "PT15M",
},
},
},
}
}

// TODO remove VirtualMachineScaleSetTerminateNotificationSchema in 4.0
func VirtualMachineScaleSetTerminateNotificationSchema() *pluginsdk.Schema {
return &pluginsdk.Schema{
Expand Down Expand Up @@ -1889,7 +1909,23 @@ func VirtualMachineScaleSetTerminationNotificationSchema() *pluginsdk.Schema {
}
}

func ExpandVirtualMachineScaleSetScheduledEventsProfile(input []interface{}) *virtualmachinescalesets.ScheduledEventsProfile {
func ExpandVirtualMachineScaleSetOsImageNotificationProfile(input []interface{}) *virtualmachinescalesets.OSImageNotificationProfile {
if len(input) == 0 {
return &virtualmachinescalesets.OSImageNotificationProfile{
Enable: pointer.To(false),
}
}

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

return &virtualmachinescalesets.OSImageNotificationProfile{
Enable: pointer.To(true),
NotBeforeTimeout: &timeout,
}
}

func ExpandVirtualMachineScaleSetTerminateNotificationProfile(input []interface{}) *virtualmachinescalesets.TerminateNotificationProfile {
if len(input) == 0 {
return nil
}
Expand All @@ -1898,26 +1934,41 @@ func ExpandVirtualMachineScaleSetScheduledEventsProfile(input []interface{}) *vi
enabled := raw["enabled"].(bool)
timeout := raw["timeout"].(string)

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

func FlattenVirtualMachineScaleSetOsImageNotificationProfile(input *virtualmachinescalesets.OSImageNotificationProfile) []interface{} {
if input == nil || !pointer.From(input.Enable) {
return nil
}

timeout := "PT15M"
if input.NotBeforeTimeout != nil {
timeout = *input.NotBeforeTimeout
}

return []interface{}{
map[string]interface{}{
"timeout": timeout,
},
}
}

func FlattenVirtualMachineScaleSetScheduledEventsProfile(input *virtualmachinescalesets.ScheduledEventsProfile) []interface{} {
// if enabled is set to false, there will be no ScheduledEventsProfile in response, to avoid plan non empty when
func FlattenVirtualMachineScaleSetTerminateNotificationProfile(input *virtualmachinescalesets.TerminateNotificationProfile) []interface{} {
// if enabled is set to false, there will be no TerminateNotificationProfile 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
if input != nil && input.Enable != nil {
enabled = *input.Enable
}

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

return []interface{}{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,14 +358,28 @@ func resourceWindowsVirtualMachineScaleSetCreate(d *pluginsdk.ResourceData, meta
virtualMachineProfile.OsProfile.WindowsConfiguration.TimeZone = pointer.To(v.(string))
}

var osImageNotificationProfile *virtualmachinescalesets.OSImageNotificationProfile
var terminateNotificationProfile *virtualmachinescalesets.TerminateNotificationProfile

if v, ok := d.GetOk("os_image_notification"); ok {
osImageNotificationProfile = ExpandVirtualMachineScaleSetOsImageNotificationProfile(v.([]interface{}))
}

if !features.FourPointOhBeta() {
if v, ok := d.GetOk("terminate_notification"); ok {
virtualMachineProfile.ScheduledEventsProfile = ExpandVirtualMachineScaleSetScheduledEventsProfile(v.([]interface{}))
terminateNotificationProfile = ExpandVirtualMachineScaleSetTerminateNotificationProfile(v.([]interface{}))
}
}

if v, ok := d.GetOk("termination_notification"); ok {
virtualMachineProfile.ScheduledEventsProfile = ExpandVirtualMachineScaleSetScheduledEventsProfile(v.([]interface{}))
terminateNotificationProfile = ExpandVirtualMachineScaleSetTerminateNotificationProfile(v.([]interface{}))
}

if terminateNotificationProfile != nil || osImageNotificationProfile != nil {
virtualMachineProfile.ScheduledEventsProfile = &virtualmachinescalesets.ScheduledEventsProfile{
OsImageNotificationProfile: osImageNotificationProfile,
TerminateNotificationProfile: terminateNotificationProfile,
}
}

if v, ok := d.GetOk("user_data"); ok {
Expand Down Expand Up @@ -717,16 +731,29 @@ func resourceWindowsVirtualMachineScaleSetUpdate(d *pluginsdk.ResourceData, meta

updateProps.ScaleInPolicy = updateScaleInPolicy
}
}

var osImageNotificationProfile *virtualmachinescalesets.OSImageNotificationProfile
var terminateNotificationProfile *virtualmachinescalesets.TerminateNotificationProfile

if d.HasChange("os_image_notification") {
osImageNotificationProfile = ExpandVirtualMachineScaleSetOsImageNotificationProfile(d.Get("os_image_notification").([]interface{}))
}

if !features.FourPointOhBeta() {
if d.HasChange("terminate_notification") {
notificationRaw := d.Get("terminate_notification").([]interface{})
updateProps.VirtualMachineProfile.ScheduledEventsProfile = ExpandVirtualMachineScaleSetScheduledEventsProfile(notificationRaw)
terminateNotificationProfile = ExpandVirtualMachineScaleSetTerminateNotificationProfile(d.Get("terminate_notification").([]interface{}))
}
}

if d.HasChange("termination_notification") {
notificationRaw := d.Get("termination_notification").([]interface{})
updateProps.VirtualMachineProfile.ScheduledEventsProfile = ExpandVirtualMachineScaleSetScheduledEventsProfile(notificationRaw)
terminateNotificationProfile = ExpandVirtualMachineScaleSetTerminateNotificationProfile(d.Get("termination_notification").([]interface{}))
}

if osImageNotificationProfile != nil || terminateNotificationProfile != nil {
updateProps.VirtualMachineProfile.ScheduledEventsProfile = &virtualmachinescalesets.ScheduledEventsProfile{
OsImageNotificationProfile: osImageNotificationProfile,
TerminateNotificationProfile: terminateNotificationProfile,
}
}

if d.HasChange("encryption_at_host_enabled") {
Expand Down Expand Up @@ -1080,16 +1107,18 @@ func resourceWindowsVirtualMachineScaleSetRead(d *pluginsdk.ResourceData, meta i
d.Set("health_probe_id", healthProbeId)
}

if !features.FourPointOhBeta() {
if scheduleProfile := profile.ScheduledEventsProfile; scheduleProfile != nil {
if err := d.Set("terminate_notification", FlattenVirtualMachineScaleSetScheduledEventsProfile(scheduleProfile)); err != nil {
if scheduleProfile := profile.ScheduledEventsProfile; scheduleProfile != nil {
if err := d.Set("os_image_notification", FlattenVirtualMachineScaleSetOsImageNotificationProfile(scheduleProfile.OsImageNotificationProfile)); err != nil {
return fmt.Errorf("setting `os_image_notification`: %+v", err)
}

if !features.FourPointOhBeta() {
if err := d.Set("terminate_notification", FlattenVirtualMachineScaleSetTerminateNotificationProfile(scheduleProfile.TerminateNotificationProfile)); err != nil {
return fmt.Errorf("setting `terminate_notification`: %+v", err)
}
}
}

if scheduleProfile := profile.ScheduledEventsProfile; scheduleProfile != nil {
if err := d.Set("termination_notification", FlattenVirtualMachineScaleSetScheduledEventsProfile(scheduleProfile)); err != nil {
if err := d.Set("termination_notification", FlattenVirtualMachineScaleSetTerminateNotificationProfile(scheduleProfile.TerminateNotificationProfile)); err != nil {
return fmt.Errorf("setting `termination_notification`: %+v", err)
}
}
Expand Down Expand Up @@ -1496,6 +1525,8 @@ func resourceWindowsVirtualMachineScaleSetSchema() map[string]*pluginsdk.Schema

"spot_restore": VirtualMachineScaleSetSpotRestorePolicySchema(),

"os_image_notification": VirtualMachineScaleSetOsImageNotificationSchema(),

"termination_notification": VirtualMachineScaleSetTerminationNotificationSchema(),

"zones": commonschema.ZonesMultipleOptionalForceNew(),
Expand Down
Loading

0 comments on commit a22c615

Please sign in to comment.