Use a host header value for testing services on Kubernetes
tswiftma
Posted on March 2, 2021
What is a Host Header? Basically it's an address that the web server (or ingress service) will send a request to.
At my company we are in the process of moving some of our services from Azure App Services to AKS. To run my C# API Integration tests against the Kubernetes pods our DevOps guys told me that I needed to use host header values to hit the internal K8S endpoints of the services.
This was fairly easy to accomplish in C# as I just added a default parameter for the host header to my Post method (as well as my other REST methods).
/// <summary>
/// Helper method to add headers for PostAsync operation with no data.
/// </summary>
/// <param name="httpClient">HttpClient.</param>
/// <param name="url">url.</param>
/// <param name="hostHeader">Host header.</param>
/// <returns>HttpResponseMessage.</returns>
public static Task<HttpResponseMessage> PostAsJsonAsync(this HttpClient httpClient, string url, string hostHeader = "none")
{
var stringContent = new StringContent(string.Empty);
stringContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
var dataAsString = stringContent.ToString();
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = new StringContent(dataAsString, Encoding.UTF8, "application/json"),
};
if (hostHeader != "none")
{
// Host name for K8S tests
httpClient.DefaultRequestHeaders.Host = hostHeader;
}
return httpClient.PostAsync(url, stringContent);
}
By default the Host Header value is "none" for normal automation runs. When the tests are run against the AKS deployment we pass the host header variable value into the K8S yaml pipeline.
- stage: Test_Online
pool:
name: 'linux-agents'
displayName: Test Online
condition: and(succeeded(),eq(${{parameters.switch}}, true))
variables:
- ${{ if eq(parameters.envtype, 'prod') }}:
- name: MyApiHostHeader
value: ${{parameters.deployenv}}-${{parameters.service}}-online.${{parameters.region}}.${{parameters.deployenv}}.test.com
- ${{ if eq(parameters.envtype, 'nonprod') }}:
- ${{ if eq(parameters.deployenv, 'dev') }}:
- name: MyApiHostHeader
value:
In my Visual Studio solution for the API automation I'm reading the hostHeader value from appSettings.json. In the K8S yaml pipeline we have to do a bunch of steps to run the job, including a FileTransform task to substitute the HostHeader variable we added earlier into the solution for the tests to run.
jobs:
- job: Test_Offline
steps:
- ${{ if eq(parameters.skipTests, false) }}:
- checkout: automation
persistCredentials: true
- script: |
apt-get update
apt-get install mono-complete
displayName: Install Dotnet prerequisites
- task: UseDotNet@2
displayName: 'Use .NET Core'
inputs:
version: $(dotnet_core_version)
- task: NuGetToolInstaller@1
displayName: 'Use NuGet'
inputs:
versionSpec: $(nuget_version)
- task: NuGetCommand@2
displayName: 'NuGet restore'
inputs:
restoreSolution: '**\MyAPITests.sln'
#this task performs envvar substitution. we need to set the vars to override in lib var group or
#the env: block does NOT seem to work for passing in variable to task. we set these in global variables above
- task: FileTransform@1
inputs:
folderPath: '$(System.DefaultWorkingDirectory)'
fileType: json
targetFiles: '**/**/appSettings.json'
- script: |
cat MyAPITests/MyAPITests/appSettings.json
displayName: show transform
- task: DotNetCoreCLI@1
displayName: 'Build solution: $(solution)'
inputs:
command: 'build'
projects: |
MyAPITests/$(solution)
- task: DotNetCoreCLI@1
displayName: 'Run API tests in solution: $(solution)'
inputs:
command: test
projects: |
HAPAPITests/**/*Tests/*.csproj
arguments: '-c release -v d --filter Category=${{ parameters.testCategory }} --logger "trx;verbosity=detailed;LogFileName=DotNetApiAutomationTestResults.trx"'
- task: PublishTestResults@2
displayName: 'Publish Offline Test Results'
inputs:
searchFolder: MyAPITests
testResultsFormat: 'VSTest'
testResultsFiles: '**/*.trx'
testRunTitle: '${{ parameters.service }} - Offline ApiAutomation ${{ parameters.deployenv }}'
publishRunAttachments: true
failTaskOnFailedTests: false
condition: succeededOrFailed()
There's a lot of moving parts here with VS, Azure DevOps pipelines and AKS but we got it working!
Posted on March 2, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.