I created a powershell gui to create IAAS cloudformation templates. The issue I'm running into is:
the template creates the folder structure for all environments successfully, once it does that it starts the process of creating each file for the deployment.
each file name is from variable:
$is = $textbox10.Lines (TEXTBOX WITH A SERVER NAME LIST)
if I input 3 server names, it'll create 3 files using the names in $i (this part works) in all folders
###################################################################
### COPY AND RENAME PARAMETER FILES IN INFRASTRUCTURE FOLDER ###
###################################################################
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\dev\params_ans_DVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\sit\params_ans_SVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\uat\params_ans_UVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\prep\params_ans_PVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\prod\params_ans_XVW$i.yml"
once it's done with that, it should attempt to go through each file it created and add other variables. In this case/example: $a variable
$azs = $textbox1.Lines
Below is an example of the current spot I'm on.
$is = "TEST01","TEST02","TEST03"
#Write-Host $is
$azs = "a","b","c"
#Write-Host $azs
foreach ($i in $is)
{
###################################################################
### COPY AND RENAME PARAMETER FILES IN INFRASTRUCTURE FOLDER ###
###################################################################
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\dev\params_ans_DVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\sit\params_ans_SVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\uat\params_ans_UVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\prep\params_ans_PVW$i.yml"
Copy-Item "$ansibleparamfile" "$($infrawindowsbasefolder)\prod\params_ans_XVW$i.yml"
Copy-Item "$cfnparamfile" "$($infrawindowsbasefolder)\dev\params_DVW$i.json"
Copy-Item "$cfnparamfile" "$($infrawindowsbasefolder)\sit\params_SVW$i.json"
Copy-Item "$cfnparamfile" "$($infrawindowsbasefolder)\uat\params_UVW$i.json"
Copy-Item "$cfnparamfile" "$($infrawindowsbasefolder)\prep\params_PVW$i.json"
Copy-Item "$cfnparamfile" "$($infrawindowsbasefolder)\prod\params_XVW$i.json"
#############################################
### REPLACE CONTENT IN PARAMETER FILES ###
###########################################
foreach ($a in $azs)
{
#Write-Host $a
## REPLACE AVAILABILITY ZONES IN TEMPLATE ##
(Get-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-1$($a)" } | Set-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json"
(Get-Content "$($infrawindowsbasefolder)\sit\params_SVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-1$($a)" } | Set-Content "$($infrawindowsbasefolder)\sit\params_SVW$i.json"
(Get-Content "$($infrawindowsbasefolder)\uat\params_UVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-$($a)" } | Set-Content "$($infrawindowsbasefolder)\uat\params_UVW$i.json"
(Get-Content "$($infrawindowsbasefolder)\prep\params_PVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-1$($a)" } | Set-Content "$($infrawindowsbasefolder)\prep\params_PVW$i.json"
(Get-Content "$($infrawindowsbasefolder)\prod\params_XVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-1$($a)" } | Set-Content "$($infrawindowsbasefolder)\prod\params_XVW$i.json"
}
}
when this runs, the 3 files created for each environment all have the 1st variable of $a "a", instead of "test01-a","test02-b","test03-c".
The problem is that your search pattern of text to replace is replaced in the first pass of the loop, and no longer exists in the second two loops. Let's simplify this and just loop on one file:
foreach ($a in $azs)
{
#Write-Host $a
## REPLACE AVAILABILITY ZONES IN TEMPLATE ##
(Get-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-1$($a)" } | Set-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json"
}
Let's say that the file params_DVWTEST01.json
contains the text:
<region>
availability-zone
<region>
Now your loop runs the first time, where $a = 'a'
. Inside the loop you get the content of the file, you perform the string replacement, and you use Set-Content
to save the updated file. End product, that file now contains:
<region>
us-east-1a
<region>
Second loop begins, this time $a = 'b'
. Inside your loop you get the content of the file, it tries to perform the string replacement, but 'availability-zone' is nowhere in the file to be replaced, so it saves the file just as it is.
Third loop where $a = 'c'
executes exactly like the second loop. It loads the file, finds nothing to replace, and saves the file just as it was. If you want it to contain all three items in $azs
you will need to concoct the strings into a single string, and use that as your replacement.
$AllZones = ($azs|ForEach{"us-east-1$_"}) -join ", "
Now $AllZones = "us-east-1a, us-east-1b, us-east-1c"
. Then use that as the replacement string, and no internal loop is needed.
$AllZones = ($azs|ForEach{"us-east-1$_"}) -join ", "
## REPLACE AVAILABILITY ZONES IN TEMPLATE ##
(Get-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json") | foreach-object { $_ -replace "availability-zone", $AllZones } | Set-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json"
Edit: It looks like you want to cycle through locations as you cycle through servers, so that each server has a different location, or at least so that servers are distributed across locations. There's a couple ways to do that. The simplest is if you have the same number of servers as you do locations. In that case you switch to using a For()
loop instead of a ForEach()
loop. Then things start to look like this:
$is = "TEST01","TEST02","TEST03"
#Write-Host $is
$azs = "a","b","c"
#Write-Host $azs
for ($y=0; $y -lt $is.count; $y++)
{
$i = $is[$y]
Then later when you doing your replace you reference $azs[$y]
like:
(Get-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json") | foreach-object { $_ -replace "availability-zone", "us-east-1$($azs[$y])" } | Set-Content "$($infrawindowsbasefolder)\dev\params_DVW$i.json"
Then TEST01 get "us-east-1a", TEST02 gets "us-east-1b", and TEST03 get "us-east-1c". Pretty simple if your number of servers and number of locations are equal.
Let us look at the other approach, where you may have different numbers of servers and locations and you want to distribute servers across a limited number of locations. It would be a similar situation, but we would have to do a little math in order to cycle through the list of locations. Let's start with setting up more servers, we'll expand to 5.
$is = "TEST01","TEST02","TEST03","TEST04","TEST05"
We'll leave the regions the same, a, b, and c. Now for simplicity's sake we'll just output what region we're assigning to each server to the screen:
For($y=0; $y -lt $is.count; $y++){
"Assigning server '$($is[$y])' to region 'us-east-1$($azs[$y%$azs.count])'"
}
The output of that would be:
Assigning server 'TEST01' to region 'us-east-1a'
Assigning server 'TEST02' to region 'us-east-1b'
Assigning server 'TEST03' to region 'us-east-1c'
Assigning server 'TEST04' to region 'us-east-1a'
Assigning server 'TEST05' to region 'us-east-1b'
The magic in this is $y%$azs.count
. What that does is gives you the remainder after dividing the current iteration of $y
by $azs.count
(which is 3). So the first time through the loop it is 0 divided by 3, which is 0 with a remainder of 0. $azs[0] = 'a'
. The next iteration is 1 divided by 3, which is 0 with a remainder of 1. $azs[1] = 'b'
. Iteration 3 is quite similar, producing 'c'. Iteration 4 is more interesting where it is 3 divided by 3, which is 1 with a remainder of 0, which is what causes us to loop back to the beginning of $azs[0] = 'a'
.