Automating Dynatrace Configuration with Terraform πŸš€

Praveen Dandu
3 min readNov 22, 2024

--

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:

  1. Consistency: Configuration-as-code eliminates manual setup discrepancies.
  2. Scalability: Easily manage configurations across environments or teams.
  3. 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:

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

  1. Define reusable modules.
  2. Use JSON files for resource definitions.
  3. 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!

--

--

Praveen Dandu
Praveen Dandu

Written by Praveen Dandu

πŸš€ DevOps Engineer | Automating Infrastructure, Streamlining Deployments | Continuous Integration & Delivery Specialist https://www.linkedin.com/in/pravin24/

No responses yet