From 63b8eb9aca460a6a877b6f9fea324f1a76ea5cbe Mon Sep 17 00:00:00 2001 From: petersin0422 Date: Fri, 5 Aug 2022 08:32:58 -0700 Subject: [PATCH] - implemented ability to manage automation account - implemented ability to manage multiple runbooks and schedules --- _common.tf | 11 +++++++ _terraform.tf | 3 ++ automation-account.tf | 18 +++++++++++ runbooks.tf | 27 ++++++++++++++++ schedule.tf | 69 +++++++++++++++++++++++++++++++++++++++++ variables.tf | 71 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 199 insertions(+) create mode 100644 _common.tf create mode 100644 _terraform.tf create mode 100644 automation-account.tf create mode 100644 runbooks.tf create mode 100644 schedule.tf create mode 100644 variables.tf diff --git a/_common.tf b/_common.tf new file mode 100644 index 0000000..35d20ed --- /dev/null +++ b/_common.tf @@ -0,0 +1,11 @@ +data "azurerm_resource_group" "current" { + name = var.azure.resource_group_name +} + +locals { + common_tags = { + managed-by = "Terraform" + } + + location = var.azure.location != null ? var.azure.location : data.azurerm_resource_group.current.location +} diff --git a/_terraform.tf b/_terraform.tf new file mode 100644 index 0000000..380e1ea --- /dev/null +++ b/_terraform.tf @@ -0,0 +1,3 @@ +terraform { + experiments = [module_variable_optional_attrs] +} \ No newline at end of file diff --git a/automation-account.tf b/automation-account.tf new file mode 100644 index 0000000..14d179e --- /dev/null +++ b/automation-account.tf @@ -0,0 +1,18 @@ +resource "azurerm_automation_account" "automation_account" { + name = var.name + public_network_access_enabled = true + resource_group_name = data.azurerm_resource_group.current.name + location = local.location + sku_name = "Basic" + + identity { + type = length(var.user_assigned_managed_identity_ids) > 0 ? "UserAssigned" : "SystemAssigned" + identity_ids = length(var.user_assigned_managed_identity_ids) > 0 ? var.user_assigned_managed_identity_ids : null + } + + tags = merge( + local.common_tags, + var.additional_tags_all, + var.additional_tags + ) +} \ No newline at end of file diff --git a/runbooks.tf b/runbooks.tf new file mode 100644 index 0000000..f5eec88 --- /dev/null +++ b/runbooks.tf @@ -0,0 +1,27 @@ +resource "azurerm_automation_runbook" "runbooks" { + for_each = var.runbooks + + name = each.key + resource_group_name = data.azurerm_resource_group.current.name + location = local.location + automation_account_name = azurerm_automation_account.automation_account.name + runbook_type = each.value.runbook_type != null ? each.value.runbook_type : "PowerShell" # Default runbook type to Powershell + log_progress = each.value.log_progress != null ? each.value.log_progress : true # Default log progress to true + log_verbose = each.value.log_verbose != null ? each.value.log_verbose : false # Default log verbose to false + description = each.value.description + content = substr(each.value.content, 0, 4) != "http" ? each.value.content : null + + dynamic "publish_content_link" { + for_each = substr(each.value.content, 0, 4) == "http" ? [1] : [] + + content { + uri = each.value.content + } + } + + tags = merge( + local.common_tags, + var.additional_tags_all, + each.value.additional_tags + ) +} \ No newline at end of file diff --git a/schedule.tf b/schedule.tf new file mode 100644 index 0000000..1cd52cf --- /dev/null +++ b/schedule.tf @@ -0,0 +1,69 @@ +locals { + runbooks_with_set_schedule = { + for name, runbook in var.runbooks : name => runbook if runbook.schedule != null + } + + week_to_number = { + "First" = "1", + "Second" = "2", + "Third" = "3", + "Fourth" = "4", + "Last" = "-1" + } +} + +resource "azurerm_automation_schedule" "schedule" { + for_each = local.runbooks_with_set_schedule + + name = "Schedule for ${each.key}" + resource_group_name = data.azurerm_resource_group.current.name + automation_account_name = azurerm_automation_account.automation_account.name + + frequency = each.value.schedule.hourly != null ? "Hour" : ( + each.value.schedule.daily != null ? "Day" : ( + each.value.schedule.weekly != null ? "Week" : ( + each.value.schedule.monthly != null ? "Month" : "OneTime" + ) + ) + ) + + description = each.value.schedule.description + + interval = each.value.schedule.hourly != null ? each.value.schedule.hourly.interval : ( + each.value.schedule.daily != null ? each.value.schedule.daily.interval : ( + each.value.schedule.weekly != null ? each.value.schedule.weekly.interval : ( + each.value.schedule.monthly != null ? each.value.schedule.monthly.interval : null + ) + ) + ) + + timezone = each.value.schedule.timezone + start_time = each.value.schedule.start_time + expiry_time = each.value.schedule.expiry_time + week_days = each.value.schedule.weekly != null ? each.value.schedule.weekly.every : null + + month_days = each.value.schedule.monthly != null ? ( + length(each.value.schedule.monthly.every[0]) < 2 ? each.value.schedule.monthly.every : null + ) : null + + dynamic "monthly_occurrence" { + for_each = each.value.schedule.monthly != null ? ( + length(each.value.schedule.monthly.every[0]) > 2 ? [1] : [] + ) : [] + + content { + day = each.value.schedule.monthly.every[1] + occurrence = local.week_to_number[each.value.schedule.monthly.every[0]] + } + } +} + +resource "azurerm_automation_job_schedule" "schedule_links" { + for_each = local.runbooks_with_set_schedule + + resource_group_name = data.azurerm_resource_group.current.name + automation_account_name = azurerm_automation_account.automation_account.name + runbook_name = azurerm_automation_runbook.runbooks[each.key].name + schedule_name = azurerm_automation_schedule.schedule[each.key].name + parameters = each.value.schedule.parameters +} \ No newline at end of file diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..0b8ded3 --- /dev/null +++ b/variables.tf @@ -0,0 +1,71 @@ +variable "azure" { + type = object({ + resource_group_name = string + location = optional(string) + }) + + description = "Where the resources will be deployed on" +} + +variable "name" { + type = string + description = "The name of the automation account. All associated resources' names will also be prefixed by this value" +} + +variable "additional_tags" { + type = map(string) + description = "Additional tags for the automation account" + default = {} +} + +variable "additional_tags_all" { + type = map(string) + description = "Additional tags for all resources in deployed with this module" + default = {} +} + +variable "runbooks" { + type = map(object({ + content = string + additional_tags = optional(map(string)) + description = optional(string) + log_progress = optional(bool) + log_verbose = optional(bool) + runbook_type = optional(string) + + schedule = optional(object({ + description = optional(string) + timezone = optional(string) + start_time = optional(string) + expiry_time = optional(string) + parameters = optional(map(string)) + + hourly = optional(object({ + interval = optional(number) + })) + + daily = optional(object({ + interval = optional(number) + })) + + weekly = optional(object({ + interval = optional(number) + every = list(string) + })) + + monthly = optional(object({ + interval = optional(number) + every = list(string) + })) + })) + })) + + description = "Defines and manages a list of Runbooks" + default = {} +} + +variable "user_assigned_managed_identity_ids" { + type = list(string) + description = "List of managed identity IDs used by the automation account to manage azure resources" + default = [] +} \ No newline at end of file