diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 29777a8..186761a 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -254,6 +254,4 @@ resource "azurerm_key_vault" "kv" { --- - - This dev container includes the Azure CLI, GitHub CLI, Terraform CLI, TFLint, and Terragrunt pre-installed and available on the PATH, along with the Terraform and Azure extensions for development. diff --git a/dev_center_dev_box_definitions.tf b/dev_center_dev_box_definitions.tf new file mode 100644 index 0000000..8fa0d30 --- /dev/null +++ b/dev_center_dev_box_definitions.tf @@ -0,0 +1,10 @@ +# Dev Center Dev Box Definitions module instantiation +module "dev_center_dev_box_definitions" { + source = "./modules/dev_center_dev_box_definition" + for_each = try(var.dev_center_dev_box_definitions, {}) + + global_settings = var.global_settings + dev_box_definition = each.value + dev_center_id = lookup(each.value, "dev_center_id", null) != null ? each.value.dev_center_id : module.dev_centers[each.value.dev_center.key].id + location = lookup(each.value, "region", null) != null ? each.value.region : module.resource_groups[each.value.resource_group.key].location +} diff --git a/docs/module_guide.md b/docs/module_guide.md index e46bf6e..95b4b36 100644 --- a/docs/module_guide.md +++ b/docs/module_guide.md @@ -122,12 +122,12 @@ dev_center_dev_box_definitions = { dev_center = { key = "devcenter1" } - image_reference = { - offer = "windows-11" - publisher = "microsoftwindowsdesktop" - sku = "win11-22h2-ent" - version = "latest" + resource_group = { + key = "rg1" } + # Currently assumes that image definition is one of that's available in the default gallery + # Format: /galleries/{gallery}/images/{image-definition} + image_reference_id = "/galleries/default/images/microsoftwindowsdesktop_windows-ent-cpc_win11-24h2-ent-cpc-m365" sku_name = "general_i_8c32gb256ssd_v2" hibernate_support = { enabled = true diff --git a/examples/dev_center/simple_case/configuration.tfvars b/examples/dev_center/simple_case/configuration.tfvars index 69b7bb6..1ee44fc 100644 --- a/examples/dev_center/simple_case/configuration.tfvars +++ b/examples/dev_center/simple_case/configuration.tfvars @@ -23,4 +23,4 @@ dev_centers = { module = "dev_center" } } -} +} \ No newline at end of file diff --git a/examples/dev_center_dev_box_definition/configuration.tfvars b/examples/dev_center_dev_box_definition/configuration.tfvars new file mode 100644 index 0000000..a995b66 --- /dev/null +++ b/examples/dev_center_dev_box_definition/configuration.tfvars @@ -0,0 +1,53 @@ +global_settings = { + prefixes = ["dev"] + random_length = 3 + passthrough = false + use_slug = true +} + +resource_groups = { + rg1 = { + name = "devfactory-dc" + region = "eastus" + tags = { + environment = "development" + workload = "devbox-example" + } + } +} + +dev_centers = { + devcenter1 = { + name = "devcenter" + resource_group = { + key = "rg1" + } + identity = { + type = "SystemAssigned" + } + tags = { + environment = "demo" + module = "dev_center" + } + } +} + +dev_center_dev_box_definitions = { + definition1 = { + name = "win11-dev" + dev_center = { + key = "devcenter1" + } + resource_group = { + key = "rg1" + } + # Currently assumes that image definition is one of that's available in the default gallery + # Format: /galleries/{gallery}/images/{image-definition} + image_reference_id = "/galleries/default/images/microsoftwindowsdesktop_windows-ent-cpc_win11-24h2-ent-cpc-m365" + sku_name = "general_i_8c32gb256ssd_v2" + tags = { + environment = "demo" + module = "dev_center_dev_box_definition" + } + } +} diff --git a/modules/dev_center_dev_box_definition/module.tf b/modules/dev_center_dev_box_definition/module.tf new file mode 100644 index 0000000..680d54a --- /dev/null +++ b/modules/dev_center_dev_box_definition/module.tf @@ -0,0 +1,34 @@ +terraform { + required_version = ">= 1.9.0" + required_providers { + azurecaf = { + source = "aztfmod/azurecaf" + version = "~> 1.2.0" + } + azurerm = { + source = "hashicorp/azurerm" + version = "~> 4.26.0" + } + } +} + +locals {} + +resource "azurecaf_name" "dev_box_definition" { + name = var.dev_box_definition.name + resource_type = "general" + prefixes = var.global_settings.prefixes + random_length = var.global_settings.random_length + clean_input = true + passthrough = var.global_settings.passthrough + use_slug = var.global_settings.use_slug +} + +resource "azurerm_dev_center_dev_box_definition" "dev_box_definition" { + name = azurecaf_name.dev_box_definition.result + location = var.location + dev_center_id = var.dev_center_id + image_reference_id = var.dev_box_definition.image_reference_id != null ? "${var.dev_center_id}${var.dev_box_definition.image_reference_id}" : null + sku_name = try(var.dev_box_definition.sku_name, null) + tags = try(var.tags, null) +} \ No newline at end of file diff --git a/modules/dev_center_dev_box_definition/output.tf b/modules/dev_center_dev_box_definition/output.tf new file mode 100644 index 0000000..d2f05ec --- /dev/null +++ b/modules/dev_center_dev_box_definition/output.tf @@ -0,0 +1,4 @@ +output "id" { + description = "The ID of the Dev Center Dev Box Definition" + value = azurerm_dev_center_dev_box_definition.dev_box_definition.id +} diff --git a/modules/dev_center_dev_box_definition/variables.tf b/modules/dev_center_dev_box_definition/variables.tf new file mode 100644 index 0000000..b922079 --- /dev/null +++ b/modules/dev_center_dev_box_definition/variables.tf @@ -0,0 +1,35 @@ +variable "global_settings" { + description = "Global settings object" + type = object({ + prefixes = optional(list(string)) + random_length = optional(number) + passthrough = optional(bool) + use_slug = optional(bool) + }) +} + +variable "dev_center_id" { + description = "The ID of the Dev Center in which to create the project" + type = string +} + +variable "location" { + description = "The location/region where the Dev Center Project is created" + type = string +} + +variable "tags" { + description = "A mapping of tags to assign to the resource" + type = map(string) + default = {} +} + +variable "dev_box_definition" { + description = "Configuration object for the Dev Box Definition" + type = object({ + name = string + image_reference_id = string + sku_name = string + tags = optional(map(string)) + }) +} diff --git a/tests/unit/dev_center_dev_box_definition/dev_box_definition_test.tftest.hcl b/tests/unit/dev_center_dev_box_definition/dev_box_definition_test.tftest.hcl new file mode 100644 index 0000000..9e1b395 --- /dev/null +++ b/tests/unit/dev_center_dev_box_definition/dev_box_definition_test.tftest.hcl @@ -0,0 +1,88 @@ +variables { + global_settings = { + prefixes = ["dev"] + random_length = 3 + passthrough = false + use_slug = true + } + + resource_groups = { + rg1 = { + name = "test-resource-group" + region = "eastus" + tags = { + environment = "test" + } + } + } + + dev_centers = { + devcenter1 = { + name = "test-dev-center" + resource_group = { + key = "rg1" + } + tags = { + environment = "test" + module = "dev_center" + } + } + } + + dev_center_dev_box_definitions = { + definition1 = { + name = "test-dev-box-definition" + dev_center = { + key = "devcenter1" + } + resource_group = { + key = "rg1" + } + image_reference_id = try(var.dev_box_definition.image_reference_id, null) + sku_name = try(var.dev_box_definition.sku_name, null) + tags = { + environment = "test" + module = "dev_center_dev_box_definition" + } + } + } + + // Empty variables required by the root module + dev_center_galleries = {} + dev_center_projects = {} + dev_center_environment_types = {} + dev_center_project_environment_types = {} + dev_center_network_connections = {} + dev_center_catalogs = {} + shared_image_galleries = {} +} + +mock_provider "azurerm" {} + +run "dev_box_definition_creation" { + command = plan + + module { + source = "../../../" + } + + assert { + condition = module.dev_center_dev_box_definitions["definition1"].name != "" + error_message = "Dev Box Definition name should not be empty" + } + + assert { + condition = contains(keys(module.dev_center_dev_box_definitions["definition1"]), "id") + error_message = "Dev Box Definition ID should be present in module outputs" + } + + assert { + condition = contains(keys(module.dev_center_dev_box_definitions["definition1"].tags), "environment") + error_message = "Dev Box Definition tags did not contain environment tag" + } + + assert { + condition = contains(keys(module.dev_center_dev_box_definitions["definition1"].tags), "module") + error_message = "Dev Box Definition tags did not contain module tag" + } +}