Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@jhorsman
Last active January 6, 2022 22:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jhorsman/6f253941cdd0caec6bbba26a2cb26345 to your computer and use it in GitHub Desktop.
Save jhorsman/6f253941cdd0caec6bbba26a2cb26345 to your computer and use it in GitHub Desktop.
Test SDL Web 8.5 micro services with PowerShell
<#
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