Skip to content

Instantly share code, notes, and snippets.

@nanoDBA
Created April 12, 2025 14:07
Show Gist options
  • Save nanoDBA/cdc5b8f209ae703670c197b60214ae68 to your computer and use it in GitHub Desktop.
Save nanoDBA/cdc5b8f209ae703670c197b60214ae68 to your computer and use it in GitHub Desktop.
Modifies AWS EBS volumes with enhanced validation and confirmation πŸš€
function Edit-EBSVolumes {
<#
.SYNOPSIS
Modifies AWS EBS volumes with enhanced validation and confirmation πŸ”§πŸš€
.DESCRIPTION
This function lets you change multiple AWS EBS volumes in one go!
It supports modifications to volume type, size, IOPS, and throughput
with safety confirmations and detailed feedback.
It’s essentially a wrapper around AWS's Edit-EC2Volume command with extra spice for validation.
.PARAMETER VolumeIds
Array of AWS EBS Volume IDs to modify.
.PARAMETER TargetSize
New volume size in GB.
.PARAMETER TargetEbsType
New volume type (gp2, gp3, io1, io2, sc1, st1).
.PARAMETER TargetIops
New IOPS value (required for io1/io2; optional for gp3).
.PARAMETER TargetThroughput
New throughput value in MB/s (applicable only for gp3).
.PARAMETER Region
AWS region of the volumes. Default: 'us-east-1'.
.PARAMETER Force
Bypasses confirmation and applies changes immediately.
.EXAMPLE
Edit-EBSVolumes -VolumeIds 'vol-0a1b2c3d4e5f6a7b','vol-0a1b2c3d4e5f6a7c' -TargetSize 2701
# Resizes specified volumes to 2701 GB in the default region.
.EXAMPLE
Edit-EBSVolumes -VolumeIds 'vol-0a1b2c3d4e5f6a7b' -TargetEbsType 'io2' -TargetIops 16000 -Region 'us-west-2'
# Changes the volume to io2 with 16000 IOPS in us-west-2.
.EXAMPLE
Edit-EBSVolumes -VolumeIds 'vol-0a1b2c3d4e5f6a7b' -TargetEbsType 'gp3' -TargetIops 5000 -TargetThroughput 600
# Changes volume to gp3 with 5000 IOPS and 600 MB/s throughput.
.NOTES
Author: Enhanced from original script by Lars, then refined by Lars and Claude.
Date: April 10, 2025
Prerequisites: AWS PowerShell module and proper AWS credentials.
⚠️ Note: Modifications follow AWS limits and constraints.
#>
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
[string[]]$VolumeIds,
[Parameter(Mandatory = $false)]
[ValidateRange(1, 16384)]
[int]$TargetSize,
[Parameter(Mandatory = $false)]
[ValidateSet('gp2', 'gp3', 'io1', 'io2', 'sc1', 'st1')]
[string]$TargetEbsType,
[Parameter(Mandatory = $false)]
[ValidateRange(100, 64000)]
[int]$TargetIops,
[Parameter(Mandatory = $false)]
[ValidateRange(125, 1000)]
[int]$TargetThroughput,
[Parameter(Mandatory = $false)]
[string]$Region = 'us-east-1',
[Parameter(Mandatory = $false)]
[switch]$Force
)
begin {
# Check for AWS PowerShell modules
if (-not (Get-Module -ListAvailable -Name AWSPowerShell, AWS.Tools.EC2)) {
Write-Error "A required AWS PowerShell module is missing. Please install either 'AWS.Tools.EC2' (recommended) or 'AWSPowerShell' using: Install-Module -Name AWS.Tools.EC2 -Force"
return
}
# Validate parameter logic for EBS types
if ($TargetEbsType) {
if ($TargetEbsType -in @('io1', 'io2') -and -not $TargetIops) {
Write-Error "TargetIops is required for io1 or io2 volume types."
return
}
if ($TargetEbsType -ne 'gp3' -and $TargetThroughput) {
Write-Warning "TargetThroughput applies only to gp3 volumes and will be ignored."
}
}
# Console header output 🌟
$separator = '=' * 50
Write-Host $separator -ForegroundColor Yellow
Write-Host " EBS VOLUME MODIFICATION UTILITY " -ForegroundColor Cyan
Write-Host " Region: $Region " -ForegroundColor Cyan
Write-Host $separator -ForegroundColor Yellow
}
process {
foreach ($volId in $VolumeIds) {
try {
Write-Host "`nRetrieving details for volume $volId..." -ForegroundColor Gray
$currentVolume = Get-EC2Volume -VolumeId $volId -Region $Region -ErrorAction Stop
if (-not $currentVolume) {
Write-Error "Volume $volId not found in region $Region"
continue
}
# Build parameters for the volume modification πŸš€
$paramHash = @{
VolumeId = $volId
Region = $Region
}
if ($TargetSize) { $paramHash.Size = $TargetSize }
if ($TargetEbsType) { $paramHash.VolumeType = $TargetEbsType }
if ($TargetIops) { $paramHash.Iops = $TargetIops }
if ($TargetThroughput -and ($TargetEbsType -eq 'gp3' -or $currentVolume.VolumeType -eq 'gp3')) {
$paramHash.Throughput = $TargetThroughput
}
# Check if any actual changes were specified
$changeRequested = $false
foreach ($key in $paramHash.Keys) {
if ($key -notin @('VolumeId', 'Region')) {
$changeRequested = $true
break
}
}
if (-not $changeRequested) {
Write-Warning "No changes specified for volume $volId. Skipping."
continue
}
# Display the volume modification details 🎯
Write-Host "`n======== VOLUME MODIFICATION DETAILS ========" -ForegroundColor Yellow
Write-Host "Volume ID: $volId" -ForegroundColor Cyan
Write-Host "State: $($currentVolume.State)" -ForegroundColor Cyan
Write-Host "Attached to: $(if ($currentVolume.Attachments) { $currentVolume.Attachments[0].InstanceId } else { 'Not attached' })" -ForegroundColor Cyan
Write-Host "Availability Zone: $($currentVolume.AvailabilityZone)" -ForegroundColor Cyan
Write-Host ""
Write-Host "CURRENT SETTINGS:" -ForegroundColor Green
Write-Host " Type: $($currentVolume.VolumeType)"
Write-Host " Size: $($currentVolume.Size) GB"
Write-Host " IOPS: $(if ($currentVolume.Iops) { $currentVolume.Iops } else { 'N/A' })"
Write-Host " Throughput: $(if ($currentVolume.Throughput) { $currentVolume.Throughput } else { 'N/A' }) MB/s"
Write-Host ""
Write-Host "CHANGES TO BE APPLIED:" -ForegroundColor Red
$changesDisplayed = $false
foreach ($key in $paramHash.Keys) {
if ($key -notin @('VolumeId', 'Region')) {
$currentValue = switch ($key) {
'Size' { $currentVolume.Size }
'Iops' { $currentVolume.Iops }
'VolumeType' { $currentVolume.VolumeType }
'Throughput' { $currentVolume.Throughput }
default { 'N/A' }
}
Write-Host " $key`: $($paramHash[$key]) (Current: $currentValue)"
$changesDisplayed = $true
}
}
if (-not $changesDisplayed) {
Write-Host " No changes specified for this volume" -ForegroundColor Yellow
continue
}
Write-Host ""
<#
Breakdown:
# PowerShell ShouldProcess Pattern Explained
## 1. Using $PSCmdlet.ShouldProcess:
- Returns false when -WhatIf is used.
- Prompts confirmation when -Confirm is specified.
- Defaults to true if neither parameter is used.
## 2. Building the confirmation string:
- Converts the parameter hashtable to a readable list of changes.
- Uses GetEnumerator() to iterate through key-value pairs.
- Filters out non-change parameters (VolumeId and Region).
- Joins the changes with commas for clear output.
## 3. Executing after confirmation:
- Displays a status message.
- Uses splatting (@paramHash) to call the AWS command.
- Enforces error handling with -ErrorAction Stop in a try/catch block.
This pattern is a PowerShell best practice for functions that make potentially destructive changes.
#>
# Proceed with modification based on Force or user confirmation
$shouldProceed = $Force
if (-not $Force) {
$confirmation = Read-Host "Are you sure you want to proceed with these changes? (yes/no)"
$shouldProceed = $confirmation -eq 'yes'
}
if ($shouldProceed) {
if ($PSCmdlet.ShouldProcess(
$volId,
"Modify EBS volume with parameters: $(
($paramHash.GetEnumerator() |
Where-Object { $_.Key -notin @('VolumeId', 'Region') } |
ForEach-Object { "$($_.Key)=$($_.Value)" }
) -join ', '
)"
)) {
Write-Host "Proceeding with volume modification..." -ForegroundColor Yellow
$result = Edit-EC2Volume @paramHash -ErrorAction Stop
Write-Host "Modification initiated successfully." -ForegroundColor Green
Write-Host "New state: $($result.ModificationState)" -ForegroundColor Green
Write-Host "Progress: $($result.Progress)%" -ForegroundColor Green
}
}
else {
Write-Host "Volume modification canceled for $volId" -ForegroundColor Red
}
Write-Host "=========================================" -ForegroundColor Yellow
}
catch {
Write-Error "Error processing volume $volId`: $_"
Write-Host "=========================================" -ForegroundColor Yellow
}
}
}
end {
Write-Host "EBS volume modification process complete. πŸŽ‰" -ForegroundColor Green
Write-Host "Run 'Get-EC2Volume -VolumeId <id> -Region $Region' to check status." -ForegroundColor Cyan
Write-Host $separator -ForegroundColor Yellow
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment