Introduction
Every DevOps Engineer is responsible for writing environment-agnostic code, which means that the code that is written should work in any environment (DEV/TEST/PREPROD/PROD). However, the configuration values could change across environments. In this article, we are going to learn how to dynamically change the environment-specific values in the Azure DevOps Pipelines using an Azure DevOps Extension called Replace Tokens.
In the below use case, we are going to learn how to replace the ARM template parameters using Replace Tokens. You can use the same technique for any requirements where you would like to dynamically change the values.
Use Case
Below is a very simple JSON file (named Tip10.parameters.json), which is used to pass Configuration values (also called Parameters files in ARM Templates).
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"pAppServicePlanName": {
"value": "az-devops-dev-eus-asp1"
},
"pAppServiceName": {
"value": "az-devops-dev-eus-wapp1"
},
"pAppInsightsName": {
"value": "az-devops-dev-eus-wapp1-ai"
},
"pSQLServerName": {
"value": "az-devops-dev-eus-sqlserver1"
}
}
}
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"pAppServicePlanName": {
"value": "#{pAppServicePlanName}#"
},
"pAppServiceName": {
"value": "#{pAppServiceName}#"
},
"pAppInsightsName": {
"value": "#{pAppInsightsName}#"
},
"pSQLServerName": {
"value": "#{pSQLServerName}#"
}
}
}
Azure DevOps Extensions - Replace Tokens
As discussed in this article, we are going to leverage a marketplace extension called Replace Tokens, which must be installed into your Azure DevOps Organization. You can download the extension from the Azure DevOps Market for Free at Azure DevOps – Replace Tokens
Azure DevOps Pipelines - Variable Group
Now, Let’s create three variable groups that contain values that are specific to three different environments as shown below.
Using the IValidateOptions<T> interface, we can also clean this up and assign the validation to the appropriate service. It helps us to simply use dependency injection and to decouple our validation from the configuration.
To do that, we must construct a new class, JwtConfigSettingsValidation, and require it to implement the IValidateOptions<JwtConfigSettings> interface. The Validate method, which allows you to return a ValidateOptionsResult, must then be implemented. If validation is unsuccessful, return Fail(message) or ValidateOptionsResult. if the validation is successful, success.