Automating Dynatrace Configuration with Terraform π
Managing configurations in Dynatrace across multiple environments can be challenging without automation. Terraform provides a powerful way to define, manage, and scale Dynatrace configurations as code, reducing manual effort and ensuring consistency. In this guide, weβll cover how to structure a Terraform project to automate the management of Custom Attributes, Synthetic Monitoring, and Maintenance Windows.
Why Use Terraform with Dynatrace?
Benefits of using Terraform for Dynatrace automation include:
- Consistency: Configuration-as-code eliminates manual setup discrepancies.
- Scalability: Easily manage configurations across environments or teams.
- Automation: Apply, update, and destroy configurations seamlessly.
Project Structure
Before diving into the code, letβs look at the structure of our project. The directory layout ensures modularity, making it easier to manage and reuse components.
dynatrace-terraform/
βββ modules/
β βββ custom_attributes/
β βββ synthetic_monitoring/
β βββ maintenance_schedules/
βββ main.tf
βββ variables.tf
βββ custom_attributes.json
βββ synthetic_tests.json
βββ maintenance_windows.json
Hereβs what each file does:
- modules/: Contains reusable Terraform modules for each resource type.
- custom_attributes/: Manages Dynatrace custom attributes.
- synthetic_monitoring/: Handles synthetic monitoring tests like HTTP or browser checks.
- maintenance_schedules/: Defines and schedules maintenance windows.
- main.tf: The entry point for Terraform. This file integrates all modules and passes inputs from JSON files.
- variables.tf: Declares global variables to be used by the modules.
- custom_attributes.json, synthetic_tests.json, and maintenance_windows.json: JSON files containing resource-specific configurations.
Step-by-Step Guide
1. Setting Up the Terraform Provider
The Dynatrace provider enables us to interact with Dynatrace resources programmatically. Add the following to your main.tf
:
terraform {
required_providers {
dynatrace = {
source = "dynatrace-oss/dynatrace"
version = "~> 1.60.0"
}
}
required_version = ">= 1.5.0"
}
provider "dynatrace" {
api_url = var.dynatrace_api_url
api_token = var.dynatrace_api_token
}
2. Loading JSON Configurations
JSON files make it easy to decouple resource definitions from Terraform code. Use the fileset
and local_file
data sources to read these files.
Example for Synthetic Monitoring in main.tf
:
locals {
synthetic_test_files = tolist(fileset("${path.module}/synthetic_tests", "*.json"))
}
data "local_file" "synthetic_tests_files" {
count = length(local.synthetic_test_files)
filename = "${path.module}/synthetic_tests/${local.synthetic_test_files[count.index]}"
}
locals {
synthetic_tests = flatten([
for file in data.local_file.synthetic_tests_files : jsondecode(file.content)
])
}
3. Creating Reusable Modules
Each resource type gets its own module. Letβs break down one module, Synthetic Monitoring.
modules/synthetic_monitoring/main.tf
:
resource "dynatrace_http_monitor" "synthetic_test" {
for_each = { for test in var.synthetic_tests : test.name => test }
name = each.value.name
frequency = each.value.frequency
enabled = each.value.enabled
locations = each.value.locations
tags = each.value.tags
dynamic "script" {
for_each = lookup(each.value, "script", [])
content {
dynamic "request" {
for_each = script.value.request
content {
method = request.value.method
url = request.value.url
}
}
}
}
}
modules/synthetic_monitoring/variables.tf
:
variable "synthetic_tests" {
type = list(object({
name = string
frequency = number
enabled = optional(bool, true)
locations = optional(list(string), [])
tags = optional(list(string), [])
script = optional(list(object({
request = list(object({
method = string
url = string
}))
})))
}))
}
4. Example JSON Input
Define synthetic monitoring tests in synthetic_tests.json
:
[
{
"name": "Homepage Availability",
"frequency": 5,
"enabled": true,
"locations": ["GEOLOCATION-F3E06A526BE3B4C4"],
"script": [
{
"request": [
{
"method": "GET",
"url": "https://example.com/metrics/ping"
}
]
}
],
"tags": ["Environment:Production"]
}
]
5. Integrating Modules in main.tf
Pass the parsed JSON configurations to the module:
module "synthetic_monitoring" {
source = "./modules/synthetic_monitoring"
synthetic_tests = local.synthetic_tests
}
Applying the Configuration
Run the following commands to deploy the resources:
- Initialise Terraform:
terraform init
2. Plan Changes:
terraform plan
This shows the changes Terraform will make in Dynatrace.
3. Apply Changes:
terraform apply
Confirm the changes to apply them.
Scaling the Approach
The same principles can be applied to Custom Attributes and Maintenance Windows, following a similar structure:
- Define reusable modules.
- Use JSON files for resource definitions.
- Pass configurations dynamically to modules.
Conclusion
By adopting Terraform for Dynatrace, you unlock the benefits of Infrastructure as Code (IaC). This approach ensures:
- Consistency across environments.
- Easier scalability and management.
- Collaboration via version control.
Start small with a single module and gradually scale your configuration to include all Dynatrace resources. Happy automating!