Last active
January 6, 2022 22:42
-
-
Save jhorsman/6f253941cdd0caec6bbba26a2cb26345 to your computer and use it in GitHub Desktop.
Test SDL Web 8.5 micro services with PowerShell
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
<# | |
https://gist.github.com/jhorsman/6f253941cdd0caec6bbba26a2cb26345 | |
.SYNOPSIS | |
Verifies the SDL Web Content Delivery micro services which are listed in the discovery service | |
.PARAMETER DiscoveryEndpointUrl | |
Endpoint to the discovery service. By default it is on port 8082 and it always ends with /discovery.svc | |
.PARAMETER Local | |
Use micro service URLs relative to the DiscoveryEndpointUrl URL, even if the Discovery service provides a different URL. This is used to test the micro service on a specific machine when the micro services are behind a load balancer. | |
.PARAMETER ClientId | |
Ignore the ClientId if your microservices do not use authentication. The script will try both without and with authentication | |
.PARAMETER ClientSecret | |
Ignore the ClientSecret if your microservices do not use authentication. The script will try both without and with authentication | |
.PARAMETER ServiceTimeoutSec | |
The serviceTimeoutSec is quite high to give the microservices time to start up in case we are doing the first request to the service. | |
.PARAMETER QUIET | |
Be less verbose | |
.EXAMPLE | |
test-cd-microservices.ps1 -DiscoveryEndpointUrl "http://cd-server:8082/discovery.svc | |
.EXAMPLE | |
test-cd-microservices.ps1 -DiscoveryEndpointUrl "http://cd-server:8082/discovery.svc -ClientId 'cduser' -ClientSecret 'somethingSecret' | |
.NOTES | |
Author: Jan Horsman | |
inspired by https://blog.indivirtual.nl/testing-sdl-web-8-micro-services/ | |
#> | |
#Requires -Version 5.0 | |
[CmdletBinding()] | |
Param( | |
[parameter(Mandatory=$false, HelpMessage="Endpoint to the discovery service. By default it is on port 8082 and it always ends with /discovery.svc")] | |
[string]$DiscoveryEndpointUrl = 'http://localhost:8082/discovery.svc', | |
[parameter(Mandatory=$false, HelpMessage="Use micro service URLs relative to the DiscoveryEndpointUrl URL.")] | |
[switch]$Local, | |
[parameter(Mandatory=$false)] | |
[string]$ClientId = 'cduser', | |
[parameter(Mandatory=$false)] | |
[string]$ClientSecret = 'CDUserP@ssw0rd', | |
[parameter(Mandatory=$false, HelpMessage="The serviceTimeoutSec is quite high to give the microservices time to start up in case we are doing the first request to the service.")] | |
[int]$ServiceTimeoutSec = 10, | |
[parameter(Mandatory=$false, HelpMessage="Be less verbose")] | |
[switch]$Quiet | |
) | |
$ErrorActionPreference = "Stop" | |
if(-not $Quiet) { | |
Write-Host "Testing microservices..." | |
} | |
#todo try to fix the URL if we do not get a full url | |
#all of the following should lead to http://server:8082/discovery.svc | |
#server:8082/discovery.svc | |
#http://server:8082 | |
#http://server:8082/ | |
#http://server | |
if(-not $DiscoveryEndpointUrl.StartsWith("http")) { | |
if(-not $DiscoveryEndpointUrl.Contains(".svc")) { | |
$urlSuggestion = ("http://{0}:8082/discovery.svc" -f $DiscoveryEndpointUrl) | |
Write-Error ("$DiscoveryEndpointUrl is not a valid URL. Did you mean $urlSuggestion ?") | |
} | |
Write-Error ("$DiscoveryEndpointUrl is not a valid URL") | |
} | |
if(-not $Quiet) { | |
Write-Host "discovery service endpoint: $DiscoveryEndpointUrl" | |
} | |
$BaseUrl = "" | |
if($Local) { | |
$BaseUrl = ([System.Uri]$DiscoveryEndpointUrl).Scheme + '://' + ([System.Uri]$DiscoveryEndpointUrl).Host | |
$DiscoveryEndpointUrl = $BaseUrl + ":" + ([System.Uri]$DiscoveryEndpointUrl).Port + ([System.Uri]$DiscoveryEndpointUrl).LocalPath | |
} | |
$DiscoveryEndpointUrl | |
$tokenServiceEndpoint = ([System.Uri]$DiscoveryEndpointUrl).Scheme + '://' + ([System.Uri]$DiscoveryEndpointUrl).Authority + '/token.svc' | |
if(-not $Quiet) { | |
Write-Host "token service endpoint: $tokenServiceEndpoint" | |
} | |
$authorizationRequired = $false # we are first trying without authorization | |
$authorizationHeader = @{} | |
try { | |
if(-not $Quiet) { | |
Write-Host -ForegroundColor Gray "trying discovery service at $DiscoveryEndpointUrl..." | |
} | |
$discoveryResponse = Invoke-RestMethod -UseBasicParsing -Uri $DiscoveryEndpointUrl -TimeoutSec $ServiceTimeoutSec | |
} catch { | |
if($_.Exception.Status -eq "ConnectFailure") { | |
Write-Error "Unable to connect to $DiscoveryEndpointUrl" | |
} elseif($_.Exception.Response.StatusCode.Value__ -eq 401) { | |
$authorizationRequired = $true | |
try { | |
$tokenParams = @{ | |
client_id = $ClientId | |
client_secret = $ClientSecret | |
grant_type = 'client_credentials' | |
resources = '/' | |
} | |
if(-not $Quiet) { | |
Write-Host -ForegroundColor Gray "trying token service at $tokenServiceEndpoint..." | |
} | |
$tokenResponse = Invoke-RestMethod -UseBasicParsing -Uri $tokenServiceEndpoint -Method Post -Body $tokenParams -TimeoutSec $ServiceTimeoutSec | |
Write-Host -ForegroundColor Green "token service OK $tokenServiceEndpoint" | |
} catch { | |
# check if we are actually talking to the token service | |
try { | |
if(-not $Quiet) { | |
Write-Host -ForegroundColor Gray "verifying token service at $tokenServiceEndpoint..." | |
} | |
$tokenResponse = Invoke-RestMethod -UseBasicParsing -Uri $tokenServiceEndpoint -TimeoutSec $ServiceTimeoutSec | |
} catch { | |
if ($_.Exception.Response.StatusCode.Value__ -eq 403 ) { | |
#checked | |
Write-Error "Expected token service at $tokenServiceEndpoint. Are you sure that $DiscoveryEndpointUrl is the SDL Web discovery service URL?" | |
} | |
# this is an unexpected error situation | |
throw $_ | |
} | |
if($tokenResponse.Content.Contains("SDL Web OAuth 2.0 Token Servlet.")) { | |
#checked | |
Write-Error "Authorization error. Check ClientId and ClientSecret" | |
} | |
Write-Error "Expected token service at $tokenServiceEndpoint. Are you sure that $DiscoveryEndpointUrl is the SDL Web discovery service URL?" | |
} | |
$authorizationHeader = @{Authorization = ($tokenResponse.token_type + ' ' + $tokenResponse.access_token)} | |
if(-not $Quiet) { | |
Write-Host -ForegroundColor Gray ("authorization header " + $authorizationHeader.Authorization) | |
} | |
} else { | |
# this is an unexpected error situation | |
throw $_ | |
} | |
try { | |
if(-not $Quiet) { | |
Write-Host -ForegroundColor Gray "trying token service at $DiscoveryEndpointUrl..." | |
} | |
$discoveryResponse = Invoke-RestMethod -UseBasicParsing -Uri $DiscoveryEndpointUrl -Headers $authorizationHeader -TimeoutSec $ServiceTimeoutSec | |
} catch { | |
if($_.Exception.Response.StatusCode.Value__ -eq 404) { | |
Write-Error "Expected discovery service at $DiscoveryEndpointUrl. Are you sure that this is the SDL Web discovery service URL?" | |
} | |
# this is an unexpected error situation | |
throw $_ | |
} | |
} | |
if(-not $Quiet) { | |
if($authorizationRequired) { | |
Write-Host "discovery service accepts authenticated requests only" | |
} else { | |
Write-Host "discovery service accepts anonymous requests" | |
} | |
} | |
Write-Host -ForegroundColor Green "discovery service OK $DiscoveryEndpointUrl" | |
if(-not $Quiet) { | |
Write-Host -ForegroundColor Gray "trying discovery service at $DiscoveryEndpointUrl..." | |
} | |
$environmentUrl = $DiscoveryEndpointUrl + '/Environment' | |
$environment = Invoke-RestMethod -UseBasicParsing -Uri $environmentUrl -Headers $authorizationHeader -TimeoutSec $ServiceTimeoutSec | |
$capabilities= $environment.entry.link.Where({$_.type -eq "application/atom+xml;type=entry"}) | |
$serviceErrorCounter = 0 | |
foreach ($capability in $capabilities) { | |
$capabilityTitle = $capability.title | |
$capabilityUrl = $DiscoveryEndpointUrl + '/' + $capability.href | |
if($BaseUrl) { | |
$capabilityUrl = $BaseUrl + ":" + ([System.Uri]$capabilityUrl).Port + ([System.Uri]$capabilityUrl).LocalPath | |
} | |
$capabilityData = $null | |
try { | |
if(-not $Quiet) { | |
Write-Host -ForegroundColor Gray "trying discovery service at $capabilityUrl..." | |
} | |
$capabilityData = Invoke-RestMethod -UseBasicParsing -Uri $capabilityUrl -Headers $authorizationHeader -TimeoutSec $ServiceTimeoutSec | |
$capabilityEndpoint = $capabilityData.entry.content.properties.URI | |
if($capabilityEndpoint -and $BaseUrl) { | |
$capabilityEndpoint = $BaseUrl + ":" + ([System.Uri]$capabilityEndpoint).Port + ([System.Uri]$capabilityEndpoint).LocalPath | |
} | |
} catch { | |
if($_.Exception.Response.StatusCode.Value__ -eq 404) { | |
if(-not $Quiet) { | |
Write-Host "$capabilityTitle not available" | |
} | |
} else { | |
# unexpected error | |
throw $_ | |
} | |
} | |
if($capabilityData) { | |
if(-not $capabilityEndpoint) { | |
if(-not $Quiet) { | |
Write-Host "$capabilityTitle has no URL" | |
} | |
} else { | |
try { | |
if(-not $Quiet) { | |
Write-Host -ForegroundColor Gray "trying $capabilityTitle at $capabilityEndpoint..." | |
} | |
Invoke-RestMethod -UseBasicParsing -Uri $capabilityEndpoint -Headers $authorizationHeader -TimeoutSec $ServiceTimeoutSec | Out-Null | |
Write-Host -ForegroundColor Green "$capabilityTitle OK $capabilityEndpoint" | |
if($capabilityTitle.Equals("ContentServiceCapability")) { | |
# test content serivce endpoints | |
$contentServiceBaseUrl = ([System.Uri]$capabilityEndpoint).Scheme + '://' + ([System.Uri]$capabilityEndpoint).Authority | |
$v2ContentUrl = $contentServiceBaseUrl + "/client/v2/content.svc" | |
if(-not $Quiet) { | |
Write-Host -ForegroundColor Gray "trying $capabilityTitle v2 at $v2ContentUrl..." | |
} | |
# todo put a try catch block around this request | |
$capabilityEndpoint = $v2ContentUrl # set $capabilityEndpoint for error reporting in the catch block | |
Invoke-RestMethod -UseBasicParsing -Uri $v2ContentUrl -Headers $authorizationHeader -TimeoutSec $ServiceTimeoutSec | Out-Null | |
Write-Host -ForegroundColor Green "$capabilityTitle v2 OK $v2ContentUrl" | |
$v4ContentUrl = $contentServiceBaseUrl + "/client/v4/content.svc" | |
if(-not $Quiet) { | |
Write-Host -ForegroundColor Gray "trying $capabilityTitle v4 at $v4ContentUrl..." | |
} | |
# todo put a try catch block around this request | |
$capabilityEndpoint = $v4ContentUrl # set $capabilityEndpoint for error reporting in the catch block | |
Invoke-RestMethod -UseBasicParsing -Uri $v4ContentUrl -Headers $authorizationHeader -TimeoutSec $ServiceTimeoutSec | Out-Null | |
Write-Host -ForegroundColor Green "$capabilityTitle v4 OK $v4ContentUrl" | |
# test DXA model service | |
# todo this is skipped when testing of the Content Service throws and error | |
$dxaServiceUrl = ($capabilityData.entry.content.properties.ExtensionProperties.element | ?{ $_.Key -eq "dxa-model-service" } ).value | |
if($dxaServiceUrl) { | |
if(-not $Quiet) { | |
Write-Host -ForegroundColor Gray "Found DXA model service in Content Service properties: $dxaServiceUrl" | |
Write-Host -ForegroundColor Gray "trying DXA model service at $dxaServiceUrl..." | |
} | |
# todo put a try catch block around this request | |
$capabilityEndpoint = $dxaServiceUrl # set $capabilityEndpoint for error reporting in the catch block | |
$capabilityTitle = "DXA model service" # set $capabilityTitle for error reporting in the catch block | |
Invoke-RestMethod -UseBasicParsing -Uri $dxaServiceUrl -Headers $authorizationHeader -TimeoutSec $ServiceTimeoutSec | Out-Null | |
Write-Host -ForegroundColor Green "DXA model service OK $dxaServiceUrl" | |
} | |
} | |
} catch { | |
if($_.Exception.Message.Contains("The operation has timed out.")) { | |
$serviceErrorCounter++ | |
Write-Host -ForegroundColor Red "$capabilityTitle FAIL (timeout) $capabilityEndpoint" | |
} elseif(($capabilityTitle.Equals("DeployerCapability") -or $capabilityTitle.Equals("SmartTargetManagementCapability")) -and $_.Exception.Response.StatusCode.Value__ -eq 403) { | |
# this is an expected situation, a GET request to the deployer endpoint will return a 403 Forbidden | |
Write-Host -ForegroundColor Green "$capabilityTitle OK $capabilityEndpoint" | |
} elseif ($_.Exception.Response.StatusCode.value__ -eq 403) { | |
$serviceErrorCounter++ | |
Write-Host -ForegroundColor Red "$capabilityTitle FAIL (403 Forbidden) $capabilityEndpoint" | |
} elseif ($_.Exception.Response.StatusCode.value__ -eq 404) { | |
$serviceErrorCounter++ | |
Write-Host -ForegroundColor Red "$capabilityTitle FAIL (404 Not Found) $capabilityEndpoint" | |
} elseif ($_.Exception.Response.StatusCode.value__ -eq 503) { | |
$serviceErrorCounter++ | |
Write-Host -ForegroundColor Red "$capabilityTitle FAIL (503 Server Unavailable) $capabilityEndpoint" | |
} else { | |
# unexpexted error | |
$serviceErrorCounter++ | |
Write-Host -ForegroundColor Red ("$capabilityTitle FAIL (unexpected error '" + $_.Exception.Message + "') $capabilityEndpoint") | |
} | |
} | |
} | |
} | |
} | |
if($serviceErrorCounter -gt 0) { | |
Write-Error "$serviceErrorCounter microservices failed" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment