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

azurerm_[linux|windows]_virtual_machine_scale_set - support for os_image_notification property #27042

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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 @@ -382,14 +382,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 @@ -735,16 +749,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 @@ -1056,16 +1083,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 @@ -1468,6 +1497,8 @@ func resourceLinuxVirtualMachineScaleSetSchema() map[string]*pluginsdk.Schema {

"spot_restore": VirtualMachineScaleSetSpotRestorePolicySchema(),

"os_image_notification": VirtualMachineScaleSetOsImageNotificationSchema(),

"termination_notification": VirtualMachineScaleSetTerminationNotificationSchema(),

"zones": commonschema.ZonesMultipleOptional(),
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 @@ -1804,6 +1804,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 @@ -1859,7 +1879,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 @@ -1868,26 +1904,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 @@ -383,14 +383,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 @@ -747,16 +761,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 @@ -1110,16 +1137,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 @@ -1526,6 +1555,8 @@ func resourceWindowsVirtualMachineScaleSetSchema() map[string]*pluginsdk.Schema

"spot_restore": VirtualMachineScaleSetSpotRestorePolicySchema(),

"os_image_notification": VirtualMachineScaleSetOsImageNotificationSchema(),

"termination_notification": VirtualMachineScaleSetTerminationNotificationSchema(),

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