@@ -110,21 +110,35 @@ func (ec2 *EC2) PostProcess() {
110110 instance .Tenancy = lt .Tenancy
111111 }
112112
113- launchTemplateBlockDeviceMap := make (map [string ]BlockDeviceMapping )
113+ // Iterate the original slices for deterministic order — Go map
114+ // iteration is randomised, and downstream consumers index into this
115+ // slice to name sub-resources, so unstable order produces flaky
116+ // output (instance-defined and LT-only devices can swap positions).
117+ // Maps are only used for lookups during the merge.
118+ //
119+ // TODO: LT-derived block devices currently inherit their address
120+ // from the launch template (e.g. `aws_launch_template.X.block_device_mapping[0]`).
121+ // Downstream the providers package falls back to a synthetic
122+ // `ebs_block_device[N]` name for these because the address doesn't
123+ // start with the instance's. It would be more accurate to surface
124+ // the actual LT-prefixed address so users can see where the device
125+ // is really defined — left for a follow-up since it changes
126+ // user-visible output.
127+ launchTemplateBlockDeviceMap := make (map [string ]BlockDeviceMapping , len (lt .BlockDeviceMappings ))
114128 for _ , blockDevice := range lt .BlockDeviceMappings {
115129 launchTemplateBlockDeviceMap [blockDevice .DeviceName .Value ()] = blockDevice
116130 }
117131
118- instanceBlockDeviceMap := make (map [string ]BlockDeviceMapping )
132+ instanceBlockDeviceNames := make (map [string ]struct {}, len ( instance . BlockDeviceMappings ) )
119133 for _ , blockDevice := range instance .BlockDeviceMappings {
120- instanceBlockDeviceMap [blockDevice .DeviceName .Value ()] = blockDevice
134+ instanceBlockDeviceNames [blockDevice .DeviceName .Value ()] = struct {}{}
121135 }
122136
123- blockDevices := []BlockDeviceMapping {}
137+ blockDevices := make ( []BlockDeviceMapping , 0 , len ( instance . BlockDeviceMappings ) + len ( lt . BlockDeviceMappings ))
124138
125- // merge any defaults from the launch template into existing block devices
126- for name , blockDevice := range instanceBlockDeviceMap {
127- if launchTemplateBlockDevice , ok := launchTemplateBlockDeviceMap [name ]; ok {
139+ // instance-defined first, merging any defaults from the launch template
140+ for _ , blockDevice := range instance . BlockDeviceMappings {
141+ if launchTemplateBlockDevice , ok := launchTemplateBlockDeviceMap [blockDevice . DeviceName . Value () ]; ok {
128142 if blockDevice .EBSVolume .Type .IsDefaultOrEmpty () {
129143 blockDevice .EBSVolume .Type = launchTemplateBlockDevice .EBSVolume .Type
130144 }
@@ -141,9 +155,9 @@ func (ec2 *EC2) PostProcess() {
141155 blockDevices = append (blockDevices , blockDevice )
142156 }
143157
144- // add any new block devices from the launch template
145- for name , blockDevice := range launchTemplateBlockDeviceMap {
146- if _ , ok := instanceBlockDeviceMap [ name ]; ! ok {
158+ // LT-only block devices appended after, in launch template order
159+ for _ , blockDevice := range lt . BlockDeviceMappings {
160+ if _ , ok := instanceBlockDeviceNames [ blockDevice . DeviceName . Value () ]; ! ok {
147161 blockDevices = append (blockDevices , blockDevice )
148162 }
149163 }
0 commit comments