Deployment Guide: Using Terraform for Daily Administrative Operations
This guide focuses on daily administrative operations using Terraform after the initial deployment:
- Keeping the .tfstate file safe
- Importing an existing Infrastructure into Terraform
- Checking an Infrastructure for changes after the initial deployment
- Checking the Endpoint App settings (Workspace App, Enterprise Browser) for changes after the initial deployment
- Changing settings/configurations of already deployed entities (Machine Catalogs, Delivery Groups, Policies, Workspace App configurations)
- Adding/removing entities to/from the infrastructure
Terraform's flexibility and wide range of integrations make it a valuable tool for DevOps and infrastructure management.
Overview
Terraform is an Infrastructure-as-Code (IaC) tool that defines cloud and on-prem resources in easy-readable configuration files rather than through a GUI.
These configurations can be versioned, reused, and shared and are created in its native declarative configuration language known as HashiCorp Configuration Language (HCL), or optionally using JSON.
IaC allows you to build, change, manage, and check your infrastructure safely and consistently by defining resource configurations.
Terraform is declarative:
You tell the Terraform provider the desired state of your planned deployment.
You do not need to write every step in your code to achieve this goal.
The provider takes care of all needed steps.
Terraform is idempotent:
No matter how often you execute the same Terraform code - your Infrastructure will remain the same unless you change the code.
You will see in the examples below, that we change only the code parts we need to alter the Infrastructure and rerun the complete Terraform code.
On Citrix Tech Zone´s Automation page, you can find various guides on initially deploying Citrix DaaS or Citrix CVAD using Terraform.
Note:
Please find a description of installing Terraform and initial configurations in our Tech Zone Deployment Guide: Installing Terraform and Configuring the Citrix Terraform Provider.
If you want to see all the mentioned examples in this guide in action, please watch our Tech Insight video on our YouTube channel.
The State
Terraform stores information about your infrastructure and configuration in its State.
It primarily maps the deployed resources to the infrastructure and keeps needed metadata.
The State is stored by default in a local file named "terraform.tfstate".
Terraform uses the State to determine which changes must be made to your infrastructure. Terraform automatically refreshes the state with the existing infrastructure before any alterations are initiated.
Important:
Be very careful with a locally saved .tfstate file—it is recommended that you store it in a safe, encrypted manner with limited access and use a versioning control system.
Caution:
Terraform´s .tfstate can contain sensitive data like database passwords, user passwords, or private keys.
If you use locally stored State files (=Local State), they are stored on your machine as plain-text JSON files.
If you use remote stored State files (=Remote State), the State is only transferred from the remote backend to memory when Terraform uses it. Be aware that the transport can be unencrypted.
The .tfstate file can grow quite large—for example, the .tfstate file in our demo environment is more than 5MB.
Example of a representation of a Machine Catalog in a locally stored .tfstate file:
..., { "mode": "managed", "type": "citrix_machine_catalog", "name": "machine_catalog_0", "provider": "provider[\"registry.terraform.io/citrix/citrix\"]", "instances": [ { "schema_version": 0, "attributes": { "allocation_type": "Random", "built_in_scopes": [ "00000000-0000-0000-0000-000000000000" ], "description": "Machine Catalog on Azure based on Windows 11 Single-Session for TMM-Gerhard", "id": "95d6xxxx-xxxx-xxxx-xxxx-xxxxxxxxdc35", "inherited_scopes": [], "is_power_managed": null, "is_remote_pc": null, "machine_accounts": null, "machine_catalog_folder_path": null, "metadata": null, "minimum_functional_level": "L7_34", "name": "MC-TMM-GK-AZURE-W11-SS", "provisioning_scheme": { "availability_zones": [ "1" ], "aws_machine_config": null, "azure_machine_config": { "azure_master_image": { "container": null, "gallery_image": null, "master_image": "TMM-GK-W11-SS-M_OsDisk_1_7d8xxxxxxxx", "resource_group": "tmm_gerhard_westeurope", "shared_subscription": null, "storage_account": null }, "azure_pvs_config": null, "disk_encryption_set": null, "enroll_in_intune": null, "image_update_reboot_options": null, "license_type": "Windows_Client", "machine_profile": { "machine_profile_resource_group": "tmm_gerhard_westeurope", "machine_profile_template_spec_name": null, "machine_profile_template_spec_version": null, "machine_profile_vm_name": "TMM-GK-W11-SS-M" }, "master_image_note": "", "service_offering": "Standard_D2s_v5", "storage_type": "Premium_LRS", "use_azure_compute_gallery": null, "use_managed_disks": true, "vda_resource_group": "tmm_gerhard_westeurope", "writeback_cache": null }, "custom_properties": null, "gcp_machine_config": null, "hypervisor": "bec2xxxx-xxxx-xxxx-xxxx-xxxxxxxxf8f0", "hypervisor_resource_pool": "2c70xxxx-xxxx-xxxx-xxxx-xxxxxxxx87cb", "identity_type": "ActiveDirectory", "machine_account_creation_rules": { "naming_scheme": "TMM-GK-W11-SS-#", "naming_scheme_type": "Numeric" }, "machine_domain_identity": { "domain": "democloud.corp", "domain_ou": "OU=_AZURE,OU=_WORKER,OU=_CITRIX,OU=TACG,OU=EBC-TMM,DC=democloud,DC=corp", "service_account": "xxxxxxxxxxxxxxxxxxxxxxxx", "service_account_password": "xxxxxxxxxxxxxxxxxxxxxxxx" }, "metadata": null, "network_mapping": null, "number_of_total_machines": 1, "nutanix_machine_config": null, "scvmm_machine_config": null, "vsphere_machine_config": null, "xenserver_machine_config": null }, "provisioning_type": "MCS", "remote_pc_ous": null, "scopes": [], "session_support": "SingleSession", "tags": null, "tenants": null, "vda_upgrade_type": null, "zone": "4050xxxx-xxxx-xxxx-xxxx-xxxxxxxxc507" }, "sensitive_attributes": [ [ { "type": "get_attr", "value": "provisioning_scheme" }, { "type": "get_attr", "value": "machine_domain_identity" }, { "type": "get_attr", "value": "service_account_password" } ] ] } ] }, ...Sensitive data would be readable in clear text. |
Sensitive data would be readable in clear text.
Keeping the State safe
The recommended way to keep the State secure is not to use Local State but Remote State.
The State is written to a remote data store. Terraform supports HCP Terraform, HashiCorp Consul, Amazon S3, Azure Blob Storage, Google Cloud Storage, Alibaba Cloud OSS, and more.
As mentioned, Terraform will not persist the State anywhere on the local disk.
It will write the State locally only in the case of a non-recoverable error, where writing the State to the backend fails. This is to prevent data loss.
We use an Azure Storage Account to store the State in this example.
You can use Terraform to create the needed Storage Account:
data "azurerm_resource_group" "GetAzureRG" { name = "TMM-Gerhard-WestEurope" }
resource "azurerm_storage_account" "AzureStorageAccountForTerraform" { name = "${var.TF-StorageAccount-Name}" resource_group_name = data.azurerm_resource_group.GetAzureRG.name location = data.azurerm_resource_group.GetAzureRG.location account_tier = "Standard" account_replication_type = "LRS" allow_nested_items_to_be_public = false
tags = { environment = "TMM-Gerhard" } }
resource "azurerm_storage_container" "AzureStorageAccountContainerForTerraform" { depends_on = [ azurerm_storage_account.AzureStorageAccountForTerraform ] name = "${var.TF-StorageAccountContainer-Name}" storage_account_name = azurerm_storage_account.AzureStorageAccountForTerraform.name container_access_type = "private" }
|
Or you can use PowerShell to create the needed Storage Account:
# Get Azure Resource Group
# Create Azure Blob Container
# Retrieve Storage Container Access Key |
Now you can configure Terraform to use Remote State using a backend configuration:
terraform { required_providers { azurerm = { source = "hashicorp/azurerm" version = "=>4.9" } }
backend "azurerm" { resource_group_name = "tmm_gerhard_westeurope" storage_account_name = "tmmgkstorageaccount" container_name = "terraform" key = "terraform.tfstate" use_oidc = true client_id = "a99fxXxX-xXxX-xXxX-xXxX-xXxXxXxXxd2de" client_secret = "xXxX-xXxX-xXxX-xXxX-xXxXxXxXx" subscription_id = "893axXxX-xXxX-xXxX-xXxX-xXxXxXxXx2de793" tenant_id = "db32xXxX-xXxX-xXxX-xXxX-xXxXxXxXx2de49f" }
}
provider "azurerm" { features {} } |
Caution:
You cannot use variables in the backend configuration part. You need to use define the settings in clear text, including all sensitive settings.
Important:
Azure Storage blobs are automatically locked before any operation writes State.
This prevents concurrent State operations.
All Data stored in an Azure blob is encrypted.
Terraform retrieves the State from the backend and stores it in local memory.
The Transport is usually encrypted, as accessing the Azure Storage Container enforces a TLS-capable connection.
Terraform initializes successfully using Remote State:
PS C:\_TERRAFORM\_BACKEND> terraform init |
You can see the .tfstate file in the Azure Storage Container:
You have successfully configured Terraform to use Remote State.
Importing an existing Infrastructure into Terraform
You can import an existing Infrastructure using a PowerShell script, which enables you to use all the benefits of Terraform.
The script works with Citrix DaaS- and Citrix CVAD-based environments.
The script collects the list of resources, imports them into Terraform, and generates the Terraform skeletons for the resources.
Note:
The Onboarding script is still in Tech Preview.
You can download the actual version of the Onboarding script from our GitHub repository.
The needed Terraform configuration is straightforward:
terraform { required_version = ">= 1.9.7"
required_providers { citrix = { source = "citrix/citrix" version = "=1.0.7" } }
backend "local" {} } |
We altered the script to insert all sensitive information directly into the script and do not need to store sensitive information in variables:
... [CmdletBinding()] Param ( [Parameter(Mandatory = $false)] [string] $CustomerId = "dcxXxXxXxXx",
[Parameter(Mandatory = $false)] [string] $ClientId = "4045xXxX-xXxX-xXxX-xXxX-xXxXxXxXxd2dea,
[Parameter(Mandatory = $false)] [string] $ClientSecret ="xXxXxXxXxXxXxXxXx",
[Parameter(Mandatory = $false)] [string] $DomainFqdn,
[Parameter(Mandatory = $false)] [string] $Hostname = "api.cloud.com",
[Parameter(Mandatory = $false)] [ValidateSet("Production", "Staging")] [string] $Environment = "Production",
[Parameter(Mandatory = $false)] [switch] $SetDependencyRelationship,
[Parameter(Mandatory = $false)] [switch] $DisableSSLValidation ) ... |
Before running the script, the Terraform provider must be initialized.
Afterwards, you can start the script:
PS C:\_TERRAFORM\_ONBOARDING> .\terraform-onboarding-v3.ps1 ... The resources that were imported are shown above. These resources are now inyour Terraform state and will henceforth be managed by Terraform. citrix.tf citrix_admin_role.tf citrix_admin_scope.tf citrix_application.tf citrix_application_icon.tf citrix_azure_hypervisor.tf citrix_azure_hypervisor_resource_pool.tf citrix_delivery_group.tf citrix_machine_catalog.tf citrix_policy_set.tf citrix_vsphere_hypervisor.tf citrix_vsphere_hypervisor_resource_pool.tf citrix_zone.tf PS C:\_TERRAFORM\_ONBOARDING> |
After about 5 minutes, the script has successfully imported the environment.
You now have all entities transformed into Terraform files which can be viewed and edited e.g., in Visual Studio Code:
You have successfully transformed your existing Infrastructure in Infrastructure-as-Code (IaC).
Checking an Infrastructure for changes after the initial deployment
You can leverage Terraform to check your infrastructure for alterations/changes that might not have been wanted or that accidentally happened.
Terraform will notify you about these changes and can revert them after asking for consent.
You need a connection to your Infrastructure and a valid State.
Example 1: Deactivation of AutoScale
In our sample Infrastructure, AutoScale is usually enabled for all Delivery Groups, but someone changed the AutoScale Settings of a Delivery Group. This is unwanted, as additional costs could arise if AutoScale is disabled.
Citrix WebStudio shows the deactivation of AutoScale:
As it would be impracticable to check all essential settings using WebStudio, we leverage Terraform to scan our environment for changes:
You only need to run terraform plan in your Terraform directory, where your Terraform files are saved to scan for changes:
PS C:\_TERRAFORM\_CCOnAzureV2\CCOnAzureV2-DeployCCEntities> terraform plan |
Terraform found the change and notifies accordingly:
# citrix_delivery_group.CreateDG will be updated in-place ~ resource "citrix_delivery_group" "CreateDG" { ~ autoscale_settings = { ~ autoscale_enabled = false -> true |
If you now run terraform apply, these changes will be remitted, and your infrastructure will match the initial State again:
Caution:
Terraform will ask for your confirmation before remitting.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
Be aware that the remittance can severely affect the currently running infrastructure, as the changes will take effect immediately.
PS C:\_TERRAFORM\_CCOnAzureV2\CCOnAzureV2-DeployCCEntities> terraform apply |
Terraform has successfully remitted the change to the original State.
Running terraform plan shows that the Infrastructure matches the original State again:
PS C:\_TERRAFORM\_CCOnAzureV2\CCOnAzureV2-DeployCCEntities> terraform plan ...
citrix_delivery_group.CreateDG: Refreshing state... [id=3dee598d-3a66-4a43-b3ce-1d989e75a3c4] |
Citrix WebStudio also reflects the re-enablement of AutoScale:
Example 2: Policy Changes
Another important aspect of keeping an Infrastructure in a desired state are the Policies.
Changes in Policies can have various negative consequences. In this example, IT does not want Native Printer Drivers installed. You can leverage Terraform to detect these changes as well:
PS C:\_TERRAFORM\_CCOnAzureV2\CCOnAzureV2-CreatePoliciesAndScopes> terraform plan |
You can now run terraform apply, to remit these changes, and your infrastructure matches the initial State again:
PS C:\_TERRAFORM\_CCOnAzureV2\CCOnAzureV2-CreatePoliciesAndScopes> terraform apply |
Terraform has successfully remitted the change to the original State.
Running terraform plan shows that the Infrastructure matches the original State again:
PS C:\_TERRAFORM\_CCOnAzureV2\CCOnAzureV2-CreatePoliciesAndScopes> terraform plan |
Example 3: Automating the Checks using the Config Drift Notification Script
Automating the check for Infrastructure changes might be helpful so you do not need to run terraform plan manually. There are various ways to do this, so use your preferred method according to your needs.
Note:
You can automate this process using our Provider Config Drift Notification script on GitHub.
The output of the Config Drift Notification script shows the changes:
PS C:\_TERRAFORM\_CCOnAzureV2\CCOnAzureV2-DeployCCEntities> .\config-drift.ps1 Terraform Config Drift Detected: --------------------------------------------------------------------------------------------------- # citrix_delivery_group.CreateDG has changed ~ resource "citrix_delivery_group" "CreateDG" { ~ autoscale_settings = { ~ autoscale_enabled = true -> false # (22 unchanged attributes hidden) } id = "3dee598d-3a66-4a43-b3ce-1d989e75a3c4" name = "DG-TMM-GK-TF-Azure" # (12 unchanged attributes hidden) } PS C:\_TERRAFORM\_CCOnAzureV2\CCOnAzureV2-DeployCCEntities> |
You can hook onto the output and take further steps, as we will show in the new script shortly.
Example 4: Using PowerShell to get Details about Changes
After creating a repetitive task to check for Infrastructure changes, getting more details about the changes would make sense.
We assume you run a daily task to check for changes.
Note:
If you have configured Configuration Logging, you could get more insights about an unwanted change. Check the Configuration Logging events in Citrix WebStudio for details or use PowerShell or REST-API calls to retrieve them.
You must install the Citrix Remote PowerShell SDK to retrieve the Configuration Logging events.
Add-PSSnapin Citrix.* |
The HTML-based reports contain all changes to your Infrastructure on the particular day (example):
18.11.2024 10:30:41 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Edit Delivery Group 'DG-TMM-GK-AZ-W11-SS' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 10:45:35 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Edit Delivery Group 'DG-TMM-GK-TF-Azure' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 11:08:20 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Edit Delivery Group 'DG-TMM-GK-TF-Azure' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 11:10:02 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Edit Delivery Group 'DG-TMM-GK-TF-Azure' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 11:31:39 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Edit Delivery Group 'DG-TMM-GK-TF-Azure' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 11:33:35 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Edit Delivery Group 'DG-TMM-GK-TF-Azure' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 11:33:36 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Edit 'TMM-GK-TF-RebootSchedule' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 11:38:37 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Edit Delivery Group 'DG-TMM-GK-TF-Azure' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 11:38:37 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Remove Power Time Scheme 'DG-TMM-GK-TF-Azure_AS-TMM-GK-TF-Azure-Weekday' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 11:38:37 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Create Power Time Scheme 'DG-TMM-GK-TF-Azure_AS-TMM-GK-TF-Azure-Weekday' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 11:38:38 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Remove 'TMM-GK-TF-RebootSchedule' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 11:38:38 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Create 'TMM-GK-TF-RebootSchedule' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 11:38:56 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Edit Delivery Group 'DG-TMM-GK-TF-Azure' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 11:39:29 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Edit Delivery Group 'DG-TMM-GK-TF-Azure' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 11:39:29 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Remove Power Time Scheme 'DG-TMM-GK-TF-Azure_AS-TMM-GK-TF-Azure-Weekday' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 11:39:29 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Create Power Time Scheme 'DG-TMM-GK-TF-Azure_AS-TMM-GK-TF-Azure-Weekday' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 11:39:30 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Remove 'TMM-GK-TF-RebootSchedule' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 11:39:30 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Create 'TMM-GK-TF-RebootSchedule' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 11:53:45 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Edit Delivery Group 'DG-TMM-GK-TF-Azure' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 11:54:16 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Edit Delivery Group 'DG-TMM-GK-TF-Azure' |
Erfolgreich |
172.29.77.84 |
|
18.11.2024 12:05:46 |
tmm-xxxxx@az.the-austrian-citrix-guy.at |
Edit Delivery Group 'DG-TMM-GK-TF-Azure' |
Erfolgreich |
172.29.77.84 |
You can now align the events in the report with the changes detected by Terraform to get more information.
Example 5: Using Azure Automation to periodically check for Changes and Receiving Notifications
The most convenient and recommended way is to automate the checks and the remediation using a script and, in this case, Azure Automation.
We are currently combining all functionalities of the 3 previously mentioned examples in one new script, which will run on Azure Automation.
We will update this section as soon as all tests are completed. Stay tuned.
Altering an Infrastructure after the Initial Deployment
You can leverage Terraform to check your Infrastructure for alterations/changes that might not be wanted or accidentally happened and alter it as new needs arise programmatically.
You can alter any Terraform-supporting entity in all layers: the Compute Layer, the Resource Layer, the Control Layer, the Access Layer, and the User Layer.
Therefore, you can leverage different providers in the same code – like this example from a current project:
Example 1: User Layer: Reconfiguring the Citrix Workspace App/Enterprise Browser
In this example, we will reconfigure the Citrix Workspace App by altering the settings used by the Citrix Global App Configuration service. You can access the current settings using Citrix WebStudio:
If you click Configure, you can choose the Endpoint app – Citrix Workspace App or Citrix Enterprise Browser. All corresponding settings of the respective application can be shown by clicking on View configured changes:
Leverage Terraform to alter the settings – for example, showing the Connection Center option in the Advance Preferences of the Workspace App – this setting is currently set to hide it:
# Configuring Citrix Cloud Global App Configuration Service ## Create Settings resource "citrix_gac_settings" "SetWorkspaceAppConfiguration" { service_url = "${var.GACS-ServiceURL}" name = "${var.GACS-Settings-Name}" description = "${var.GACS-Settings-Description}"
app_settings = { windows = [ { user_override = false, category = "Root", settings = [ { name = "Hide advanced preferences", value_string = "true" }, { name = "Hide connection center", value_string = "true" } ] }, ... |
To change this setting, comment the corresponding code segment and apply the Terraform code using terraform apply.
# Configuring Citrix Cloud Global App Configuration Service ## Create Settings resource "citrix_gac_settings" "SetWorkspaceAppConfiguration" { service_url = "${var.GACS-ServiceURL}" name = "${var.GACS-Settings-Name}" description = "${var.GACS-Settings-Description}"
app_settings = { windows = [ { user_override = false, category = "Root", settings = [ { name = "Hide advanced preferences", value_string = "true" }, /* { name = "Hide connection center", value_string = "true" } */ ] |
Terraform changes the setting as intended:
PS C:\_TERRAFORM\_TMM-CC-GACS> terraform apply
|
The settings in WebStudio reflect the change:
The changed configuration item is no longer shown. Terraform has successfully changed a Workspace App setting.
Example 2: Platform Layer: Updating the Azure Machine Types
In this example, we will update the Machine Types of the Cloud Connector Machines.
We have defined the Machine Type in a Terraform Variable:
... |
We change this variable´s value to a new value:
... |
terraform plan shows that it can update the VMs in place and change the size from Standard_D2s_v5 to Standard_D4s_v5 – nothing will be destroyed or re-created:
PS C:\_TERRAFORM\_CCOnAzureV2\CCOnAzureV2-ChangeVMSize> terraform plan |
terraform apply will change the VM size in-place:
Terraform will perform the following actions: |
Terraform has successfully changed the VM size.
Example 3: Resource Layer: Updating a Machine Catalog – Deploy a New Master Image Version
In this example, we will update a Machine Catalog and deploy a new Master Image version.
You can access the current settings using Citrix WebStudio:
The current Master Image version is W11-BaseImageDefinition-1-baseDisk-3w0te.
This is also reflected in the initially deployed Terraform code:
#### Creating the Machine Catalog based on Image Definitions and Image Versions resource "citrix_machine_catalog" "CreateAzureImgDefMCSCatalog" { depends_on = [ time_sleep.wait_30_seconds1 ] name = "${var.CC-Azure-MCImgDef-Name}" description = "${var.CC-Azure-MCImgDef-Description}" allocation_type = "${var.CC-Azure-MCImgDef-AllocationType}" session_support = "${var.CC-Azure-MCImgDef-SessionType}" provisioning_type = "MCS" #zone = data.local_file.LoadZoneID.content zone = data.citrix_zone.GetTFAzureZoneID.id provisioning_scheme = { hypervisor = citrix_azure_hypervisor.CreateAzureHostingConnection.id hypervisor_resource_pool = citrix_azure_hypervisor_resource_pool.CreateAzureHostingConnectionPool.id identity_type = "${var.CC-Azure-MCImgDef-IDPType}"
machine_domain_identity = { domain = "${var.CC-Azure-MCImgDef-Domain}" domain_ou = "${var.CC-Azure-MCImgDef-DomainOU}" service_account = "${var.CC-Azure-MCImgDef-DomainAdmin-Username-UPN}" service_account_password = "${var.CC-Azure-MCImgDef-DomainAdmin-Password}" }
azure_machine_config = { storage_type = "Standard_LRS" use_managed_disks = true service_offering = "${var.CC-Azure-MCImgDef-VMSize}"
azure_master_image = { resource_group = "${var.CC-Azure-MCImgDef-MasterImage-RG}" master_image = "${var.CC-Azure-MCImgDef-MasterImage}" #master_image = "${var.CC-Azure-MCImgDef-MasterImage-V3}" }
machine_profile = { machine_profile_resource_group = "${var.TACG-TMM-ResourceGroup-Name}" machine_profile_vm_name = "${var.CC-Azure-MCImgDef-VMProfileName}" }
}
number_of_total_machines = 1
machine_account_creation_rules = { naming_scheme = "${var.CC-Azure-MCImgDef-NamingScheme-Name}" naming_scheme_type = "${var.CC-Azure-MCImgDef-NamingScheme-Type}" } } } |
The Terraform code references to a variable which holds the current Master Image name:
master_image = "${var.CC-Azure-MCImgDef-MasterImage}" |
This variable´s value is:
... "CC-Azure-MCImgDef-MasterImage":"W11-BaseImageDefinition-1-baseDisk-3w0te", ... |
We now change the Terraform code to use a new Master Image version:
azure_master_image = { resource_group = "${var.CC-Azure-MCImgDef-MasterImage-RG}" master_image = "${var.CC-Azure-MCImgDef-MasterImage}" #master_image = "${var.CC-Azure-MCImgDef-MasterImage-V3}" } |
to
|
The new variable´s value is:
... "CC-Azure-MCImgDef-MasterImage-V3":" W11-BaseImageDefinition-3-baseDisk-my3dm", ... |
Running terraform apply will change the Machine Catalog and apply the new Image version:
PS C:\_TERRAFORM\_CCOnAzureV2\CCOnAzureV2-DeployCCEntities> terraform apply |
Terraform has successfully changed the Master Image version.
WebStudio reflects this change:
Adding/Removing Entities to/from an Infrastructure after the initial Deployment
At last, you can leverage Terraform to add or remove whole entities if needed.
Example 1: Adding a Delivery Group
We will add a new Delivery Group to our environment in this example. You can access the current Delivery Groups using Citrix WebStudio:
We just need to alter the Terraform code to add the new Delivery Group – currently, it is uncommented, and this needs to be removed:
#### Create the Delivery Group based on the Image Definition-based Machine Catalog /* resource "citrix_delivery_group" "CreateImgDefDG" { name = "${var.CC-Azure-DGImgDef-Name}" associated_machine_catalogs = [ { machine_catalog = citrix_machine_catalog.CreateAzureImgDefMCSCatalog.id machine_count = "${var.CC-Azure-MCImgDef-Machine_Count}" } ] desktops = [ { published_name = "${var.CC-Azure-DGImgDef-PublishedDesktopName}" description = "${var.CC-Azure-DGImgDef-Description}" restricted_access_users = { allow_list = [ "xXxXxXxXxXxXxXxXx", ] } enabled = true }
] autoscale_settings = { autoscale_enabled = true disconnect_peak_idle_session_after_seconds = 60 disconnect_off_peak_idle_session_after_seconds = 60 log_off_off_peak_disconnected_session_after_seconds = 60 log_off_peak_disconnected_session_after_seconds = 60
peak_log_off_action = "Suspend" off_peak_log_off_action = "Suspend" peak_disconnect_action = "Suspend" off_peak_disconnect_action = "Suspend"
power_time_schemes = [ { days_of_week = [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" ] name = "${var.CC-Azure-DGImgDef-AS-Name}" display_name = "${var.CC-Azure-DGImgDef-AS-Name}" peak_time_ranges = [ "09:00-17:00" ] pool_size_schedules = [ { time_range = "09:00-17:00", pool_size = 1 } ] pool_using_percentage = false }, ] } restricted_access_users = { allow_list = [ "xXxXxXxXxXx", ] } reboot_schedules = [ { name = "TMM-GK-TF-RebootSchedule1" reboot_schedule_enabled = true frequency = "Weekly" frequency_factor = 1 days_in_week = [ "Sunday", ] start_time = "02:00" start_date = "2024-01-01" reboot_duration_minutes = 0 ignore_maintenance_mode = true natural_reboot_schedule = false } ]
policy_set_id = "3658867a-c55a-4a76-996a-03be1c0560a2"
} */ |
terraform apply adds the Delivery Group to the Infrastructure:
PS C:\_TERRAFORM\_CCOnAzureV2\CCOnAzureV2-DeployCCEntities> terraform apply |
Terraform has successfully added the Delivery Group in 10 seconds - compare this to the time it would take to manually create it using WebStudio.
WebStudio reflects the addition:
Example 2: Removing the Delivery Group
In this example, we will remove the just created Delivery Group from our environment to show that Terraform can decommission and completely wipe entities or whole infrastructures.
Caution:
You cannot stop the process as soon as you give consent to Terraform's application to destroy the entity/entities. Terraform will decommission whatever it has to.
We only need to uncomment or remove the snippet from the Terraform code to remove the just-created Delivery Group.
We just need to alter the Terraform code to add the new Delivery Group – currently, it is uncommented, and this needs to be removed:
#### Create the Delivery Group based on the Image Definition-based Machine Catalog /* resource "citrix_delivery_group" "CreateImgDefDG" { name = "${var.CC-Azure-DGImgDef-Name}" associated_machine_catalogs = [ { machine_catalog = citrix_machine_catalog.CreateAzureImgDefMCSCatalog.id machine_count = "${var.CC-Azure-MCImgDef-Machine_Count}" } ] desktops = [ { published_name = "${var.CC-Azure-DGImgDef-PublishedDesktopName}" description = "${var.CC-Azure-DGImgDef-Description}" restricted_access_users = { allow_list = [ "xXxXxXxXxXxXxXxXx", ] } enabled = true }
] autoscale_settings = { autoscale_enabled = true disconnect_peak_idle_session_after_seconds = 60 disconnect_off_peak_idle_session_after_seconds = 60 log_off_off_peak_disconnected_session_after_seconds = 60 log_off_peak_disconnected_session_after_seconds = 60
peak_log_off_action = "Suspend" off_peak_log_off_action = "Suspend" peak_disconnect_action = "Suspend" off_peak_disconnect_action = "Suspend"
power_time_schemes = [ { days_of_week = [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" ] name = "${var.CC-Azure-DGImgDef-AS-Name}" display_name = "${var.CC-Azure-DGImgDef-AS-Name}" peak_time_ranges = [ "09:00-17:00" ] pool_size_schedules = [ { time_range = "09:00-17:00", pool_size = 1 } ] pool_using_percentage = false }, ] } restricted_access_users = { allow_list = [ "xXxXxXxXxXx", ] } reboot_schedules = [ { name = "TMM-GK-TF-RebootSchedule1" reboot_schedule_enabled = true frequency = "Weekly" frequency_factor = 1 days_in_week = [ "Sunday", ] start_time = "02:00" start_date = "2024-01-01" reboot_duration_minutes = 0 ignore_maintenance_mode = true natural_reboot_schedule = false } ]
policy_set_id = "3658867a-c55a-4a76-996a-03be1c0560a2"
} */ |
Terraform recognizes that the Delivery Group is not part of the IaC anymore and decommissions the Delivery Group:
PS C:\_TERRAFORM\_CCOnAzureV2\CCOnAzureV2-DeployCCEntities> terraform apply |
Terraform has decommissioned the Delivery Group and its adjacent entities.
Summary
Using Terraform for daily administration tasks can significantly streamline your workflow and improve efficiency:
Automation:
Terraform automates repetitive tasks, such as provisioning and managing infrastructure. This reduces the need for manual intervention and minimizes the risk of human error.
Consistency:
By defining your IaC, Terraform ensures that your environments are consistent and reproducible. This is particularly useful for maintaining multiple environments like development, staging, and production.
Scalability:
Terraform makes it easy to scale your infrastructure up or down based on demand. You can define your desired state, and Terraform will handle the necessary changes to achieve that state.
Collaboration:
Terraform configurations can be stored in version control systems like Git, enabling team collaboration. Team members can review, comment on, and approve changes before they are applied.
Visibility:
Terraform provides a clear and auditable record of changes to your infrastructure. This makes it easier to track changes, troubleshoot issues, and ensure compliance with organizational policies.
Integration:
Terraform integrates with various tools and services, such as CI/CD pipelines, monitoring systems, and configuration management tools. This allows you to create a seamless, automated workflow for managing your infrastructure.
Cost Management:
By automating resource provisioning and de-provisioning, Terraform helps you optimize resource usage and control costs. You can easily identify and eliminate unused or underutilized resources.
Using Terraform for daily administration tasks can help you achieve greater efficiency, consistency, and control over your infrastructure.
There are no comments to display.
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now