jan-h
9/20/2017 - 7:27 PM

Test SDL Web 8.5 micro services with PowerShell

Test SDL Web 8.5 micro services with PowerShell

<#
.SYNOPSIS
    Verifies the SDL Web Content Delivery micro services which are listed in the discovery service

.PARAMETER DiscoveryServiceEndpoint
    Endpoint to the discovery service. By default it is on port 8082 and it always ends with /discovery.svc

.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.

.EXAMPLE
    test-cd-microservices.ps1 -DiscoveryServiceEndpoint "http://cd-server:8082/discovery.svc

.EXAMPLE
    test-cd-microservices.ps1 -DiscoveryServiceEndpoint "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/
#>

[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]$DiscoveryServiceEndpoint = 'http://localhost:8082/discovery.svc',

   [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
)

$ErrorActionPreference = "Stop"

Write-Host "discovery service endpoint: $DiscoveryServiceEndpoint"

$tokenServiceEndpoint  = ([System.Uri]$DiscoveryServiceEndpoint).Scheme + '://' + ([System.Uri]$DiscoveryServiceEndpoint).Authority + '/token.svc'
write-Host "token service endpoint: $tokenServiceEndpoint"

$authorizationRequired = $false  # we are first trying without authorization
$authorizationHeader = @{}

try {
    Write-Host -ForegroundColor Gray "trying discovery service at $DiscoveryServiceEndpoint..."
    $discoveryResponse = Invoke-RestMethod -Uri $DiscoveryServiceEndpoint -TimeoutSec $ServiceTimeoutSec
} catch {
    if($_.Exception.Status -eq "ConnectFailure") {
        Write-Error "Unable to connect to $DiscoveryServiceEndpoint"
    } elseif($_.Exception.Response.StatusCode.Value__ -eq 401) {
        $authorizationRequired = $true

        try {
            $tokenParams = @{
                client_id = $ClientId
                client_secret = $ClientSecret
                grant_type = 'client_credentials'
                resources = '/'
            }
            Write-Host -ForegroundColor Gray "trying token service at $tokenServiceEndpoint..."
            $tokenResponse = Invoke-RestMethod -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 {
                Write-Host -ForegroundColor Gray "verifying token service at $tokenServiceEndpoint..."
                $tokenResponse = Invoke-WebRequest -Uri $tokenServiceEndpoint -TimeoutSec $ServiceTimeoutSec
            } catch {
                if ($_.Exception.Response.StatusCode.Value__ -eq 403 ) {
                    #checked
                    Write-Error "Expected token service at $tokenServiceEndpoint. Are you sure that $DiscoveryServiceEndpoint 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 $DiscoveryServiceEndpoint is the SDL Web discovery service URL?"
        }
        $authorizationHeader = @{Authorization = ($tokenResponse.token_type + ' ' + $tokenResponse.access_token)}
        Write-Host -ForegroundColor Gray ("authorization header " + $authorizationHeader.Authorization)
    } else {
        # this is an unexpected error situation
        throw $_
    }

    try {
        Write-Host -ForegroundColor Gray "trying token service at $DiscoveryServiceEndpoint..."
        $discoveryResponse = Invoke-RestMethod -Uri $DiscoveryServiceEndpoint -Headers $authorizationHeader -TimeoutSec $ServiceTimeoutSec
    } catch {
        if($_.Exception.Response.StatusCode.Value__ -eq 404) {
            Write-Error "Expected discovery service at $DiscoveryServiceEndpoint. Are you sure that this is the SDL Web discovery service URL?"
        }

        # this is an unexpected error situation
        throw $_
    }
}

if($authorizationRequired) {
    Write-Host "discovery service accepts authenticated requests only"
} else {
    Write-Host ce"discovery service accepts anonymous requests"
}
Write-Host -ForegroundColor Green "discovery service OK  $DiscoveryServiceEndpoint"

Write-Host -ForegroundColor Gray "trying discovery service at $DiscoveryServiceEndpoint..."
$environmentUrl = $DiscoveryServiceEndpoint + '/Environment'
$environment = Invoke-RestMethod -Uri $environmentUrl -Headers $authorizationHeader -TimeoutSec $ServiceTimeoutSec
$capabilities= $environment.entry.link.Where({$_.type -eq "application/atom+xml;type=entry"})

foreach ($capability in $capabilities) {
    $capabilityTitle = $capability.title
    $capabilityUrl = $DiscoveryServiceEndpoint + '/' + $capability.href
    
    $capabilityData = $null
    try {
        Write-Host -ForegroundColor Gray "trying discovery service at $capabilityUrl..."
        $capabilityData = Invoke-RestMethod -Uri $capabilityUrl -Headers $authorizationHeader -TimeoutSec $ServiceTimeoutSec
        $capabilityEndpoint = $capabilityData.entry.content.properties.URI
    } catch {
        if($_.Exception.Response.StatusCode.Value__ -eq 404) {
            Write-Host "$capabilityTitle not available"
        } else {
            # unexpected error
            throw $_
        }
    }

    if($capabilityData) {
        if(-not $capabilityEndpoint) {
            Write-Host "$capabilityTitle has no URL"
        } else {
            try {
                Write-Host -ForegroundColor Gray "trying $capabilityTitle at $capabilityEndpoint..."
                Invoke-WebRequest -Uri $capabilityEndpoint -Headers $authorizationHeader -TimeoutSec $ServiceTimeoutSec | Out-Null
                Write-Host -ForegroundColor Green "$capabilityTitle OK  $capabilityEndpoint"

                if($capabilityTitle.Equals("ContentServiceCapability")) {
                    $contentServiceBaseUrl = ([System.Uri]$capabilityEndpoint).Scheme + '://' + ([System.Uri]$capabilityEndpoint).Authority 
                    $v2ContentUrl = $contentServiceBaseUrl + "/client/v2/content.svc" 
                    Write-Host -ForegroundColor Gray "trying $capabilityTitle v2 at $v2ContentUrl..."
                    # todo put a try catch block around this request
                    Invoke-WebRequest -Uri $v2ContentUrl -Headers $authorizationHeader -TimeoutSec $ServiceTimeoutSec | Out-Null
                    Write-Host -ForegroundColor Green "$capabilityTitle v2 OK  $v2ContentUrl"

                    $v4ContentUrl = $contentServiceBaseUrl + "/client/v4/content.svc"
                    Write-Host -ForegroundColor Gray "trying $capabilityTitle v4 at $v4ContentUrl..."
                    # todo put a try catch block around this request
                    Invoke-WebRequest -Uri $v4ContentUrl -Headers $authorizationHeader -TimeoutSec $ServiceTimeoutSec | Out-Null
                    Write-Host -ForegroundColor Green "$capabilityTitle v4 OK  $v4ContentUrl"
                }
            } catch {
                if($_.Exception.Message.Contains("The operation has timed out.")) {
                    Write-Host -ForegroundColor Red "$capabilityTitle FAIL (timeout)  $capabilityEndpoint"
                } elseif($capabilityTitle.Equals("DeployerCapability") -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) {
                    Write-Host -ForegroundColor Red "$capabilityTitle FAIL (403 Forbidden)  $capabilityEndpoint"
                } elseif ($_.Exception.Response.StatusCode.value__ -eq 503) {
                    Write-Host -ForegroundColor Red "$capabilityTitle FAIL (503 Server Unavailable)  $capabilityEndpoint"
                } else {
                    # unexpexted error
                    throw $_
                }
            }
        }
    }
}