Last active
June 21, 2023 18:40
-
-
Save vgribok/9e68de07e03f0266a573aa3159af95de to your computer and use it in GitHub Desktop.
Allows copying RDS parameter groups between AWS Regions and Accounts. Enables version-controlling values of RDS param groups via JSON files. Makes possible RDS cluster provisioning automation for custom parameter groups.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
Allows exporting RDS Parameter Group parameters as a file and importing it in another AWS Account or a region. | |
Inspired by https://gist.github.com/phill-tornroth/f0ef50f9402c7c94cbafd8c94bbec9c9. | |
PowerShell is a *cross-platform* shell compatible with Linux, MacOS and Windows. | |
PowerShell can be installed in seconds: https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell | |
Usage: | |
To *export* a cluster parameter group named "custom-aurora-postgresql13-babelfish-compat-1", run: | |
Get-RdsClusterParamGroupDetails custom-aurora-postgresql13-babelfish-compat-1 | ConvertTo-Json -Depth 3 | Out-File RDS-BBF-params.json | |
or (the easier way): | |
Get-RdsClusterParamGroupDetailsJson custom-aurora-postgresql13-babelfish-compat-1 -FilePath RDS-BBF-params.json | |
To create a parameter group named apg-bbf-params from JSON file: | |
Import-RdsClusterParamGroupDetails RDS-BBF-params.json -ProfileName default -Region us-west-2 ` | |
-Name "apg-bbf-params" | |
Note: ProfileName and Region parameters are optional. | |
#> | |
Write-Host "Adding all AWS PowerShell commands. It may take a few seconds.." | |
Import-Module awspowershell.netcore | |
function Get-RdsClusterParamGroupDetailsJson { | |
param ( | |
[Parameter(mandatory=$true, HelpMessage='Use Get-RDSDBClusterParameterGroup cmdlet to list all cluster parameter groups')] | |
[string] $Name, | |
[Parameter(mandatory=$false)] [string] $Region, | |
[Parameter(mandatory=$false)] [string] $ProfileName, | |
[Parameter(mandatory=$false)] [string] $FilePath | |
) | |
$result = Get-RdsClusterParamGroupDetails -Name $Name ` | |
-Region $Region ` | |
-ProfileName $ProfileName | |
if(-not $result) { | |
return | |
} | |
if(-not $FilePath) { $FilePath = "$Name--param-group-details.json" } | |
$result | ConvertTo-Json -Depth 9 | Out-File $FilePath | |
} | |
function Get-RdsClusterParamGroupDetails { | |
param ( | |
[Parameter(mandatory=$true, HelpMessage='Use Get-RDSDBClusterParameterGroup cmdlet to list all cluster parameter groups')] [string] $Name, | |
[Parameter(mandatory=$false)] [string] $Region, | |
[Parameter(mandatory=$false)] [string] $ProfileName | |
) | |
$prevRegion = Get-DefaultAWSRegion | |
try{ | |
if($Region) { Set-DefaultAWSRegion $Region} | |
if($ProfileName -eq "") { $ProfileName = $null } | |
$sourceParamGroup = Get-RDSDBClusterParameterGroup $Name ` | |
-ProfileName $ProfileName | |
$parameters = Get-RDSDBClusterParameter $Name ` | |
-ProfileName $ProfileName ` | |
| Where { $_.ParameterValue -and $_.IsModifiable } | |
$result = [PSCustomObject]@{ | |
ParameterGroupName = $sourceParamGroup.DBClusterParameterGroupName | |
Description = $sourceParamGroup.Description | |
GroupFamily = $sourceParamGroup.DBParameterGroupFamily | |
Parameters = $parameters | |
} | |
return $result | |
} | |
finally{ | |
if($prevRegion) { Set-DefaultAWSRegion $prevRegion} else {Clear-DefaultAWSRegion} | |
} | |
} | |
# Test command for export debugging puposes: | |
# $exportedData = Get-RdsClusterParamGroupDetails custom-aurora-postgresql13-babelfish-compat-1 | ConvertTo-Json -Depth 3 | |
# $exportedData | Out-File custom-aurora-postgresql13-babelfish-compat-1-rds-param-group-details.json | |
# Get-RdsClusterParamGroupDetailsJson custom-aurora-postgresql13-babelfish-compat-1 -FilePath RDS-BBF-params.json | |
function Import-RdsClusterParamGroupDetails { | |
param ( | |
[Parameter(mandatory=$true, ValueFromPipeline = $true, | |
HelpMessage='Use Get-RdsClusterParamGroupDetails cmdlet to export details of the cluster parameter groups') | |
] $ImportedParamGroupDetails, | |
[Parameter(mandatory=$false)] [string] $Name, | |
[Parameter(mandatory=$false)] [string] $Region, | |
[Parameter(mandatory=$false)] [string] $ProfileName | |
) | |
# Write-Debug "Imported data:\n$ImportedParamGroupDetails" | |
# The ImportedParamGroupDetails can either be piped-in, already parsed Json, | |
# or a path to th eJSON file. | |
if($ImportedParamGroupDetails -is [string]) { | |
$ImportedParamGroupDetails = Get-Content $ImportedParamGroupDetails | ConvertFrom-Json -Depth 9 | |
} | |
$prevRegion = Get-DefaultAWSRegion | |
try{ | |
if($Region) { Set-DefaultAWSRegion $Region} | |
if(-not $Name) {$Name = $ImportedParamGroupDetails.ParameterGroupName} | |
New-RDSDBClusterParameterGroup ` | |
-DBClusterParameterGroupName $Name ` | |
-DBParameterGroupFamily $ImportedParamGroupDetails.GroupFamily ` | |
-Description GroupFamily.Description ` | |
-ProfileName $ProfileName | |
$importedParameters = _FilterOutIdenticalValues $ImportedParamGroupDetails.Parameters $Name $ProfileName | |
$paramCollectionLength = $importedParameters.Count | |
Write-Information "Will update $paramCollectionLength parameters" | |
for($i=0 ; $i -lt $paramCollectionLength ; $i += 20) { | |
$chunkSize = $paramCollectionLength - $i | |
if($chunkSize -gt 20) { $chunkSize = 20 } | |
# Slice out no more than 20 parameters for the batch update | |
$params = $importedParameters[$i..($i+$chunkSize-1)] ?? $importedParameters | |
foreach ($param in $params) { | |
# ApplyMethod cannot be converted autpmatically | |
$param.ApplyMethod = [Amazon.RDS.ApplyMethod]::New($param.ApplyMethod.Value) | |
} | |
# Update the batch of values | |
if($params -and ($params.Count -gt 0)){ | |
Edit-RDSDBClusterParameterGroup -DBClusterParameterGroupName $Name -ProfileName $ProfileName ` | |
-Parameter $params | |
} | |
## Debug version - updates parameters one by one instead of in chunks of 20, to see which ones are failing | |
# foreach($p in $params) { | |
# try{ | |
# Edit-RDSDBClusterParameterGroup -DBClusterParameterGroupName $Name -ProfileName $ProfileName ` | |
# -Parameter $p | |
# } | |
# catch { | |
# Write-Host "==> UPDATE ERROR: Failed to modify parameter `"$($p.ParameterName)`" with value `"$($p.ParameterValue)`" due to the `"$($_))`" error, with allowed values of `"$($p.AllowedValues)`"." | |
# # throw | |
# } | |
# } | |
} | |
} | |
finally{ | |
if($prevRegion) { Set-DefaultAWSRegion $prevRegion} else {Clear-DefaultAWSRegion} | |
} | |
} | |
function _FilterOutIdenticalValues($importedParameters, [string] $Name, [string] $ProfileName) | |
{ | |
$stockParameters = Get-RDSDBClusterParameter $Name ` | |
-ProfileName $ProfileName ` | |
| Where-Object { $_.ParameterValue -and $_.IsModifiable } | |
$paramsToSkip = [System.Collections.ArrayList]@(); | |
foreach($importedParam in $importedParameters) { | |
$sameParam = $stockParameters | Where-Object { ($_.ParameterName -eq $importedParam.ParameterName) -and ($_.ParameterValue -eq $importedParam.ParameterValue) } | Select-Object -First 1 | |
if($sameParam) { | |
$paramsToSkip.Add($sameParam.ParameterName) | out-null | |
} | |
} | |
# Remove parameters that should be skipped | |
$importedParameters = $importedParameters | Where-Object { -not $paramsToSkip.Contains($_.ParameterName) } | |
return $importedParameters | |
} | |
#Testing import | |
# Get-Content RDS-BBF-params.json ` | |
# | ConvertFrom-Json -Depth 4 ` | |
# | Import-RdsClusterParamGroupDetails -ProfileName default -Region us-west-2 | |
#Import-RdsClusterParamGroupDetails RDS-BBF-params.json -ProfileName default -Region us-west-2 ` | |
# -Name "apg-bbf-params" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment