4

I'm trying to automate the creation of a server farm in PowerShell. Through manual creation I've got the following XML:

<webFarms>
    <webFarm name="alwaysup" enabled="true">
        <server address="alwaysup-blue" enabled="true">
            <applicationRequestRouting httpPort="8001" />
        </server>
        <server address="alwaysup-green" enabled="true">
            <applicationRequestRouting httpPort="8002" />
        </server>
        <applicationRequestRouting>
            <healthCheck url="http://alwaysup/up.html" interval="00:00:05" responseMatch="up" />
        </applicationRequestRouting>
    </webFarm>
    <applicationRequestRouting>
        <hostAffinityProviderList>
            <add name="Microsoft.Web.Arr.HostNameRoundRobin" />
        </hostAffinityProviderList>
    </applicationRequestRouting>
</webFarms>

Trying to do this via PS proves troublesome however: as far as I can tell there is no dedicated API to do this through (WebFarmSnapin is meant for an older version).

I have shifted my attention to IIS Administration Cmdlets but only got it half working.

The code that I have:

#####
# Overwriting the server farm
#####

Write-Host "Overwriting the server farm $($webFarmName)"

$webFarm = @{};
$webFarm["name"] = 'siteFarm'

Set-WebConfiguration "/webFarms" -Value $webFarm

#####
# Adding the servers
#####

Write-Host "Adding the servers"

$blueServer = @{}
$blueServer["address"] = 'site-blue'
$blueServer["applicationRequestRouting"] = @{}

$greenServer = @{}
$greenServer["address"] = 'site-green'
$greenServer["applicationRequestRouting"] = @{}

$servers = @($blueServer, $greenServer)

Add-WebConfiguration -Filter "/webFarms/webFarm[@name='siteFarm']" -Value $servers

#####
# Adding routing
#####

Write-Host "Adding the routing configurations"

$blueServerRouting = @{}
$blueServerRouting["httpPort"] = "8001"
Add-WebConfiguration -Filter "/webFarms/webFarm[@name='siteFarm']/server[@address='site-blue']" -Value $blueServerRouting

This generates

<webFarms>
    <webFarm name="siteFarm">
        <server address="site-blue" />
        <server address="site-green" />
    </webFarm>
    <applicationRequestRouting>
        <hostAffinityProviderList>
            <add name="Microsoft.Web.Arr.HostNameRoundRobin" />
        </hostAffinityProviderList>
    </applicationRequestRouting>
</webFarms>

As you can see it's missing the port related to the routing. And I haven't even started with trying to add the healthcheck at this point.

What am I doing wrong? Is there some Cmdlet that I haven't found which makes this easier?

Related but without much of a useful answer (the PowerShell tab with generated code stays empty).

Crossposted it here from SO after realizing SF exists and might be more appropriate.

  • Is there some reason why you cant use the xml file you created manually and just apply it to the servers in the farm? – Mr Zach Nov 11 '17 at 21:48
  • The XML file in question is applicationhost.config and a core IIS config file. I did have the idea to just directly manipulate the XML but it seems like a hacky way and I'd prefer a more robust solution that actually uses an API. – Jeroen Vannevel Nov 11 '17 at 21:56
  • Yes, might be a bit "hacky" but at the same time, that's why ms is using XML for the configuration, so you can read and modify it from "what ever you want" but for sure, you need to make sure to never create invalid configuration files. – Mr Zach Nov 11 '17 at 22:00
  • Have you heard of "puppet"? It's entire function is deploying and managing sets of server automatically based on rules. https://forge.puppet.com/puppetlabs/iis – HackSlash Nov 14 '17 at 16:37

1 Answers1

2

The best way I've seen to accomplish this is by mixing powershell with the appcmd.exe command. Microsoft has released some sample code for setting up a farm in a docker container here.

Here's an example:

ForEach($farm in $farms)
{   
    # Create the farm
    .\appcmd.exe set config  -section:webFarms /+"[name='$($farm.name)']" /commit:apphost

    ForEach($server in $farm.Servers)
    {
        # Add server to farm
        .\appcmd.exe set config  -section:webFarms /+"[name='$($farm.name)'].[address='$($server.address)']" /commit:apphost
    }

    # URL Rewrite
    .\appcmd.exe set config  -section:system.webServer/rewrite/globalRules /+"[name='ARR_$($farm.name)_lb', patternSyntax='Wildcard',stopProcessing='True']" /commit:apphost
    .\appcmd.exe set config  -section:system.webServer/rewrite/globalRules /"[name='ARR_$($farm.name)_lb',patternSyntax='Wildcard',stopProcessing='True']".match.url:"*"  /commit:apphost
    .\appcmd.exe set config  -section:system.webServer/rewrite/globalRules /"[name='ARR_$($farm.name)_lb',patternSyntax='Wildcard',stopProcessing='True']".action.type:"Rewrite"  /"[name='ARR_$($farm.name)_lb',patternSyntax='Wildcard',stopProcessing='True']".action.url:"http://$($farm.name)/{R:0}"  /commit:apphost
}