diff --git a/DEVELOPER.md b/DEVELOPER.md
index 47bcf20..a18dd69 100644
--- a/DEVELOPER.md
+++ b/DEVELOPER.md
@@ -15,7 +15,7 @@ This documentation will guide you through the process of setting up your dev env
- [Debugging with citrix-daas-rest-go client code in Visual Studio Code](#debugging-with-citrix-daas-rest-go-client-code-in-visual-studio-code)
- [Running the tests](#running-the-tests)
- [Commonly faced errors](#commonly-faced-errors)
-
+ - [Plugin for Terraform Provider for StoreFront Developer Guide](#plugin-for-terraform-provider-for-storefront-developer-guide)
## Install Dependencies
* Install Go on your local system: https://go.dev/doc/install
* `choco install golang`
@@ -119,4 +119,8 @@ To navigate to `settings.json` file, follow the steps below:
To solve this issue, run the following command at the root of the repository:
```powershell
git config --global --add safe.directory [path to dir/repo]
-```
\ No newline at end of file
+```
+
+## Plugin for Terraform Provider for StoreFront Developer Guide
+
+The test running process is the same as [Running the tests](#running-the-tests) with additional parameter in the settings.cloud.example.json or settings.onprem.example.json `StoreFront env variable` section
\ No newline at end of file
diff --git a/README.md b/README.md
index f660694..0d65fc1 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,11 @@ Citrix has developed a custom Terraform provider for automating Citrix product d
- [Create a Hypervisor Resource Pool](#create-a-hypervisor-resource-pool)
- [Create a Machine Catalog](#create-a-machine-catalog)
- [Create a Delivery Group](#create-a-delivery-group)
+ - [Using the Plugin for Terraform Provider for other Citrix resources](#using-the-plugin-for-terraform-provider-for-other-citrix-resources)
+ - [Configure Global App Configuration (GAC) Settings](#configure-global-app-configuration-gac-settings)
+ - [Create Citrix Cloud Resource Locations](#create-citrix-cloud-resource-locations)
+ - [Managing StoreFront resources](#managing-storefront-resources)
+ - [Deployment Guides](#deployment-guides)
- [Frequently Asked Questions](#frequently-asked-questions)
- [What resource is supported for different connection types?](#what-resource-is-supported-for-different-connection-types)
- [What provisioning types are supported for machine catalog?](#what-provisioning-types-are-supported-for-machine-catalog)
@@ -123,7 +128,7 @@ Refer section [Understanding Provider Configuration](#understanding-provider-con
### Start writing Terraform for managing your Citrix DaaS site
-To find all the Citrix DaaS resources manageable via Terraform, understand all the configurable properties for each resource and how they work together, refer documentations for DaaS resources that has `daas_` as resource name prefix in [Citrix Terraform resource documentation](docs/resources). To better understand how the resource is managed via Citrix DaaS Rest API, you can refer the [Citrix DaaS Rest API documentation](https://developer.cloud.com/citrixworkspace/citrix-daas/citrix-daas-rest-apis/docs/overview).
+To find all the Citrix DaaS resources manageable via Terraform, understand all the configurable properties for each resource and how they work together, refer documentations for resources in [Citrix Terraform resource documentation](docs/resources). To better understand how the resource is managed via Citrix DaaS Rest API, you can refer the [Citrix DaaS Rest API documentation](https://developer.cloud.com/citrixworkspace/citrix-daas/citrix-daas-rest-apis/docs/overview).
### Create a Zone in Citrix DaaS as the first step
@@ -135,7 +140,7 @@ Hypervisor is needed to use your preferred public cloud provider with Citrix Daa
### Create a Hypervisor Resource Pool
-The hypervisor resource pool defines the network configuration for a hypervisor connection. Refer the [DaaS Hypervisor Resource Pool documentaion](docs/resources/hypervisor_resource_pool.md) to configure a hypervisr resource pool via terraform.
+The hypervisor resource pool defines the network configuration for a hypervisor connection. Refer the [DaaS Hypervisor Resource Pool documentaion](docs/resources/azure_hypervisor_resource_pool.md) to configure an Azure hypervisr resource pool via terraform.
### Create a Machine Catalog
@@ -144,18 +149,39 @@ A machine catalog is a collection of machines managed as a single entity. Refer
### Create a Delivery Group
A delivery group is a collection of machines selected from one or more machine catalogs. The delivery group can also specify which users can use those machines, plus the applications and desktops available to those users. Refer the [DaaS Delivery Group documentation](docs/resources/delivery_group.md) to configure a delivery group via terraform.
+## Using the Plugin for Terraform Provider for other Citrix resources
+
+### Configure Global App Configuration (GAC) Settings
+
+The Global App Configuration service provides a centralized setup for IT admins to easily configure Citrix Workspace app settings on Windows, Mac, Android, iOS, HTML5, Chrome OS platforms. Currently, configuration of GAC settings is only supported for citrix cloud customers. Please refer to [Global App Configuration settings documentation](docs/resources/gac_settings.md) to configure GAC settings via terraform.
+
+### Create Citrix Cloud Resource Locations
+
+Resource locations contain the resources (e.g. cloud connectors) required to deliver applications and desktops to users. Resource locations are only supported for Cloud customers. On-premises customers can use the zone resource directly. Please refer to [Citrix Resource Location](docs/resources/resource_location.md) documentation to configure citrix cloud resource locations via terraform.
+
+### Managing StoreFront resources
+Please refer to the [StoreFront.md](StoreFront.md) to configure StoreFront resources via terraform.
+
+## Deployment Guides
+Detailed instructions on setting up deployments on different cloud providers.
+
+- [AWS EC2](https://community.citrix.com/tech-zone/build/deployment-guides/terraform-daas-aws/)
+- [Azure](https://community.citrix.com/tech-zone/build/deployment-guides/citrix-daas-terraform-azure/)
+- [GCP](https://community.citrix.com/tech-zone/build/deployment-guides/terraform-daas-gcp/)
+
## Frequently Asked Questions
#### What resource is supported for different connection types?
-| Connection Type | Hypervisor | Resource Pool | MCS Power Managed |MCS Provisioning |
-|-----------------|------------------|------------------|---------------------|------------------|
-| AzureRM |:heavy_check_mark:|:heavy_check_mark:| :heavy_check_mark: |:heavy_check_mark:|
-| AWS EC2 |:heavy_check_mark:|:heavy_check_mark:| :heavy_check_mark: |:heavy_check_mark:|
-| GCP |:heavy_check_mark:|:heavy_check_mark:| :heavy_check_mark: |:heavy_check_mark:|
-| Vsphere |:heavy_check_mark:|:heavy_check_mark:| :heavy_check_mark: |:heavy_check_mark:|
-| XenServer |:heavy_check_mark:|:heavy_check_mark:| :heavy_check_mark: |:heavy_check_mark:|
-| Nutanix |:heavy_check_mark:|:heavy_check_mark:| :heavy_check_mark: |:heavy_check_mark:|
+| Connection Type | Hypervisor | Resource Pool | MCS Power Managed | MCS Provisioning | PVS |
+|-----------------|------------------|------------------|---------------------|-------------------|------------------------|
+| AzureRM |:heavy_check_mark:|:heavy_check_mark:| :heavy_check_mark: | :heavy_check_mark:|In Progress |
+| AWS EC2 |:heavy_check_mark:|:heavy_check_mark:| :heavy_check_mark: | :heavy_check_mark:|:heavy_multiplication_x:|
+| GCP |:heavy_check_mark:|:heavy_check_mark:| :heavy_check_mark: | :heavy_check_mark:|:heavy_multiplication_x:|
+| Vsphere |:heavy_check_mark:|:heavy_check_mark:| :heavy_check_mark: | :heavy_check_mark:|:heavy_multiplication_x:|
+| XenServer |:heavy_check_mark:|:heavy_check_mark:| :heavy_check_mark: | :heavy_check_mark:|:heavy_multiplication_x:|
+| Nutanix |:heavy_check_mark:|:heavy_check_mark:| :heavy_check_mark: | :heavy_check_mark:|:heavy_multiplication_x:|
+| SCVMM |In Progress |In Progress | In Progress | In Progress |:heavy_multiplication_x:|
#### What provisioning types are supported for machine catalog?
diff --git a/StoreFront.md b/StoreFront.md
new file mode 100644
index 0000000..88ea32d
--- /dev/null
+++ b/StoreFront.md
@@ -0,0 +1,108 @@
+# Terraform Module for Citrix StoreFront
+
+This Terraform module allows you to manage resources in Citrix StoreFront.
+
+## Table of Contents
+
+- [Terraform Module for Citrix StoreFront](#terraform-module-for-citrix-storefront)
+ - [Table of Contents](#table-of-contents)
+ - [Prerequisites](#prerequisites)
+ - [Installation](#installation)
+ - [StoreFront configuration for provider](#storefront-configuration-for-provider)
+ - [Usage](#usage)
+ - [Create a deployment](#create-a-deployment)
+ - [Create an authentication service](#create-an-authentication-service)
+ - [Create a store service](#create-a-store-service)
+ - [Create a webreceiver service](#create-a-webreceiver-service)
+
+## Prerequisites
+
+- Terraform 0.14.x
+- The machine running the provider needs to be running on Windows 10+ or Server 2016+
+- The machine running the provider needs WinRM access to the specified StoreFront server ([Microsoft docs on how to enable WinRM](https://learn.microsoft.com/en-us/troubleshoot/windows-server/remote/how-to-enable-windows-remote-shell))
+
+## Installation
+
+If running the StoreFront provider on a machine other than the machine where StoreFront is installed, please provide the Active Directory Admin credentials in either environment variables or provider configuration
+ - `SF_COMPUTER_NAME`:
+ - The name of the remote computer where the StoreFront server is running.
+ - `SF_AD_ADMAIN_USERNAME`:
+ - The Active Directory Admin username to connect to the remote PowerShell of the StoreFront Server machine.
+ - `SF_AD_ADMAIN_PASSWORD`:
+ - The Active Directory Admin password to connect to the remote PowerShell of the StoreFront server machine.
+
+
+### StoreFront configuration for provider
+
+ ```hcl
+ provider "citrix" {
+ hostname =
+ customer_id =
+ environment =
+ client_id =
+ client_secret =
+ disable_ssl_verification =
+ storefront_remote_host = {
+ computer_name = "{Name of the remote computer where the StoreFront located}"
+ ad_admin_username ="{Active Directory Admin Username}"
+ ad_admin_password ="{Active Directory Admin Password}"
+ }
+ }
+ ```
+
+
+## Usage
+Example Usage of the StoreFront Terraform Configuration
+
+### Create a deployment
+
+```hcl
+resource citrix_stf_deployment "testSTFDeployment" {
+ site_id = 1
+ host_base_url = "https://example3.storefront.com"
+}
+```
+
+### Create an authentication service
+```hcl
+resource "citrix_stf_authentication_service" "example-stf-authentication-service" {
+ site_id = "${citrix_stf_deployment.testSTFDeployment.site_id}"
+ friendly_name = "Auth"
+ virtual_path = "/Citrix/Authentication"
+}
+```
+
+### Create a store service
+```hcl
+resource "citrix_stf_store_service" "example-stf-store-service" {
+ site_id = "${citrix_stf_deployment.testSTFDeployment.site_id}"
+ virtual_path = "/Citrix/Store"
+ friendly_name = "Store"
+ authentication_service = "${citrix_stf_authentication_service.example-stf-authentication-service.virtual_path}"
+ farm_config = {
+ farm_name = "Controller"
+ farm_type = "XenDesktop"
+ servers = ["cvad.storefront.com"]
+ }
+}
+```
+
+### Create a webreceiver service
+```hcl
+resource "citrix_stf_webreceiver_service" "example-stf-webreceiver-service"{
+ site_id = "${citrix_stf_deployment.testSTFDeployment.site_id}"
+ virtual_path = "/Citrix/StoreWeb"
+ friendly_name = "Receiver2"
+ store_service = "${citrix_stf_store_service.example-stf-store-service.virtual_path}"
+ authentication_methods = [
+ "ExplicitForms",
+ ]
+ plugin_assistant = {
+ enabled = true
+ html5_single_tab_launch = true
+ upgrade_at_login = true
+ html5_enabled = "Off"
+ }
+}
+```
+
diff --git a/docs/index.md b/docs/index.md
index 8958a51..c76e92c 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -39,3 +39,13 @@ provider "citrix" {
- `disable_ssl_verification` (Boolean) Disable SSL verification against the target DDC.
Only applicable to on-premises customers. Citrix Cloud customers should omit this option. Set to true to skip SSL verification only when the target DDC does not have a valid SSL certificate issued by a trusted CA.
When set to true, please make sure that your provider config is set for a known DDC hostname.
[It is recommended to configure a valid certificate for the target DDC](https://docs.citrix.com/en-us/citrix-virtual-apps-desktops/install-configure/install-core/secure-web-studio-deployment)
Can be set via Environment Variable **CITRIX_DISABLE_SSL_VERIFICATION**.
- `environment` (String) Citrix Cloud environment of the customer. Only applicable for Citrix Cloud customers. Available options: `Production`, `Staging`, `Japan`, `JapanStaging`, `Gov`, `GovStaging`.
Can be set via Environment Variable **CITRIX_ENVIRONMENT**.
- `hostname` (String) Host name / base URL of Citrix DaaS service.
For Citrix on-premises customers (Required): Use this to specify Delivery Controller hostname.
For Citrix Cloud customers (Optional): Use this to force override the Citrix DaaS service hostname.
Can be set via Environment Variable **CITRIX_HOSTNAME**.
+- `storefront_remote_host` (Attributes) StoreFront Remote Host for Citrix DaaS service.
Only applicable for Citrix on-premises StoreFront. Use this to specify StoreFront Remote Host.
(see [below for nested schema](#nestedatt--storefront_remote_host))
+
+
+### Nested Schema for `storefront_remote_host`
+
+Required:
+
+- `ad_admin_password` (String) Active Directory Admin Password to connect to storefront server
Only applicable for Citrix on-premises customers. Use this to specify AD admin password
Can be set via Environment Variable **SF_AD_ADMAIN_PASSWORD**.
+- `ad_admin_username` (String) Active Directory Admin Username to connect to storefront server
Only applicable for Citrix on-premises customers. Use this to specify AD admin username
Can be set via Environment Variable **SF_AD_ADMAIN_USERNAME**.
+- `computer_name` (String) StoreFront server computer Name
Only applicable for Citrix on-premises customers. Use this to specify StoreFront server computer name
Can be set via Environment Variable **SF_COMPUTER_NAME**.
diff --git a/docs/resources/delivery_group.md b/docs/resources/delivery_group.md
index aaa54bf..6d51cee 100644
--- a/docs/resources/delivery_group.md
+++ b/docs/resources/delivery_group.md
@@ -225,7 +225,7 @@ Optional:
Optional:
-- `allow_list` (List of String) Users who can use this Desktop. Must be in `Domain\UserOrGroupName` or `user@domain.com` format
+- `allow_list` (List of String) Users who can use this Desktop. Must be in `DOMAIN\UserOrGroupName` or `user@domain.com` format
- `block_list` (List of String) Users who cannot use this Desktop. A block list is meaningful only when used to block users in the allow list. Must be in `Domain\UserOrGroupName` or `user@domain.com` format
@@ -274,7 +274,7 @@ Optional:
Optional:
-- `allow_list` (List of String) Users who can use this Delivery Group. Must be in `Domain\UserOrGroupName` or `user@domain.com` format
+- `allow_list` (List of String) Users who can use this Delivery Group. Must be in `DOMAIN\UserOrGroupName` or `user@domain.com` format
- `block_list` (List of String) Users who cannot use this Delivery Group. A block list is meaningful only when used to block users in the allow list. Must be in `Domain\UserOrGroupName` or `user@domain.com` format
## Import
diff --git a/docs/resources/gac_settings.md b/docs/resources/gac_settings.md
new file mode 100644
index 0000000..9f3fb83
--- /dev/null
+++ b/docs/resources/gac_settings.md
@@ -0,0 +1,262 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "citrix_gac_settings Resource - citrix"
+subcategory: ""
+description: |-
+ Manages the Global App Configuration settings for a service url.
+---
+
+# citrix_gac_settings (Resource)
+
+Manages the Global App Configuration settings for a service url.
+
+## Example Usage
+
+```terraform
+// Currently, only settings objects with value type of integer, boolean, strings and list of strings is supported.
+resource "citrix_gac_settings" "test_settings_configuration" {
+ service_url = "https://:443"
+ name = "test-settings"
+ description = "Test settings configuration"
+ app_settings = {
+ windows = [
+ {
+ user_override = false,
+ category = "ICA Client",
+ settings = [
+ {
+ name = "Allow Client Clipboard Redirection",
+ value_string = "true"
+ }
+ ]
+ },
+ {
+ user_override = false,
+ category = "Browser",
+ settings = [
+ {
+ name = "delete browsing data on exit",
+ value_list = [
+ "browsing_history",
+ "download_history"
+ ]
+ },
+ {
+ name = "relaunch notification period",
+ value_string = "3600000"
+ }
+ ]
+ }
+ ],
+ html5 = [
+ {
+ category = "Virtual Channel",
+ user_override = false,
+ settings = [
+ {
+ name = "Clipboard Operations Between VDA And Local Device",
+ value_string = "true"
+ }
+ ]
+ }
+ ],
+ ios = [
+ {
+ category = "Audio",
+ user_override = false,
+ settings = [
+ {
+ name = "audio",
+ value_string = "true"
+ }
+ ]
+ }
+ ],
+ macos = [
+ {
+ category = "ica client",
+ user_override = false,
+ settings = [
+ {
+ name = "Reconnect Apps and Desktops",
+ value_list = [
+ "startWorkspace",
+ "refreshApps"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
+```
+
+
+## Schema
+
+### Required
+
+- `app_settings` (Attributes) Defines the device platform and the associated settings. Currently, only settings objects with value type of integer, boolean, strings and list of strings is supported. (see [below for nested schema](#nestedatt--app_settings))
+- `description` (String) Description of the settings record.
+- `name` (String) Name of the settings record.
+- `service_url` (String) Citrix workspace application store url for which settings are to be configured. The value is case sensitive and requires the protocol ("https" or "http") and port number.
+
+### Optional
+
+- `use_for_app_config` (Boolean) Defines whether to use the settings for app configuration or not. Defaults to `true`.
+
+
+### Nested Schema for `app_settings`
+
+Optional:
+
+- `android` (Attributes List) Settings to be applied for users using android platform. (see [below for nested schema](#nestedatt--app_settings--android))
+- `chromeos` (Attributes List) Settings to be applied for users using chrome os platform. (see [below for nested schema](#nestedatt--app_settings--chromeos))
+- `html5` (Attributes List) Settings to be applied for users using html5. (see [below for nested schema](#nestedatt--app_settings--html5))
+- `ios` (Attributes List) Settings to be applied for users using ios platform. (see [below for nested schema](#nestedatt--app_settings--ios))
+- `macos` (Attributes List) Settings to be applied for users using mac os platform. (see [below for nested schema](#nestedatt--app_settings--macos))
+- `windows` (Attributes List) Settings to be applied for users using windows platform. (see [below for nested schema](#nestedatt--app_settings--windows))
+
+
+### Nested Schema for `app_settings.android`
+
+Required:
+
+- `category` (String) Defines the category of the setting.
+- `settings` (Attributes List) A list of name value pairs for the settings. Please refer to the following [table](https://developer-docs.citrix.com/en-us/server-integration/global-app-configuration-service/getting-started#supported-settings-and-their-values-per-platform) for the supported settings name and their values per platform. (see [below for nested schema](#nestedatt--app_settings--android--settings))
+- `user_override` (Boolean) Defines if users can modify or change the value of as obtained settings from the Global App Citrix Workspace configuration service.
+
+
+### Nested Schema for `app_settings.android.settings`
+
+Required:
+
+- `name` (String) Name of the setting.
+
+Optional:
+
+- `value_list` (List of String) List value (if any) associated with the setting.
+- `value_string` (String) String value (if any) associated with the setting.
+
+
+
+
+### Nested Schema for `app_settings.chromeos`
+
+Required:
+
+- `category` (String) Defines the category of the setting.
+- `settings` (Attributes List) A list of name value pairs for the settings. Please refer to the following [table](https://developer-docs.citrix.com/en-us/server-integration/global-app-configuration-service/getting-started#supported-settings-and-their-values-per-platform) for the supported settings name and their values per platform. (see [below for nested schema](#nestedatt--app_settings--chromeos--settings))
+- `user_override` (Boolean) Defines if users can modify or change the value of as obtained settings from the Global App Citrix Workspace configuration service.
+
+
+### Nested Schema for `app_settings.chromeos.settings`
+
+Required:
+
+- `name` (String) Name of the setting.
+
+Optional:
+
+- `value_list` (List of String) List value (if any) associated with the setting.
+- `value_string` (String) String value (if any) associated with the setting.
+
+
+
+
+### Nested Schema for `app_settings.html5`
+
+Required:
+
+- `category` (String) Defines the category of the setting.
+- `settings` (Attributes List) A list of name value pairs for the settings. Please refer to the following [table](https://developer-docs.citrix.com/en-us/server-integration/global-app-configuration-service/getting-started#supported-settings-and-their-values-per-platform) for the supported settings name and their values per platform. (see [below for nested schema](#nestedatt--app_settings--html5--settings))
+- `user_override` (Boolean) Defines if users can modify or change the value of as obtained settings from the Global App Citrix Workspace configuration service.
+
+
+### Nested Schema for `app_settings.html5.settings`
+
+Required:
+
+- `name` (String) Name of the setting.
+
+Optional:
+
+- `value_list` (List of String) List value (if any) associated with the setting.
+- `value_string` (String) String value (if any) associated with the setting.
+
+
+
+
+### Nested Schema for `app_settings.ios`
+
+Required:
+
+- `category` (String) Defines the category of the setting
+- `settings` (Attributes List) A list of name value pairs for the settings. Please refer to the following [table](https://developer-docs.citrix.com/en-us/server-integration/global-app-configuration-service/getting-started#supported-settings-and-their-values-per-platform) for the supported settings name and their values per platform. (see [below for nested schema](#nestedatt--app_settings--ios--settings))
+- `user_override` (Boolean) Defines if users can modify or change the value of as obtained settings from the Global App Citrix Workspace configuration service.
+
+
+### Nested Schema for `app_settings.ios.settings`
+
+Required:
+
+- `name` (String) Name of the setting.
+
+Optional:
+
+- `value_string` (String) String value (if any) associated with the setting.
+
+
+
+
+### Nested Schema for `app_settings.macos`
+
+Required:
+
+- `category` (String) Defines the category of the setting.
+- `settings` (Attributes List) A list of name value pairs for the settings. Please refer to the following [table](https://developer-docs.citrix.com/en-us/server-integration/global-app-configuration-service/getting-started#supported-settings-and-their-values-per-platform) for the supported settings name and their values per platform. (see [below for nested schema](#nestedatt--app_settings--macos--settings))
+- `user_override` (Boolean) Defines if users can modify or change the value of as obtained settings from the Global App Citrix Workspace configuration service.
+
+
+### Nested Schema for `app_settings.macos.settings`
+
+Required:
+
+- `name` (String) Name of the setting.
+
+Optional:
+
+- `value_list` (List of String) List value (if any) associated with the setting.
+- `value_string` (String) String value (if any) associated with the setting.
+
+
+
+
+### Nested Schema for `app_settings.windows`
+
+Required:
+
+- `category` (String) Defines the category of the setting.
+- `settings` (Attributes List) A list of name value pairs for the settings. Please refer to [table](https://developer-docs.citrix.com/en-us/server-integration/global-app-configuration-service/getting-started#supported-settings-and-their-values-per-platform) for the supported settings name and their values per platform. (see [below for nested schema](#nestedatt--app_settings--windows--settings))
+- `user_override` (Boolean) Defines if users can modify or change the value of as obtained settings from the Global App Citrix Workspace configuration service.
+
+
+### Nested Schema for `app_settings.windows.settings`
+
+Required:
+
+- `name` (String) Name of the setting.
+
+Optional:
+
+- `value_list` (List of String) List value (if any) associated with the setting.
+- `value_string` (String) String value (if any) associated with the setting.
+
+## Import
+
+Import is supported using the following syntax:
+
+```shell
+# Global App Configuration settings can be imported by specifying the service url
+terraform import citrix_gac_settings.test_gac_settings https://example.com:443
+```
diff --git a/docs/resources/machine_catalog.md b/docs/resources/machine_catalog.md
index f893874..c5e9114 100644
--- a/docs/resources/machine_catalog.md
+++ b/docs/resources/machine_catalog.md
@@ -53,10 +53,12 @@ resource "citrix_machine_catalog" "example-azure-mtsession" {
storage_cost_saving = true
}
}
- network_mapping = {
- network_device = "0"
- network = ""
- }
+ network_mapping = [
+ {
+ network_device = "0"
+ network = ""
+ }
+ ]
availability_zones = "1,2,..."
number_of_total_machines = 1
machine_account_creation_rules ={
@@ -94,10 +96,12 @@ resource "citrix_machine_catalog" "example-aws-mtsession" {
]
tenancy_type = "Shared"
}
- network_mapping = {
- network_device = "0"
- network = "10.0.128.0/20"
- }
+ network_mapping = [
+ {
+ network_device = "0"
+ network = "10.0.128.0/20"
+ }
+ ]
number_of_total_machines = 1
machine_account_creation_rules ={
naming_scheme = "aws-multi-##"
@@ -330,10 +334,12 @@ resource "citrix_machine_catalog" "example-non-domain-joined-azure-mcs" {
storage_type = "Standard_LRS"
use_managed_disks = true
service_offering = "Standard_D2_v2"
- resource_group = ""
- storage_account = ""
- container = ""
- master_image = ""
+ azure_master_image = {
+ resource_group = ""
+ storage_account = ""
+ container = ""
+ master_image = ""
+ }
writeback_cache = {
wbc_disk_storage_type = "pd-standard"
persist_wbc = true
@@ -430,7 +436,7 @@ Optional:
- `custom_properties` (Attributes List) **This is an advanced feature. Use with caution.** Custom properties to be set for the machine catalog. For properties that are already supported as a terraform configuration field, please use terraform field instead. (see [below for nested schema](#nestedatt--provisioning_scheme--custom_properties))
- `gcp_machine_config` (Attributes) Machine Configuration For GCP MCS catalog. (see [below for nested schema](#nestedatt--provisioning_scheme--gcp_machine_config))
- `machine_domain_identity` (Attributes) The domain identity for machines in the machine catalog.
Required when identity_type is set to `ActiveDirectory` (see [below for nested schema](#nestedatt--provisioning_scheme--machine_domain_identity))
-- `network_mapping` (Attributes) Specifies how the attached NICs are mapped to networks. If this parameter is omitted, provisioned VMs are created with a single NIC, which is mapped to the default network in the hypervisor resource pool. If this parameter is supplied, machines are created with the number of NICs specified in the map, and each NIC is attached to the specified network.
Required when `provisioning_scheme.identity_type` is `AzureAD`. (see [below for nested schema](#nestedatt--provisioning_scheme--network_mapping))
+- `network_mapping` (Attributes List) Specifies how the attached NICs are mapped to networks. If this parameter is omitted, provisioned VMs are created with a single NIC, which is mapped to the default network in the hypervisor resource pool. If this parameter is supplied, machines are created with the number of NICs specified in the map, and each NIC is attached to the specified network.
Required when `provisioning_scheme.identity_type` is `AzureAD`. (see [below for nested schema](#nestedatt--provisioning_scheme--network_mapping))
- `nutanix_machine_config` (Attributes) Machine Configuration For Nutanix MCS catalog. (see [below for nested schema](#nestedatt--provisioning_scheme--nutanix_machine_config))
- `vsphere_machine_config` (Attributes) Machine Configuration for vSphere MCS catalog. (see [below for nested schema](#nestedatt--provisioning_scheme--vsphere_machine_config))
- `xenserver_machine_config` (Attributes) Machine Configuration For XenServer MCS catalog. (see [below for nested schema](#nestedatt--provisioning_scheme--xenserver_machine_config))
@@ -470,7 +476,7 @@ Optional:
- `disk_encryption_set` (Attributes) The configuration for Disk Encryption Set (DES). The DES must be in the same subscription and region as your resources. If your master image is encrypted with a DES, use the same DES when creating this machine catalog. When using a DES, if you later disable the key with which the corresponding DES is associated in Azure, you can no longer power on the machines in this catalog or add machines to it. (see [below for nested schema](#nestedatt--provisioning_scheme--azure_machine_config--disk_encryption_set))
- `enroll_in_intune` (Boolean) Specify whether to enroll machines in Microsoft Intune. Use this property only when `identity_type` is set to `AzureAD`.
- `license_type` (String) Windows license type used to provision virtual machines in Azure at the base compute rate. License types include: `Windows_Client` and `Windows_Server`.
-- `machine_profile` (Attributes) The name of the virtual machine template that will be used to identify the default value for the tags, virtual machine size, boot diagnostics, host cache property of OS disk, accelerated networking and availability zone.
Required when identity_type is set to `AzureAD` (see [below for nested schema](#nestedatt--provisioning_scheme--azure_machine_config--machine_profile))
+- `machine_profile` (Attributes) The name of the virtual machine or template spec that will be used to identify the default value for the tags, virtual machine size, boot diagnostics, host cache property of OS disk, accelerated networking and availability zone.
Required when identity_type is set to `AzureAD` (see [below for nested schema](#nestedatt--provisioning_scheme--azure_machine_config--machine_profile))
- `use_azure_compute_gallery` (Attributes) Use this to place prepared image in Azure Compute Gallery. Required when `storage_type = Azure_Ephemeral_OS_Disk`. (see [below for nested schema](#nestedatt--provisioning_scheme--azure_machine_config--use_azure_compute_gallery))
- `use_managed_disks` (Boolean) Indicate whether to use Azure managed disks for the provisioned virtual machine.
- `vda_resource_group` (String) Designated resource group where the VDA VMs will be located on Azure.
@@ -516,7 +522,12 @@ Required:
Required:
-- `machine_profile_resource_group` (String) The resource group name where machine profile VM is located in.
+- `machine_profile_resource_group` (String) The name of the resource group where the machine profile VM or template spec is located.
+
+Optional:
+
+- `machine_profile_template_spec_name` (String) The name of the machine profile template spec.
+- `machine_profile_template_spec_version` (String) The version of the machine profile template spec.
- `machine_profile_vm_name` (String) The name of the machine profile virtual machine.
diff --git a/docs/resources/resource_location.md b/docs/resources/resource_location.md
new file mode 100644
index 0000000..0571c06
--- /dev/null
+++ b/docs/resources/resource_location.md
@@ -0,0 +1,44 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "citrix_resource_location Resource - citrix"
+subcategory: ""
+description: |-
+ Manages a Citrix Cloud resource location.
+---
+
+# citrix_resource_location (Resource)
+
+Manages a Citrix Cloud resource location.
+
+## Example Usage
+
+```terraform
+resource "citrix_resource_location" "example-resource-location" {
+ name = "example-resource-location"
+}
+```
+
+
+## Schema
+
+### Required
+
+- `name` (String) Name of the resource location.
+
+### Optional
+
+- `internal_only` (Boolean) Flag to determine if the resource location can only be used internally. Defaults to `false`.
+- `time_zone` (String) Timezone associated with the resource location. Please refer to the `Timezone` column in the following [table](https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/default-time-zones?view=windows-11#time-zones) for allowed values.
+
+### Read-Only
+
+- `id` (String) ID of the resource location.
+
+## Import
+
+Import is supported using the following syntax:
+
+```shell
+# Resource Location can be imported by specifying the resource location GUID
+terraform import citrix_resource_location.test_resource_location 00000000-0000-0000-0000-000000000000
+```
diff --git a/docs/resources/stf_authentication_service.md b/docs/resources/stf_authentication_service.md
new file mode 100644
index 0000000..ebb03bb
--- /dev/null
+++ b/docs/resources/stf_authentication_service.md
@@ -0,0 +1,39 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "citrix_stf_authentication_service Resource - citrix"
+subcategory: ""
+description: |-
+ Storefront Authentication Service.
+---
+
+# citrix_stf_authentication_service (Resource)
+
+Storefront Authentication Service.
+
+## Example Usage
+
+```terraform
+resource "citrix_stf_authentication_service" "example-stf-authentication-service" {
+ site_id = "1"
+ friendly_name = "Example STF Authentication Service"
+ virtual_path = "/Citrix/Authentication"
+}
+```
+
+
+## Schema
+
+### Optional
+
+- `friendly_name` (String) The friendly name the authentication service should be known as. Defaults to `Authentication Service`.
+- `site_id` (String) The IIS site to configure the authentication service for. Defaults to `1`.
+- `virtual_path` (String) The IIS virtual path to use for the authentication service. Defaults to `/Citrix/Authentication`.
+
+## Import
+
+Import is supported using the following syntax:
+
+```shell
+# StoreFront Authentication Service can be imported with the IIS Site Id and Virtual Path
+terraform import citrix_stf_deployment.example-stf-deployment 1,"/Citrix/Auth"
+```
diff --git a/docs/resources/stf_deployment.md b/docs/resources/stf_deployment.md
new file mode 100644
index 0000000..48e5211
--- /dev/null
+++ b/docs/resources/stf_deployment.md
@@ -0,0 +1,40 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "citrix_stf_deployment Resource - citrix"
+subcategory: ""
+description: |-
+ Storefront Deployment.
+---
+
+# citrix_stf_deployment (Resource)
+
+Storefront Deployment.
+
+## Example Usage
+
+```terraform
+resource "citrix_stf_deployment" "example-stf-deployment" {
+ site_id = "1"
+ host_base_url = "https://example.com"
+}
+```
+
+
+## Schema
+
+### Required
+
+- `host_base_url` (String) Url used to access the StoreFront server group.
+
+### Optional
+
+- `site_id` (String) The IIS site id of the Storefront deployment. Defaults to 1.
+
+## Import
+
+Import is supported using the following syntax:
+
+```shell
+# StoreFront Deployment can be imported with the IIS Site ID
+terraform import citrix_stf_deployment.example-stf-deployment "1"
+```
diff --git a/docs/resources/stf_store_service.md b/docs/resources/stf_store_service.md
new file mode 100644
index 0000000..b3817a9
--- /dev/null
+++ b/docs/resources/stf_store_service.md
@@ -0,0 +1,69 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "citrix_stf_store_service Resource - citrix"
+subcategory: ""
+description: |-
+ Storefront StoreService.
+---
+
+# citrix_stf_store_service (Resource)
+
+Storefront StoreService.
+
+## Example Usage
+
+```terraform
+resource "citrix_stf_storeservice" "example-stf-store-service" {
+ site_id = "1"
+ virtual_path = "/Citrix/Store"
+ friendly_name = "Store"
+ authentication_service = "${citrix_stf_authentication_service.example-stf-authentication-service.virtual_path}"
+ farm_config = {
+ farm_name = "Controller"
+ farm_type = "XenDesktop"
+ servers = ["cvad.storefront.com", "cvad.storefront2.com"]
+ }
+}
+
+// Anonymous Authentication Service
+resource "citrix_stf_store_service" "example-stf-store-service" {
+ site_id = "1"
+ virtual_path = "/Citrix/Store"
+ friedly_name = "Store"
+ anonymous = true
+}
+```
+
+
+## Schema
+
+### Required
+
+- `virtual_path` (String) The IIS VirtualPath at which the Store will be configured to be accessed by Receivers.
+
+### Optional
+
+- `anonymous` (Boolean) Whether the Store is anonymous. Anonymous Store not requiring authentication.
+- `authentication_service` (String) The StoreFront Authentication Service to use for authenticating users.
+- `farm_config` (Attributes) Farm configuration for the Store. (see [below for nested schema](#nestedatt--farm_config))
+- `friendly_name` (String) The friendly name of the Store
+- `load_balance` (Boolean) Whether the Store is load balanced.
+- `site_id` (String) The IIS site id of the Storefront storeservice. Defaults to 1.
+
+
+### Nested Schema for `farm_config`
+
+Required:
+
+- `farm_name` (String) The name of the Farm.
+- `farm_type` (String) The type of the Farm.
+- `servers` (List of String) The list of servers in the Farm.
+
+## Import
+
+Import is supported using the following syntax:
+
+```shell
+# StoreFront Store Service can be imported with the IIS Site Id and Virtual Path
+terraform import citrix_stf_store_service.example-stf-store-service 1,"/Citrix/Store"
+```
diff --git a/docs/resources/stf_webreceiver_service.md b/docs/resources/stf_webreceiver_service.md
new file mode 100644
index 0000000..c299357
--- /dev/null
+++ b/docs/resources/stf_webreceiver_service.md
@@ -0,0 +1,77 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "citrix_stf_webreceiver_service Resource - citrix"
+subcategory: ""
+description: |-
+ Storefront WebReceiver.
+---
+
+# citrix_stf_webreceiver_service (Resource)
+
+Storefront WebReceiver.
+
+## Example Usage
+
+```terraform
+resource "citrix_stf_webreceiver_service" "example-stf-webreceiver-service"{
+ site_id = "citrix_stf_deployment.testSTFDeployment.site_id"
+ virtual_path = "/Citrix/StoreWeb"
+ friendly_name = "Receiver"
+ store_service = "${citrix_stf_store_service.example-stf-store-service.virtual_path}"
+ authentication_methods = [
+ "ExplicitForms",
+ "CitrixAGBasic"
+ ]
+ plugin_assistant = {
+ enabled = true
+ html5_single_tab_launch = true
+ upgrade_at_login = true
+ html5_enabled = "Fallback"
+ }
+}
+```
+
+
+## Schema
+
+### Required
+
+- `virtual_path` (String) The IIS VirtualPath at which the WebReceiver will be configured to be accessed by Receivers.
+
+### Optional
+
+- `authentication_methods` (List of String) The authentication methods supported by the WebReceiver.
+- `friendly_name` (String) The friendly name of the WebReceiver
+- `plugin_assistant` (Attributes) Pluin Assistant configuration for the WebReceiver. (see [below for nested schema](#nestedatt--plugin_assistant))
+- `site_id` (String) The IIS site id of the Storefront webreceiver. Defaults to 1.
+- `store_service` (String) The StoreFront Store Service linked to the WebReceiver.
+
+
+### Nested Schema for `plugin_assistant`
+
+Optional:
+
+- `enabled` (Boolean) Enable the Plugin Assistant.
+- `html5_chrome_app_origins` (String) The Html5 Chrome Application Origins settings.
+- `html5_chrome_app_preferences` (String) The Html5 Chrome Application preferences.
+- `html5_enabled` (String) Method of deploying and using the Html5 Receiver.
+- `html5_platforms` (String) The supported Html5 platforms.
+- `html5_preferences` (String) Html5 Receiver preferences.
+- `html5_single_tab_launch` (Boolean) Launch Html5 Receiver in the same browser tab.
+- `macos_minimum_supported_version` (String) Minimum version of the MacOS supported.
+- `macos_path` (String) Path to the MacOS Receiver.
+- `protocol_handler_enabled` (Boolean) Enable the Receiver Protocol Handler.
+- `protocol_handler_platforms` (String) The supported Protocol Handler platforms.
+- `protocol_handler_skip_double_hop_check_when_disabled` (Boolean) Skip the Protocol Handle double hop check.
+- `show_after_login` (Boolean) Show Plugin Assistant after the user logs in.
+- `upgrade_at_login` (Boolean) Prompt to upgrade older clients.
+- `win32_path` (String) Path to the Windows Receiver.
+
+## Import
+
+Import is supported using the following syntax:
+
+```shell
+# StoreFront Webreceiver Service can be imported with the IIS Virtual Path
+terraform import citrix_stf_webreceiver_service.example-stf-webreceiver-service 1,"/Citrix/StoreWeb"
+```
diff --git a/docs/resources/storefront_server.md b/docs/resources/storefront_server.md
new file mode 100644
index 0000000..8d997b3
--- /dev/null
+++ b/docs/resources/storefront_server.md
@@ -0,0 +1,45 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "citrix_storefront_server Resource - citrix"
+subcategory: ""
+description: |-
+ Manages a StoreFront server.
+---
+
+# citrix_storefront_server (Resource)
+
+Manages a StoreFront server.
+
+## Example Usage
+
+```terraform
+resource "citrix_storefront_server" "example-storefront_server" {
+ name = "example-storefront-server"
+ description = "StoreFront server example"
+ url = "https://storefront.example.com/citrix/store"
+ enabled = true
+}
+```
+
+
+## Schema
+
+### Required
+
+- `description` (String) Description of the StoreFront server.
+- `enabled` (Boolean) Indicates if the StoreFront server is enabled.
+- `name` (String) Name of the StoreFront server.
+- `url` (String) URL for connecting to the StoreFront server.
+
+### Read-Only
+
+- `id` (String) GUID identifier of the StoreFront server.
+
+## Import
+
+Import is supported using the following syntax:
+
+```shell
+# StoreFront Server can be imported by specifying the GUID
+terraform import citrix_storefront_server.example-storefront-server f60476fd-360d-4d35-861d-da8404652b166
+```
diff --git a/examples/basic_aws_mcs_vda/machine_catalogs.tf b/examples/basic_aws_mcs_vda/machine_catalogs.tf
index e8fcf00..2b8420c 100644
--- a/examples/basic_aws_mcs_vda/machine_catalogs.tf
+++ b/examples/basic_aws_mcs_vda/machine_catalogs.tf
@@ -28,10 +28,6 @@ resource "citrix_machine_catalog" "example-aws-catalog" {
tenancy_type = "Shared"
}
number_of_total_machines = 1
- network_mapping = {
- network_device = "0"
- network = ""
- }
machine_account_creation_rules = {
naming_scheme = "ctx-aws-###"
naming_scheme_type = "Numeric"
diff --git a/examples/basic_azure_mcs_vda/machine_catalogs.tf b/examples/basic_azure_mcs_vda/machine_catalogs.tf
index dcb724b..46a6539 100644
--- a/examples/basic_azure_mcs_vda/machine_catalogs.tf
+++ b/examples/basic_azure_mcs_vda/machine_catalogs.tf
@@ -29,10 +29,6 @@ resource "citrix_machine_catalog" "example-catalog" {
use_managed_disks = true
}
number_of_total_machines = 1
- network_mapping = {
- network_device = "0"
- network = ""
- }
machine_account_creation_rules = {
naming_scheme = "ctx-pvdr-##"
naming_scheme_type = "Numeric"
diff --git a/examples/basic_gcp_mcs_vda/machine_catalogs.tf b/examples/basic_gcp_mcs_vda/machine_catalogs.tf
index 6b120d1..3638513 100644
--- a/examples/basic_gcp_mcs_vda/machine_catalogs.tf
+++ b/examples/basic_gcp_mcs_vda/machine_catalogs.tf
@@ -25,10 +25,6 @@ resource "citrix_machine_catalog" "example-catalog" {
}
availability_zones = "::,::,..."
number_of_total_machines = 1
- network_mapping = {
- network_device = "0"
- network = ""
- }
machine_account_creation_rules = {
naming_scheme = "ctx-pvdr-##"
naming_scheme_type = "Numeric"
diff --git a/go.mod b/go.mod
index c3e1ca1..9d786bb 100644
--- a/go.mod
+++ b/go.mod
@@ -5,16 +5,16 @@ go 1.21
toolchain go1.21.4
require (
- github.com/citrix/citrix-daas-rest-go v0.3.0
+ github.com/citrix/citrix-daas-rest-go v0.4.1
github.com/google/uuid v1.6.0
- github.com/hashicorp/go-azure-helpers v0.67.0
+ github.com/hashicorp/go-azure-helpers v0.69.0
github.com/hashicorp/terraform-plugin-docs v0.14.1
github.com/hashicorp/terraform-plugin-framework v1.8.0
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0
- github.com/hashicorp/terraform-plugin-go v0.22.2
+ github.com/hashicorp/terraform-plugin-go v0.23.0
github.com/hashicorp/terraform-plugin-log v0.9.0
- github.com/hashicorp/terraform-plugin-testing v1.2.0
- golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f
+ github.com/hashicorp/terraform-plugin-testing v1.8.0
+ golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
golang.org/x/mod v0.17.0
)
@@ -22,13 +22,13 @@ require (
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.0 // indirect
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
- github.com/ProtonMail/go-crypto v1.1.0-alpha.0 // indirect
+ github.com/ProtonMail/go-crypto v1.1.0-alpha.2 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/armon/go-radix v1.0.0 // indirect
github.com/bgentry/speakeasy v0.1.0 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
- github.com/fatih/color v1.16.0 // indirect
+ github.com/fatih/color v1.17.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
@@ -37,15 +37,15 @@ require (
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect
github.com/hashicorp/go-hclog v1.6.3 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
- github.com/hashicorp/go-plugin v1.6.0 // indirect
+ github.com/hashicorp/go-plugin v1.6.1 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
- github.com/hashicorp/go-version v1.6.0 // indirect
- github.com/hashicorp/hc-install v0.6.3 // indirect
+ github.com/hashicorp/go-version v1.7.0 // indirect
+ github.com/hashicorp/hc-install v0.6.4 // indirect
github.com/hashicorp/hcl/v2 v2.20.1 // indirect
github.com/hashicorp/logutils v1.0.0 // indirect
- github.com/hashicorp/terraform-exec v0.20.0 // indirect
- github.com/hashicorp/terraform-json v0.21.0 // indirect
- github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 // indirect
+ github.com/hashicorp/terraform-exec v0.21.0 // indirect
+ github.com/hashicorp/terraform-json v0.22.1 // indirect
+ github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 // indirect
github.com/hashicorp/terraform-registry-address v0.2.3 // indirect
github.com/hashicorp/terraform-svchost v0.1.1 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
@@ -68,16 +68,16 @@ require (
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/zclconf/go-cty v1.14.4 // indirect
- golang.org/x/crypto v0.22.0 // indirect
- golang.org/x/net v0.24.0 // indirect
+ golang.org/x/crypto v0.23.0 // indirect
+ golang.org/x/net v0.25.0 // indirect
golang.org/x/sync v0.7.0 // indirect
- golang.org/x/sys v0.19.0 // indirect
- golang.org/x/text v0.14.0 // indirect
- golang.org/x/tools v0.20.0 // indirect
+ golang.org/x/sys v0.20.0 // indirect
+ golang.org/x/text v0.15.0 // indirect
+ golang.org/x/tools v0.21.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be // indirect
- google.golang.org/grpc v1.63.2 // indirect
- google.golang.org/protobuf v1.33.0 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e // indirect
+ google.golang.org/grpc v1.64.0 // indirect
+ google.golang.org/protobuf v1.34.1 // indirect
)
// replace github.com/citrix/citrix-daas-rest-go => ../citrix-daas-rest-go
diff --git a/go.sum b/go.sum
index 2c2ace9..f51b990 100644
--- a/go.sum
+++ b/go.sum
@@ -10,8 +10,8 @@ github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
-github.com/ProtonMail/go-crypto v1.1.0-alpha.0 h1:nHGfwXmFvJrSR9xu8qL7BkO4DqTHXE9N5vPhgY2I+j0=
-github.com/ProtonMail/go-crypto v1.1.0-alpha.0/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
+github.com/ProtonMail/go-crypto v1.1.0-alpha.2 h1:bkyFVUP+ROOARdgCiJzNQo2V2kiB97LyUpzH9P6Hrlg=
+github.com/ProtonMail/go-crypto v1.1.0-alpha.2/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
@@ -24,8 +24,8 @@ github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQ
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8=
-github.com/citrix/citrix-daas-rest-go v0.3.0 h1:5uQCzNfkWBY7bvxrOXseuzaTXpmuqlRNfYkZvdCJrXo=
-github.com/citrix/citrix-daas-rest-go v0.3.0/go.mod h1:wObnH2H4QP/nwoKR589SzQZ5dGTu3AoVi927NN/e77s=
+github.com/citrix/citrix-daas-rest-go v0.4.1 h1:5xxSzA2VpbanH7GV6bcOZ1qx60/fkeGO4veLtFRe3Co=
+github.com/citrix/citrix-daas-rest-go v0.4.1/go.mod h1:wObnH2H4QP/nwoKR589SzQZ5dGTu3AoVi927NN/e77s=
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
@@ -37,16 +37,16 @@ github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
-github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
-github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
+github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
+github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
-github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4=
-github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY=
+github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
+github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY=
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
@@ -67,8 +67,8 @@ github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
-github.com/hashicorp/go-azure-helpers v0.67.0 h1:0RY6mY3W3Ym2I+jExLtyLx96fh6p5n9vidqisAKGUSE=
-github.com/hashicorp/go-azure-helpers v0.67.0/go.mod h1:S4Bu66vyJvHA0trqHQB0YVGsISuF7HMH9tyEsMVlx8A=
+github.com/hashicorp/go-azure-helpers v0.69.0 h1:JwUWXyDgyr6OafU4CgSvrbEP1wcMjfz4gxRQciDQkBQ=
+github.com/hashicorp/go-azure-helpers v0.69.0/go.mod h1:BmbF4JDYXK5sEmFeU5hcn8Br21uElcqLfdQxjatwQKw=
github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU=
github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
@@ -81,37 +81,37 @@ github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVH
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
-github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A=
-github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI=
+github.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI=
+github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
-github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
-github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
-github.com/hashicorp/hc-install v0.6.3 h1:yE/r1yJvWbtrJ0STwScgEnCanb0U9v7zp0Gbkmcoxqs=
-github.com/hashicorp/hc-install v0.6.3/go.mod h1:KamGdbodYzlufbWh4r9NRo8y6GLHWZP2GBtdnms1Ln0=
+github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
+github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/hc-install v0.6.4 h1:QLqlM56/+SIIGvGcfFiwMY3z5WGXT066suo/v9Km8e0=
+github.com/hashicorp/hc-install v0.6.4/go.mod h1:05LWLy8TD842OtgcfBbOT0WMoInBMUSHjmDx10zuBIA=
github.com/hashicorp/hcl/v2 v2.20.1 h1:M6hgdyz7HYt1UN9e61j+qKJBqR3orTWbI1HKBJEdxtc=
github.com/hashicorp/hcl/v2 v2.20.1/go.mod h1:TZDqQ4kNKCbh1iJp99FdPiUaVDDUPivbqxZulxDYqL4=
github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
-github.com/hashicorp/terraform-exec v0.20.0 h1:DIZnPsqzPGuUnq6cH8jWcPunBfY+C+M8JyYF3vpnuEo=
-github.com/hashicorp/terraform-exec v0.20.0/go.mod h1:ckKGkJWbsNqFKV1itgMnE0hY9IYf1HoiekpuN0eWoDw=
-github.com/hashicorp/terraform-json v0.21.0 h1:9NQxbLNqPbEMze+S6+YluEdXgJmhQykRyRNd+zTI05U=
-github.com/hashicorp/terraform-json v0.21.0/go.mod h1:qdeBs11ovMzo5puhrRibdD6d2Dq6TyE/28JiU4tIQxk=
+github.com/hashicorp/terraform-exec v0.21.0 h1:uNkLAe95ey5Uux6KJdua6+cv8asgILFVWkd/RG0D2XQ=
+github.com/hashicorp/terraform-exec v0.21.0/go.mod h1:1PPeMYou+KDUSSeRE9szMZ/oHf4fYUmB923Wzbq1ICg=
+github.com/hashicorp/terraform-json v0.22.1 h1:xft84GZR0QzjPVWs4lRUwvTcPnegqlyS7orfb5Ltvec=
+github.com/hashicorp/terraform-json v0.22.1/go.mod h1:JbWSQCLFSXFFhg42T7l9iJwdGXBYV8fmmD6o/ML4p3A=
github.com/hashicorp/terraform-plugin-docs v0.14.1 h1:MikFi59KxrP/ewrZoaowrB9he5Vu4FtvhamZFustiA4=
github.com/hashicorp/terraform-plugin-docs v0.14.1/go.mod h1:k2NW8+t113jAus6bb5tQYQgEAX/KueE/u8X2Z45V1GM=
github.com/hashicorp/terraform-plugin-framework v1.8.0 h1:P07qy8RKLcoBkCrY2RHJer5AEvJnDuXomBgou6fD8kI=
github.com/hashicorp/terraform-plugin-framework v1.8.0/go.mod h1:/CpTukO88PcL/62noU7cuyaSJ4Rsim+A/pa+3rUVufY=
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 h1:HOjBuMbOEzl7snOdOoUfE2Jgeto6JOjLVQ39Ls2nksc=
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0/go.mod h1:jfHGE/gzjxYz6XoUwi/aYiiKrJDeutQNUtGQXkaHklg=
-github.com/hashicorp/terraform-plugin-go v0.22.2 h1:5o8uveu6eZUf5J7xGPV0eY0TPXg3qpmwX9sce03Bxnc=
-github.com/hashicorp/terraform-plugin-go v0.22.2/go.mod h1:drq8Snexp9HsbFZddvyLHN6LuWHHndSQg+gV+FPkcIM=
+github.com/hashicorp/terraform-plugin-go v0.23.0 h1:AALVuU1gD1kPb48aPQUjug9Ir/125t+AAurhqphJ2Co=
+github.com/hashicorp/terraform-plugin-go v0.23.0/go.mod h1:1E3Cr9h2vMlahWMbsSEcNrOCxovCZhOOIXjFHbjc/lQ=
github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0=
github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow=
-github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 h1:qHprzXy/As0rxedphECBEQAh3R4yp6pKksKHcqZx5G8=
-github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0/go.mod h1:H+8tjs9TjV2w57QFVSMBQacf8k/E1XwLXGCARgViC6A=
-github.com/hashicorp/terraform-plugin-testing v1.2.0 h1:pASRAe6BOZFO4xSGQr9WzitXit0nrQAYDk8ziuRfn9E=
-github.com/hashicorp/terraform-plugin-testing v1.2.0/go.mod h1:+8bp3O7xUb1UtBcdknrGdVRIuTw4b62TYSIgXHqlyew=
+github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 h1:kJiWGx2kiQVo97Y5IOGR4EMcZ8DtMswHhUuFibsCQQE=
+github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0/go.mod h1:sl/UoabMc37HA6ICVMmGO+/0wofkVIRxf+BMb/dnoIg=
+github.com/hashicorp/terraform-plugin-testing v1.8.0 h1:wdYIgwDk4iO933gC4S8KbKdnMQShu6BXuZQPScmHvpk=
+github.com/hashicorp/terraform-plugin-testing v1.8.0/go.mod h1:o2kOgf18ADUaZGhtOl0YCkfIxg01MAiMATT2EtIHlZk=
github.com/hashicorp/terraform-registry-address v0.2.3 h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI=
github.com/hashicorp/terraform-registry-address v0.2.3/go.mod h1:lFHA76T8jfQteVfT7caREqguFrW3c4MFSPhZB7HHgUM=
github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ=
@@ -176,13 +176,13 @@ github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBO
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
-github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
-github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
+github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
+github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
-github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ=
-github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
+github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A=
+github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
@@ -213,10 +213,10 @@ golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
-golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
-golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
-golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY=
-golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
+golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
+golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
+golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
+golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
@@ -225,8 +225,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
-golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
-golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
+golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
+golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -246,8 +246,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
-golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
+golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
@@ -257,26 +257,26 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
-golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
+golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
+golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be h1:LG9vZxsWGOmUKieR8wPAUR3u3MpnYFQZROPIMaXh7/A=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
-google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
-google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e h1:Elxv5MwEkCI9f5SkoL6afed6NTdxaGoAo39eANBwHL8=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
+google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
+google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
-google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
+google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
diff --git a/internal/daas/admin_role/admin_role_resource.go b/internal/daas/admin_role/admin_role_resource.go
index e9abda8..06d4476 100644
--- a/internal/daas/admin_role/admin_role_resource.go
+++ b/internal/daas/admin_role/admin_role_resource.go
@@ -300,6 +300,8 @@ func readAdminRole(ctx context.Context, client *citrixdaasclient.CitrixDaasClien
}
func (r *adminRoleResource) ValidateConfig(ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
var data AdminRoleResourceModel
diags := req.Config.Get(ctx, &data)
resp.Diagnostics.Append(diags...)
diff --git a/internal/daas/admin_scope/admin_scope_data_source.go b/internal/daas/admin_scope/admin_scope_data_source.go
index 9c0cd0b..b309308 100644
--- a/internal/daas/admin_scope/admin_scope_data_source.go
+++ b/internal/daas/admin_scope/admin_scope_data_source.go
@@ -86,6 +86,8 @@ func (d *AdminScopeDataSource) Configure(ctx context.Context, req datasource.Con
}
func (d *AdminScopeDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
var data AdminScopeDataSourceModel
// Read Terraform configuration data into the model
diff --git a/internal/daas/application/application_folder_details_data_source.go b/internal/daas/application/application_folder_details_data_source.go
index 7e848f2..7a5696b 100644
--- a/internal/daas/application/application_folder_details_data_source.go
+++ b/internal/daas/application/application_folder_details_data_source.go
@@ -103,6 +103,8 @@ func (d *ApplicationDataSource) Configure(ctx context.Context, req datasource.Co
}
func (d *ApplicationDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
var data ApplicationFolderDetailsDataSourceModel
// Read Terraform configuration data into the model
diff --git a/internal/daas/delivery_group/delivery_group_resource.go b/internal/daas/delivery_group/delivery_group_resource.go
index c4274d0..5670881 100644
--- a/internal/daas/delivery_group/delivery_group_resource.go
+++ b/internal/daas/delivery_group/delivery_group_resource.go
@@ -32,7 +32,6 @@ var (
_ resource.ResourceWithImportState = &deliveryGroupResource{}
_ resource.ResourceWithValidateConfig = &deliveryGroupResource{}
_ resource.ResourceWithModifyPlan = &deliveryGroupResource{}
- _ resource.ResourceWithValidateConfig = &deliveryGroupResource{}
)
// NewDeliveryGroupResource is a helper function to simplify the provider implementation.
@@ -108,6 +107,9 @@ func (r *deliveryGroupResource) Schema(_ context.Context, _ resource.SchemaReque
"restricted_access_users": getSchemaForRestrictedAccessUsers(false),
},
},
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
},
"associated_machine_catalogs": schema.ListNestedAttribute{
Description: "Machine catalogs from which to assign machines to the newly created delivery group.",
@@ -332,6 +334,9 @@ func (r *deliveryGroupResource) Schema(_ context.Context, _ resource.SchemaReque
},
},
},
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
},
},
},
@@ -477,6 +482,9 @@ func (r *deliveryGroupResource) Schema(_ context.Context, _ resource.SchemaReque
},
},
},
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
},
"total_machines": schema.Int64Attribute{
Description: "The total number of machines in the delivery group.",
@@ -495,7 +503,7 @@ func (r *deliveryGroupResource) Schema(_ context.Context, _ resource.SchemaReque
Computed: true,
Default: stringdefault.StaticString("L7_20"),
Validators: []validator.String{
- util.GetValidatorFromEnum(citrixorchestration.AllowedFunctionalLevelEnumValues),
+ stringvalidator.OneOfCaseInsensitive(util.GetAllowedFunctionalLevelValues()...),
},
},
},
@@ -621,6 +629,11 @@ func (r *deliveryGroupResource) Create(ctx context.Context, req resource.CreateR
deliveryGroup.SetPolicySetGuid(types.StringNull().ValueString())
}
+ deliveryGroup, deliveryGroupDesktops, err = updateDeliveryGroupUserAccessDetails(ctx, r.client, &resp.Diagnostics, deliveryGroup, deliveryGroupDesktops)
+ if err != nil {
+ return
+ }
+
plan = plan.RefreshPropertyValues(deliveryGroup, deliveryGroupDesktops, deliveryGroupPowerTimeSchemes, deliveryGroupMachines, deliveryGroupRebootSchedule)
// Set state to fully populated data
@@ -675,6 +688,11 @@ func (r *deliveryGroupResource) Read(ctx context.Context, req resource.ReadReque
deliveryGroup.SetPolicySetGuid("")
}
+ deliveryGroup, deliveryGroupDesktops, err = updateDeliveryGroupUserAccessDetails(ctx, r.client, &resp.Diagnostics, deliveryGroup, deliveryGroupDesktops)
+ if err != nil {
+ return
+ }
+
state = state.RefreshPropertyValues(deliveryGroup, deliveryGroupDesktops, deliveryGroupPowerTimeSchemes, deliveryGroupMachines, deliveryGroupRebootSchedule)
// Set refreshed state
@@ -767,6 +785,11 @@ func (r *deliveryGroupResource) Update(ctx context.Context, req resource.UpdateR
updatedDeliveryGroup.SetPolicySetGuid(types.StringNull().ValueString())
}
+ updatedDeliveryGroup, deliveryGroupDesktops, err = updateDeliveryGroupUserAccessDetails(ctx, r.client, &resp.Diagnostics, updatedDeliveryGroup, deliveryGroupDesktops)
+ if err != nil {
+ return
+ }
+
plan = plan.RefreshPropertyValues(updatedDeliveryGroup, deliveryGroupDesktops, deliveryGroupPowerTimeSchemes, deliveryGroupMachines, deliveryGroupRebootSchedule)
diags = resp.State.Set(ctx, plan)
@@ -809,6 +832,8 @@ func (r *deliveryGroupResource) ImportState(ctx context.Context, req resource.Im
}
func (r *deliveryGroupResource) ValidateConfig(ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
var data DeliveryGroupResourceModel
diags := req.Config.Get(ctx, &data)
resp.Diagnostics.Append(diags...)
diff --git a/internal/daas/delivery_group/delivery_group_utils.go b/internal/daas/delivery_group/delivery_group_utils.go
index 46acee9..bb8c99d 100644
--- a/internal/daas/delivery_group/delivery_group_utils.go
+++ b/internal/daas/delivery_group/delivery_group_utils.go
@@ -7,6 +7,7 @@ import (
"fmt"
"reflect"
"regexp"
+ "slices"
"strconv"
"strings"
@@ -378,12 +379,12 @@ func getSchemaForRestrictedAccessUsers(forDeliveryGroup bool) schema.NestedAttri
Attributes: map[string]schema.Attribute{
"allow_list": schema.ListAttribute{
ElementType: types.StringType,
- Description: fmt.Sprintf("Users who can use this %s. Must be in `Domain\\UserOrGroupName` or `user@domain.com` format", resource),
+ Description: fmt.Sprintf("Users who can use this %s. Must be in `DOMAIN\\UserOrGroupName` or `user@domain.com` format", resource),
Optional: true,
Validators: []validator.List{
listvalidator.ValueStringsAre(
validator.String(
- stringvalidator.RegexMatches(regexp.MustCompile(fmt.Sprintf("%s|%s", util.SamRegex, util.UpnRegex)), "must be in `Domain\\UserOrGroupName` or `user@domain.com` format"),
+ stringvalidator.RegexMatches(regexp.MustCompile(fmt.Sprintf("%s|%s", util.SamRegex, util.UpnRegex)), "must be in `DOMAIN\\UserOrGroupName` or `user@domain.com` format"),
),
),
listvalidator.SizeAtLeast(1),
@@ -396,9 +397,10 @@ func getSchemaForRestrictedAccessUsers(forDeliveryGroup bool) schema.NestedAttri
Validators: []validator.List{
listvalidator.ValueStringsAre(
validator.String(
- stringvalidator.RegexMatches(regexp.MustCompile(util.SamRegex), "must be in `Domain\\UserOrGroupName` or `user@domain.com` format"),
+ stringvalidator.RegexMatches(regexp.MustCompile(fmt.Sprintf("%s|%s", util.SamRegex, util.UpnRegex)), "must be in `DOMAIN\\UserOrGroupName` or `user@domain.com` format"),
),
),
+ listvalidator.SizeAtLeast(1),
},
},
},
@@ -760,7 +762,7 @@ func getRequestModelForDeliveryGroupUpdate(diagnostics *diag.Diagnostics, plan D
}
func parsePowerTimeSchemesPluginToClientModel(powerTimeSchemes []DeliveryGroupPowerTimeScheme) []citrixorchestration.PowerTimeSchemeRequestModel {
- var res []citrixorchestration.PowerTimeSchemeRequestModel
+ res := []citrixorchestration.PowerTimeSchemeRequestModel{}
for _, powerTimeScheme := range powerTimeSchemes {
var powerTimeSchemeRequest citrixorchestration.PowerTimeSchemeRequestModel
@@ -828,7 +830,7 @@ func parsePowerTimeSchemesClientToPluginModel(powerTimeSchemesResponse []citrixo
}
func parseDeliveryGroupRebootScheduleToClientModel(rebootSchedules []DeliveryGroupRebootSchedule) []citrixorchestration.RebootScheduleRequestModel {
- var res []citrixorchestration.RebootScheduleRequestModel
+ res := []citrixorchestration.RebootScheduleRequestModel{}
if rebootSchedules == nil {
return res
}
@@ -1109,6 +1111,125 @@ func (r DeliveryGroupResourceModel) updatePlanWithDesktops(deliveryGroupDesktops
return r
}
+func updateDeliveryGroupUserAccessDetails(ctx context.Context, client *citrixdaasclient.CitrixDaasClient, diagnostics *diag.Diagnostics, deliveryGroup *citrixorchestration.DeliveryGroupDetailResponseModel, deliveryGroupDesktops *citrixorchestration.DesktopResponseModelCollection) (*citrixorchestration.DeliveryGroupDetailResponseModel, *citrixorchestration.DesktopResponseModelCollection, error) {
+ simpleAccessPolicy := deliveryGroup.GetSimpleAccessPolicy()
+ updatedIncludedUsers, updatedExcludedUsers, err := updateIdentityUserDetails(ctx, client, diagnostics, simpleAccessPolicy.GetIncludedUsers(), simpleAccessPolicy.GetExcludedUsers())
+ if err != nil {
+ return deliveryGroup, deliveryGroupDesktops, err
+ }
+
+ simpleAccessPolicy.SetIncludedUsers(updatedIncludedUsers)
+ simpleAccessPolicy.SetExcludedUsers(updatedExcludedUsers)
+ deliveryGroup.SetSimpleAccessPolicy(simpleAccessPolicy)
+
+ updatedDeliveryGroupDesktops := []citrixorchestration.DesktopResponseModel{}
+ for _, desktop := range deliveryGroupDesktops.GetItems() {
+ updatedIncludedUsers, updatedExcludedUsers, err := updateIdentityUserDetails(ctx, client, diagnostics, desktop.GetIncludedUsers(), desktop.GetExcludedUsers())
+ if err != nil {
+ return deliveryGroup, deliveryGroupDesktops, err
+ }
+ desktop.SetIncludedUsers(updatedIncludedUsers)
+ desktop.SetExcludedUsers(updatedExcludedUsers)
+ updatedDeliveryGroupDesktops = append(updatedDeliveryGroupDesktops, desktop)
+ }
+ deliveryGroupDesktops.SetItems(updatedDeliveryGroupDesktops)
+
+ return deliveryGroup, deliveryGroupDesktops, nil
+}
+
+func verifyIdentityUserListCompleteness(inputUserNames []string, remoteUsers []citrixorchestration.IdentityUserResponseModel) error {
+ if len(remoteUsers) < len(inputUserNames) {
+ missingUsers := []string{}
+ for _, includedUser := range inputUserNames {
+ userIndex := slices.IndexFunc(remoteUsers, func(i citrixorchestration.IdentityUserResponseModel) bool {
+ return includedUser == i.GetSamName() || includedUser == i.GetPrincipalName()
+ })
+ if userIndex == -1 {
+ missingUsers = append(missingUsers, includedUser)
+ }
+ }
+
+ return fmt.Errorf("The following users could not be found: " + strings.Join(missingUsers, ", "))
+ }
+ return nil
+}
+
+func updateIdentityUserDetails(ctx context.Context, client *citrixdaasclient.CitrixDaasClient, diagnostics *diag.Diagnostics, includedUsers []citrixorchestration.IdentityUserResponseModel, excludedUsers []citrixorchestration.IdentityUserResponseModel) ([]citrixorchestration.IdentityUserResponseModel, []citrixorchestration.IdentityUserResponseModel, error) {
+ includedUserNames := []string{}
+ for _, includedUser := range includedUsers {
+ if includedUser.GetSamName() != "" {
+ includedUserNames = append(includedUserNames, includedUser.GetSamName())
+ } else if includedUser.GetPrincipalName() != "" {
+ includedUserNames = append(includedUserNames, includedUser.GetPrincipalName())
+ }
+ }
+
+ if len(includedUserNames) > 0 {
+ getIncludedUsersRequest := client.ApiClient.IdentityAPIsDAAS.IdentityGetUsers(ctx)
+ getIncludedUsersRequest = getIncludedUsersRequest.User(includedUserNames)
+ getIncludedUsersRequest = getIncludedUsersRequest.Provider(citrixorchestration.IDENTITYPROVIDERTYPE_ALL)
+ includedUsersResponse, httpResp, err := citrixdaasclient.AddRequestData(getIncludedUsersRequest, client).Execute()
+ if err != nil {
+ diagnostics.AddError(
+ "Error fetching delivery group user details",
+ "TransactionId: "+citrixdaasclient.GetTransactionIdFromHttpResponse(httpResp)+
+ "\nError message: "+util.ReadClientError(err),
+ )
+ return nil, nil, err
+ }
+
+ err = verifyIdentityUserListCompleteness(includedUserNames, includedUsersResponse.GetItems())
+ if err != nil {
+ diagnostics.AddError(
+ "Error fetching delivery group user details",
+ "TransactionId: "+citrixdaasclient.GetTransactionIdFromHttpResponse(httpResp)+
+ "\nError message: "+err.Error(),
+ )
+ return nil, nil, err
+ }
+
+ includedUsers = includedUsersResponse.GetItems()
+ }
+
+ excludedUserNames := []string{}
+ for _, excludedUser := range excludedUsers {
+ if excludedUser.GetSamName() != "" {
+ excludedUserNames = append(excludedUserNames, excludedUser.GetSamName())
+ } else if excludedUser.GetPrincipalName() != "" {
+ excludedUserNames = append(excludedUserNames, excludedUser.GetPrincipalName())
+ }
+ }
+
+ if len(excludedUserNames) > 0 {
+ getExcludedUsersRequest := client.ApiClient.IdentityAPIsDAAS.IdentityGetUsers(ctx)
+ getExcludedUsersRequest = getExcludedUsersRequest.User(excludedUserNames)
+ getExcludedUsersRequest = getExcludedUsersRequest.Provider(citrixorchestration.IDENTITYPROVIDERTYPE_ALL)
+ excludedUsersResponse, httpResp, err := citrixdaasclient.AddRequestData(getExcludedUsersRequest, client).Execute()
+ if err != nil {
+ diagnostics.AddError(
+ "Error fetching delivery group user details",
+ "TransactionId: "+citrixdaasclient.GetTransactionIdFromHttpResponse(httpResp)+
+ "\nError message: "+util.ReadClientError(err),
+ )
+ return nil, nil, err
+ }
+
+ err = verifyIdentityUserListCompleteness(excludedUserNames, excludedUsersResponse.GetItems())
+ if err != nil {
+ diagnostics.AddError(
+ "Error fetching delivery group user details",
+ "TransactionId: "+citrixdaasclient.GetTransactionIdFromHttpResponse(httpResp)+
+ "\nError message: "+err.Error(),
+ )
+ return nil, nil, err
+ }
+
+ excludedUsers = excludedUsersResponse.GetItems()
+ }
+
+ return includedUsers, excludedUsers, nil
+}
+
func (r DeliveryGroupResourceModel) updatePlanWithRestrictedAccessUsers(deliveryGroup *citrixorchestration.DeliveryGroupDetailResponseModel) DeliveryGroupResourceModel {
simpleAccessPolicy := deliveryGroup.GetSimpleAccessPolicy()
diff --git a/internal/daas/gac_settings/gac_settings_resource.go b/internal/daas/gac_settings/gac_settings_resource.go
new file mode 100644
index 0000000..db0026d
--- /dev/null
+++ b/internal/daas/gac_settings/gac_settings_resource.go
@@ -0,0 +1,771 @@
+// Copyright © 2023. Citrix Systems, Inc.
+
+package gac_settings
+
+import (
+ "context"
+ b64 "encoding/base64"
+
+ citrixdaasclient "github.com/citrix/citrix-daas-rest-go/client"
+ globalappconfiguration "github.com/citrix/citrix-daas-rest-go/globalappconfiguration"
+ "github.com/citrix/terraform-provider-citrix/internal/util"
+
+ "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
+ "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/resource"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/schema/validator"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+)
+
+// Ensure the implementation satisfies the expected interfaces.
+var (
+ _ resource.Resource = &gacSettingsResource{}
+ _ resource.ResourceWithConfigure = &gacSettingsResource{}
+ _ resource.ResourceWithImportState = &gacSettingsResource{}
+)
+
+// NewAdminUserResource is a helper function to simplify the provider implementation.
+func NewAGacSettingsResource() resource.Resource {
+ return &gacSettingsResource{}
+}
+
+// adminUserResource is the resource implementation.
+type gacSettingsResource struct {
+ client *citrixdaasclient.CitrixDaasClient
+}
+
+// Metadata returns the resource type name.
+func (r *gacSettingsResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_gac_settings"
+}
+
+// Schema defines the schema for the resource.
+func (r *gacSettingsResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ Description: "Manages the Global App Configuration settings for a service url.",
+
+ Attributes: map[string]schema.Attribute{
+ "service_url": schema.StringAttribute{
+ Description: "Citrix workspace application store url for which settings are to be configured. The value is case sensitive and requires the protocol (\"https\" or \"http\") and port number.",
+ Required: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "name": schema.StringAttribute{
+ Description: "Name of the settings record.",
+ Required: true,
+ },
+ "description": schema.StringAttribute{
+ Description: "Description of the settings record.",
+ Required: true, //Check if this can be made into Optional
+ },
+ "use_for_app_config": schema.BoolAttribute{
+ Description: "Defines whether to use the settings for app configuration or not. Defaults to `true`.",
+ Optional: true,
+ Computed: true,
+ Default: booldefault.StaticBool(true),
+ },
+ "app_settings": schema.SingleNestedAttribute{
+ Description: "Defines the device platform and the associated settings. Currently, only settings objects with value type of integer, boolean, strings and list of strings is supported.",
+ Required: true,
+ Attributes: map[string]schema.Attribute{
+ "windows": schema.ListNestedAttribute{
+ Description: "Settings to be applied for users using windows platform.",
+ Optional: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "category": schema.StringAttribute{
+ Description: "Defines the category of the setting.",
+ Required: true,
+ },
+ "user_override": schema.BoolAttribute{
+ Description: "Defines if users can modify or change the value of as obtained settings from the Global App Citrix Workspace configuration service.",
+ Required: true,
+ },
+ "settings": schema.ListNestedAttribute{
+ Description: "A list of name value pairs for the settings. Please refer to [table](https://developer-docs.citrix.com/en-us/server-integration/global-app-configuration-service/getting-started#supported-settings-and-their-values-per-platform) for the supported settings name and their values per platform.",
+ Required: true,
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "name": schema.StringAttribute{
+ Description: "Name of the setting.",
+ Required: true,
+ },
+ "value_string": schema.StringAttribute{
+ Description: "String value (if any) associated with the setting.",
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.ExactlyOneOf(path.MatchRelative().AtParent().AtName("value_string"), path.MatchRelative().AtParent().AtName("value_list")),
+ stringvalidator.LengthAtLeast(1),
+ },
+ },
+ "value_list": schema.ListAttribute{
+ ElementType: types.StringType,
+ Description: "List value (if any) associated with the setting.",
+ Optional: true,
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
+ },
+ "ios": schema.ListNestedAttribute{
+ Description: "Settings to be applied for users using ios platform.",
+ Optional: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "category": schema.StringAttribute{
+ Description: "Defines the category of the setting",
+ Required: true,
+ },
+ "user_override": schema.BoolAttribute{
+ Description: "Defines if users can modify or change the value of as obtained settings from the Global App Citrix Workspace configuration service.",
+ Required: true,
+ },
+ "settings": schema.ListNestedAttribute{
+ Description: "A list of name value pairs for the settings. Please refer to the following [table](https://developer-docs.citrix.com/en-us/server-integration/global-app-configuration-service/getting-started#supported-settings-and-their-values-per-platform) for the supported settings name and their values per platform.",
+ Required: true,
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "name": schema.StringAttribute{
+ Description: "Name of the setting.",
+ Required: true,
+ },
+ "value_string": schema.StringAttribute{
+ Description: "String value (if any) associated with the setting.",
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.LengthAtLeast(1),
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
+ },
+ "android": schema.ListNestedAttribute{
+ Description: "Settings to be applied for users using android platform.",
+ Optional: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "category": schema.StringAttribute{
+ Description: "Defines the category of the setting.",
+ Required: true,
+ },
+ "user_override": schema.BoolAttribute{
+ Description: "Defines if users can modify or change the value of as obtained settings from the Global App Citrix Workspace configuration service.",
+ Required: true,
+ },
+ "settings": schema.ListNestedAttribute{
+ Description: "A list of name value pairs for the settings. Please refer to the following [table](https://developer-docs.citrix.com/en-us/server-integration/global-app-configuration-service/getting-started#supported-settings-and-their-values-per-platform) for the supported settings name and their values per platform.",
+ Required: true,
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "name": schema.StringAttribute{
+ Description: "Name of the setting.",
+ Required: true,
+ },
+ "value_string": schema.StringAttribute{
+ Description: "String value (if any) associated with the setting.",
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.ExactlyOneOf(path.MatchRelative().AtParent().AtName("value_string"), path.MatchRelative().AtParent().AtName("value_list")),
+ stringvalidator.LengthAtLeast(1),
+ },
+ },
+ "value_list": schema.ListAttribute{
+ ElementType: types.StringType,
+ Description: "List value (if any) associated with the setting.",
+ Optional: true,
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
+ },
+ "html5": schema.ListNestedAttribute{
+ Description: "Settings to be applied for users using html5.",
+ Optional: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "category": schema.StringAttribute{
+ Description: "Defines the category of the setting.",
+ Required: true,
+ },
+ "user_override": schema.BoolAttribute{
+ Description: "Defines if users can modify or change the value of as obtained settings from the Global App Citrix Workspace configuration service.",
+ Required: true,
+ },
+ "settings": schema.ListNestedAttribute{
+ Description: "A list of name value pairs for the settings. Please refer to the following [table](https://developer-docs.citrix.com/en-us/server-integration/global-app-configuration-service/getting-started#supported-settings-and-their-values-per-platform) for the supported settings name and their values per platform.",
+ Required: true,
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "name": schema.StringAttribute{
+ Description: "Name of the setting.",
+ Required: true,
+ },
+ "value_string": schema.StringAttribute{
+ Description: "String value (if any) associated with the setting.",
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.ExactlyOneOf(path.MatchRelative().AtParent().AtName("value_string"), path.MatchRelative().AtParent().AtName("value_list")),
+ stringvalidator.LengthAtLeast(1),
+ },
+ },
+ "value_list": schema.ListAttribute{
+ ElementType: types.StringType,
+ Description: "List value (if any) associated with the setting.",
+ Optional: true,
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
+ },
+ "chromeos": schema.ListNestedAttribute{
+ Description: "Settings to be applied for users using chrome os platform.",
+ Optional: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "category": schema.StringAttribute{
+ Description: "Defines the category of the setting.",
+ Required: true,
+ },
+ "user_override": schema.BoolAttribute{
+ Description: "Defines if users can modify or change the value of as obtained settings from the Global App Citrix Workspace configuration service.",
+ Required: true,
+ },
+ "settings": schema.ListNestedAttribute{
+ Description: "A list of name value pairs for the settings. Please refer to the following [table](https://developer-docs.citrix.com/en-us/server-integration/global-app-configuration-service/getting-started#supported-settings-and-their-values-per-platform) for the supported settings name and their values per platform.",
+ Required: true,
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "name": schema.StringAttribute{
+ Description: "Name of the setting.",
+ Required: true,
+ },
+ "value_string": schema.StringAttribute{
+ Description: "String value (if any) associated with the setting.",
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.ExactlyOneOf(path.MatchRelative().AtParent().AtName("value_string"), path.MatchRelative().AtParent().AtName("value_list")),
+ stringvalidator.LengthAtLeast(1),
+ },
+ },
+ "value_list": schema.ListAttribute{
+ ElementType: types.StringType,
+ Description: "List value (if any) associated with the setting.",
+ Optional: true,
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
+ },
+ "macos": schema.ListNestedAttribute{
+ Description: "Settings to be applied for users using mac os platform.",
+ Optional: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "category": schema.StringAttribute{
+ Description: "Defines the category of the setting.",
+ Required: true,
+ },
+ "user_override": schema.BoolAttribute{
+ Description: "Defines if users can modify or change the value of as obtained settings from the Global App Citrix Workspace configuration service.",
+ Required: true,
+ },
+ "settings": schema.ListNestedAttribute{
+ Description: "A list of name value pairs for the settings. Please refer to the following [table](https://developer-docs.citrix.com/en-us/server-integration/global-app-configuration-service/getting-started#supported-settings-and-their-values-per-platform) for the supported settings name and their values per platform.",
+ Required: true,
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "name": schema.StringAttribute{
+ Description: "Name of the setting.",
+ Required: true,
+ },
+ "value_string": schema.StringAttribute{
+ Description: "String value (if any) associated with the setting.",
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.ExactlyOneOf(path.MatchRelative().AtParent().AtName("value_string"), path.MatchRelative().AtParent().AtName("value_list")),
+ stringvalidator.LengthAtLeast(1),
+ },
+ },
+ "value_list": schema.ListAttribute{
+ ElementType: types.StringType,
+ Description: "List value (if any) associated with the setting.",
+ Optional: true,
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ Validators: []validator.List{
+ listvalidator.SizeAtLeast(1),
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
+// Configure adds the provider configured client to the resource.
+func (r *gacSettingsResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ r.client = req.ProviderData.(*citrixdaasclient.CitrixDaasClient)
+}
+
+// Create creates the resource and sets the initial Terraform state.
+func (r *gacSettingsResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ var plan GACSettingsResourceModel
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ var serviceUrlModel globalappconfiguration.ServiceURL
+ serviceUrlModel.SetUrl(plan.ServiceUrl.ValueString())
+
+ var appSettings globalappconfiguration.AppSettings
+ appSettings.SetAndroid(GetAppSettingsForAndroid(plan.AppSettings.Android))
+ appSettings.SetChromeos(GetAppSettingsForChromeos(plan.AppSettings.Chromeos))
+ appSettings.SetHtml5(GetAppSettingsForHtml5(plan.AppSettings.Html5))
+ appSettings.SetIos(GetAppSettingsForIos(plan.AppSettings.Ios))
+ appSettings.SetMacos(GetAppSettingsForMacos(plan.AppSettings.Macos))
+ appSettings.SetWindows(GetAppSettingsForWindows(plan.AppSettings.Windows))
+
+ var settings globalappconfiguration.Settings
+ settings.SetName(plan.Name.ValueString())
+ settings.SetDescription(plan.Description.ValueString())
+ settings.SetUseForAppConfig(plan.UseForAppConfig.ValueBool())
+ settings.SetAppSettings(appSettings)
+
+ var body globalappconfiguration.SettingsRecordModel
+
+ body.SetServiceURL(serviceUrlModel)
+ body.SetSettings(settings)
+
+ // Call the API
+ createSettingsRequest := r.client.GacClient.SettingsControllerDAAS.PostSettingsApiUsingPOST(ctx, util.GacAppName)
+ createSettingsRequest = createSettingsRequest.SettingsRecord(body)
+ _, httpResp, err := citrixdaasclient.AddRequestData(createSettingsRequest, r.client).Execute()
+
+ //In case of error, add it to diagnostics and return
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error creating Settings configuration for ServiceUrl: "+plan.ServiceUrl.ValueString(),
+ "TransactionId: "+citrixdaasclient.GetTransactionIdFromHttpResponse(httpResp)+
+ "\nError message: "+util.ReadClientError(err),
+ )
+ return
+ }
+
+ //Try to get the new settings configuration from remote
+ settingsConfiguration, err := getSettingsConfiguration(ctx, r.client, &resp.Diagnostics, plan.ServiceUrl.ValueString())
+ if err != nil {
+ return
+ }
+
+ //Set the new state
+ // Map response body to schema and populate computed attribute values
+ plan = plan.RefreshPropertyValues(settingsConfiguration.GetItems()[0], &resp.Diagnostics)
+
+ // Set state to fully populated data
+ diags = resp.State.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Read refreshes the Terraform state with the latest data.
+func (r *gacSettingsResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ var state GACSettingsResourceModel
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Try to get Service Url settings from remote
+ settingsConfiguration, err := readSettingsConfiguration(ctx, r.client, resp, state.ServiceUrl.ValueString())
+ if err != nil {
+ return
+ }
+
+ state = state.RefreshPropertyValues(settingsConfiguration.GetItems()[0], &resp.Diagnostics)
+
+ // Set refreshed state
+ diags = resp.State.Set(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Update updates the resource and sets the updated Terraform state on success.
+func (r *gacSettingsResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ var plan GACSettingsResourceModel
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ var serviceUrlModel globalappconfiguration.ServiceURL
+ serviceUrlModel.SetUrl(plan.ServiceUrl.ValueString())
+
+ var appSettings globalappconfiguration.AppSettings
+ appSettings.SetAndroid(GetAppSettingsForAndroid(plan.AppSettings.Android))
+ appSettings.SetChromeos(GetAppSettingsForChromeos(plan.AppSettings.Chromeos))
+ appSettings.SetHtml5(GetAppSettingsForHtml5(plan.AppSettings.Html5))
+ appSettings.SetIos(GetAppSettingsForIos(plan.AppSettings.Ios))
+ appSettings.SetMacos(GetAppSettingsForMacos(plan.AppSettings.Macos))
+ appSettings.SetWindows(GetAppSettingsForWindows(plan.AppSettings.Windows))
+
+ var settings globalappconfiguration.Settings
+ settings.SetName(plan.Name.ValueString())
+ settings.SetDescription(plan.Description.ValueString())
+ settings.SetUseForAppConfig(plan.UseForAppConfig.ValueBool())
+ settings.SetAppSettings(appSettings)
+
+ var body globalappconfiguration.SettingsRecordModel
+
+ body.SetServiceURL(serviceUrlModel)
+ body.SetSettings(settings)
+
+ // Call the API
+ updateSettingsRequest := r.client.GacClient.SettingsControllerDAAS.PutSettingsApiUsingPUT(ctx, util.GacAppName, b64.StdEncoding.EncodeToString([]byte(plan.ServiceUrl.ValueString())))
+ updateSettingsRequest = updateSettingsRequest.SettingsRecord(body)
+ httpResp, err := citrixdaasclient.AddRequestData(updateSettingsRequest, r.client).Execute()
+
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error updating settings configuration for service url: "+plan.ServiceUrl.ValueString(),
+ "TransactionId: "+citrixdaasclient.GetTransactionIdFromHttpResponse(httpResp)+
+ "\nError message: "+util.ReadClientError(err),
+ )
+ }
+
+ // Try to get Service Url settings from remote
+ updatedSettingsConfiguration, err := getSettingsConfiguration(ctx, r.client, &resp.Diagnostics, plan.ServiceUrl.ValueString())
+ if err != nil {
+ return
+ }
+
+ plan = plan.RefreshPropertyValues(updatedSettingsConfiguration.GetItems()[0], &resp.Diagnostics)
+
+ // Set state to fully populated data
+ diags = resp.State.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Delete deletes the resource and removes the Terraform state on success.
+func (r *gacSettingsResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Retrieve values from state
+ var state GACSettingsResourceModel
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ //Delete settings configuration for the service url
+ encodedServiceUrl := b64.StdEncoding.EncodeToString([]byte(state.ServiceUrl.ValueString()))
+ deleteSettingsRequest := r.client.GacClient.SettingsControllerDAAS.DeleteSettingsApiUsingDELETE(ctx, util.GacAppName, encodedServiceUrl)
+ httpResp, err := citrixdaasclient.AddRequestData(deleteSettingsRequest, r.client).Execute()
+
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error deleting settings configuration for service url: "+state.ServiceUrl.ValueString(),
+ "TransactionId: "+citrixdaasclient.GetTransactionIdFromHttpResponse(httpResp)+
+ "\nError message: "+util.ReadClientError(err),
+ )
+ return
+ }
+
+}
+
+func (r *gacSettingsResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ // Retrieve import ID and save to id attribute
+ resource.ImportStatePassthroughID(ctx, path.Root("service_url"), req, resp)
+}
+
+func getSettingsConfiguration(ctx context.Context, client *citrixdaasclient.CitrixDaasClient, diagnostics *diag.Diagnostics, serviceUrl string) (*globalappconfiguration.GetAllSettingResponse, error) {
+ encodedServiceUrl := b64.StdEncoding.EncodeToString([]byte(serviceUrl))
+ getSettingsRequest := client.GacClient.SettingsControllerDAAS.GetSettingsApiUsingGET(ctx, util.GacAppName, encodedServiceUrl)
+ getSettingsResponse, httpResp, err := citrixdaasclient.ExecuteWithRetry[*globalappconfiguration.GetAllSettingResponse](getSettingsRequest, client)
+ if err != nil {
+ diagnostics.AddError(
+ "Error fetching settings configuration for service url: "+serviceUrl,
+ "TransactionId: "+citrixdaasclient.GetTransactionIdFromHttpResponse(httpResp)+
+ "\nError message: "+util.ReadClientError(err),
+ )
+ }
+
+ return getSettingsResponse, nil
+}
+
+func readSettingsConfiguration(ctx context.Context, client *citrixdaasclient.CitrixDaasClient, resp *resource.ReadResponse, serviceUrl string) (*globalappconfiguration.GetAllSettingResponse, error) {
+ encodedServiceUrl := b64.StdEncoding.EncodeToString([]byte(serviceUrl))
+ getSettingsRequest := client.GacClient.SettingsControllerDAAS.GetSettingsApiUsingGET(ctx, util.GacAppName, encodedServiceUrl)
+ getSettingsResponse, _, err := util.ReadResource[*globalappconfiguration.GetAllSettingResponse](getSettingsRequest, ctx, client, resp, "ServiceUrl Settings Configuration", serviceUrl)
+ return getSettingsResponse, err
+}
+
+func GetAppSettingsForWindows(windows []Windows) []globalappconfiguration.PlatformSettings {
+ var platformSettings []globalappconfiguration.PlatformSettings
+ for _, windowsInstance := range windows {
+ var platformSetting globalappconfiguration.PlatformSettings
+ platformSetting.SetCategory(windowsInstance.Category.ValueString())
+ platformSetting.SetUserOverride(windowsInstance.UserOverride.ValueBool())
+ platformSetting.SetAssignmentPriority(util.AssignmentPriority)
+ platformSetting.SetAssignedTo(util.PlatformSettingsAssignedTo)
+ platformSetting.SetSettings(CreateCategorySettingsForWindows(windowsInstance.Settings))
+ platformSettings = append(platformSettings, platformSetting)
+ }
+ return platformSettings
+}
+
+func GetAppSettingsForIos(ios []Ios) []globalappconfiguration.PlatformSettings {
+ var platformSettings []globalappconfiguration.PlatformSettings
+ for _, iosInstance := range ios {
+ var platformSetting globalappconfiguration.PlatformSettings
+ platformSetting.SetCategory(iosInstance.Category.ValueString())
+ platformSetting.SetUserOverride(iosInstance.UserOverride.ValueBool())
+ platformSetting.SetAssignmentPriority(util.AssignmentPriority)
+ platformSetting.SetAssignedTo(util.PlatformSettingsAssignedTo)
+ platformSetting.SetSettings(CreateCategorySettingsForIos(iosInstance.Settings))
+ platformSettings = append(platformSettings, platformSetting)
+ }
+ return platformSettings
+}
+
+func GetAppSettingsForAndroid(android []Android) []globalappconfiguration.PlatformSettings {
+ var platformSettings []globalappconfiguration.PlatformSettings
+ for _, androidInstance := range android {
+ var platformSetting globalappconfiguration.PlatformSettings
+ platformSetting.SetCategory(androidInstance.Category.ValueString())
+ platformSetting.SetUserOverride(androidInstance.UserOverride.ValueBool())
+ platformSetting.SetAssignmentPriority(util.AssignmentPriority)
+ platformSetting.SetAssignedTo(util.PlatformSettingsAssignedTo)
+ platformSetting.SetSettings(CreateCategorySettingsForAndroid(androidInstance.Settings))
+ platformSettings = append(platformSettings, platformSetting)
+ }
+ return platformSettings
+}
+
+func GetAppSettingsForChromeos(chromeos []Chromeos) []globalappconfiguration.PlatformSettings {
+ var platformSettings []globalappconfiguration.PlatformSettings
+ for _, chromeosInstance := range chromeos {
+ var platformSetting globalappconfiguration.PlatformSettings
+ platformSetting.SetCategory(chromeosInstance.Category.ValueString())
+ platformSetting.SetUserOverride(chromeosInstance.UserOverride.ValueBool())
+ platformSetting.SetAssignmentPriority(util.AssignmentPriority)
+ platformSetting.SetAssignedTo(util.PlatformSettingsAssignedTo)
+ platformSetting.SetSettings(CreateCategorySettingsForChromeos(chromeosInstance.Settings))
+ platformSettings = append(platformSettings, platformSetting)
+ }
+ return platformSettings
+}
+
+func GetAppSettingsForHtml5(html5 []Html5) []globalappconfiguration.PlatformSettings {
+ var platformSettings []globalappconfiguration.PlatformSettings
+ for _, html5Instance := range html5 {
+ var platformSetting globalappconfiguration.PlatformSettings
+ platformSetting.SetCategory(html5Instance.Category.ValueString())
+ platformSetting.SetUserOverride(html5Instance.UserOverride.ValueBool())
+ platformSetting.SetAssignmentPriority(util.AssignmentPriority)
+ platformSetting.SetAssignedTo(util.PlatformSettingsAssignedTo)
+ platformSetting.SetSettings(CreateCategorySettingsForHtml5(html5Instance.Settings))
+ platformSettings = append(platformSettings, platformSetting)
+ }
+ return platformSettings
+}
+
+func GetAppSettingsForMacos(macos []Macos) []globalappconfiguration.PlatformSettings {
+ var platformSettings []globalappconfiguration.PlatformSettings
+ for _, macosInstance := range macos {
+ var platformSetting globalappconfiguration.PlatformSettings
+ platformSetting.SetCategory(macosInstance.Category.ValueString())
+ platformSetting.SetUserOverride(macosInstance.UserOverride.ValueBool())
+ platformSetting.SetAssignmentPriority(util.AssignmentPriority)
+ platformSetting.SetAssignedTo(util.PlatformSettingsAssignedTo)
+ platformSetting.SetSettings(CreateCategorySettingsForMacos(macosInstance.Settings))
+ platformSettings = append(platformSettings, platformSetting)
+ }
+ return platformSettings
+}
+
+func CreateCategorySettingsForWindows(windowsSettings []WindowsSettings) []globalappconfiguration.CategorySettings {
+ var categorySettings []globalappconfiguration.CategorySettings
+ for _, windowsSetting := range windowsSettings {
+ var categorySetting globalappconfiguration.CategorySettings
+
+ categorySetting.SetName(windowsSetting.Name.ValueString())
+ if !windowsSetting.ValueString.IsNull() {
+ categorySetting.SetValue(windowsSetting.ValueString.ValueString())
+ } else if len(windowsSetting.ValueList) > 0 {
+ categorySetting.SetValue(util.ConvertBaseStringArrayToPrimitiveStringArray(windowsSetting.ValueList))
+ }
+ categorySettings = append(categorySettings, categorySetting)
+ }
+ return categorySettings
+}
+
+func CreateCategorySettingsForIos(iosSettings []IosSettings) []globalappconfiguration.CategorySettings {
+ var categorySettings []globalappconfiguration.CategorySettings
+ for _, iosSetting := range iosSettings {
+ var categorySetting globalappconfiguration.CategorySettings
+
+ categorySetting.SetName(iosSetting.Name.ValueString())
+ if !iosSetting.ValueString.IsNull() {
+ categorySetting.SetValue(iosSetting.ValueString.ValueString())
+ }
+ categorySettings = append(categorySettings, categorySetting)
+ }
+ return categorySettings
+}
+
+func CreateCategorySettingsForAndroid(androidSettings []AndroidSettings) []globalappconfiguration.CategorySettings {
+ var categorySettings []globalappconfiguration.CategorySettings
+ for _, androidSetting := range androidSettings {
+ var categorySetting globalappconfiguration.CategorySettings
+
+ categorySetting.SetName(androidSetting.Name.ValueString())
+ if !androidSetting.ValueString.IsNull() {
+ categorySetting.SetValue(androidSetting.ValueString.ValueString())
+ } else if len(androidSetting.ValueList) > 0 {
+ categorySetting.SetValue(util.ConvertBaseStringArrayToPrimitiveStringArray(androidSetting.ValueList))
+ }
+ categorySettings = append(categorySettings, categorySetting)
+ }
+ return categorySettings
+}
+
+func CreateCategorySettingsForHtml5(html5Settings []Html5Settings) []globalappconfiguration.CategorySettings {
+ var categorySettings []globalappconfiguration.CategorySettings
+ for _, html5Setting := range html5Settings {
+ var categorySetting globalappconfiguration.CategorySettings
+
+ categorySetting.SetName(html5Setting.Name.ValueString())
+ if !html5Setting.ValueString.IsNull() {
+ categorySetting.SetValue(html5Setting.ValueString.ValueString())
+ } else if len(html5Setting.ValueList) > 0 {
+ categorySetting.SetValue(util.ConvertBaseStringArrayToPrimitiveStringArray(html5Setting.ValueList))
+ }
+ categorySettings = append(categorySettings, categorySetting)
+ }
+ return categorySettings
+}
+
+func CreateCategorySettingsForChromeos(chromeosSettings []ChromeosSettings) []globalappconfiguration.CategorySettings {
+ var categorySettings []globalappconfiguration.CategorySettings
+ for _, chromeosSetting := range chromeosSettings {
+ var categorySetting globalappconfiguration.CategorySettings
+
+ categorySetting.SetName(chromeosSetting.Name.ValueString())
+ if !chromeosSetting.ValueString.IsNull() {
+ categorySetting.SetValue(chromeosSetting.ValueString.ValueString())
+ } else if len(chromeosSetting.ValueList) > 0 {
+ categorySetting.SetValue(util.ConvertBaseStringArrayToPrimitiveStringArray(chromeosSetting.ValueList))
+ }
+ categorySettings = append(categorySettings, categorySetting)
+ }
+ return categorySettings
+}
+
+func CreateCategorySettingsForMacos(macosSettings []MacosSettings) []globalappconfiguration.CategorySettings {
+ var categorySettings []globalappconfiguration.CategorySettings
+ for _, macosSetting := range macosSettings {
+ var categorySetting globalappconfiguration.CategorySettings
+
+ categorySetting.SetName(macosSetting.Name.ValueString())
+ if !macosSetting.ValueString.IsNull() {
+ categorySetting.SetValue(macosSetting.ValueString.ValueString())
+ } else if len(macosSetting.ValueList) > 0 {
+ categorySetting.SetValue(util.ConvertBaseStringArrayToPrimitiveStringArray(macosSetting.ValueList))
+ }
+ categorySettings = append(categorySettings, categorySetting)
+ }
+ return categorySettings
+}
diff --git a/internal/daas/gac_settings/gac_settings_resource_model.go b/internal/daas/gac_settings/gac_settings_resource_model.go
new file mode 100644
index 0000000..07b78fa
--- /dev/null
+++ b/internal/daas/gac_settings/gac_settings_resource_model.go
@@ -0,0 +1,1099 @@
+// Copyright © 2023. Citrix Systems, Inc.
+
+package gac_settings
+
+import (
+ "fmt"
+ "reflect"
+
+ globalappconfiguration "github.com/citrix/citrix-daas-rest-go/globalappconfiguration"
+ "github.com/citrix/terraform-provider-citrix/internal/util"
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+)
+
+type GACSettingsResourceModel struct {
+ ServiceUrl types.String `tfsdk:"service_url"`
+ Name types.String `tfsdk:"name"`
+ Description types.String `tfsdk:"description"`
+ UseForAppConfig types.Bool `tfsdk:"use_for_app_config"`
+ AppSettings *AppSettings `tfsdk:"app_settings"`
+}
+
+type AppSettings struct {
+ Windows []Windows `tfsdk:"windows"`
+ Ios []Ios `tfsdk:"ios"`
+ Android []Android `tfsdk:"android"`
+ Chromeos []Chromeos `tfsdk:"chromeos"`
+ Html5 []Html5 `tfsdk:"html5"`
+ Macos []Macos `tfsdk:"macos"`
+}
+
+type Windows struct {
+ Category types.String `tfsdk:"category"`
+ UserOverride types.Bool `tfsdk:"user_override"`
+ Settings []WindowsSettings `tfsdk:"settings"`
+}
+
+type Ios struct {
+ Category types.String `tfsdk:"category"`
+ UserOverride types.Bool `tfsdk:"user_override"`
+ Settings []IosSettings `tfsdk:"settings"`
+}
+
+type Android struct {
+ Category types.String `tfsdk:"category"`
+ UserOverride types.Bool `tfsdk:"user_override"`
+ Settings []AndroidSettings `tfsdk:"settings"`
+}
+
+type Chromeos struct {
+ Category types.String `tfsdk:"category"`
+ UserOverride types.Bool `tfsdk:"user_override"`
+ Settings []ChromeosSettings `tfsdk:"settings"`
+}
+
+type Html5 struct {
+ Category types.String `tfsdk:"category"`
+ UserOverride types.Bool `tfsdk:"user_override"`
+ Settings []Html5Settings `tfsdk:"settings"`
+}
+
+type Macos struct {
+ Category types.String `tfsdk:"category"`
+ UserOverride types.Bool `tfsdk:"user_override"`
+ Settings []MacosSettings `tfsdk:"settings"`
+}
+
+type WindowsSettings struct {
+ Name types.String `tfsdk:"name"`
+ ValueString types.String `tfsdk:"value_string"`
+ ValueList []types.String `tfsdk:"value_list"`
+}
+
+type IosSettings struct {
+ Name types.String `tfsdk:"name"`
+ ValueString types.String `tfsdk:"value_string"`
+}
+
+type AndroidSettings struct {
+ Name types.String `tfsdk:"name"`
+ ValueString types.String `tfsdk:"value_string"`
+ ValueList []types.String `tfsdk:"value_list"`
+}
+
+type ChromeosSettings struct {
+ Name types.String `tfsdk:"name"`
+ ValueString types.String `tfsdk:"value_string"`
+ ValueList []types.String `tfsdk:"value_list"`
+}
+
+type Html5Settings struct {
+ Name types.String `tfsdk:"name"`
+ ValueString types.String `tfsdk:"value_string"`
+ ValueList []types.String `tfsdk:"value_list"`
+}
+
+type MacosSettings struct {
+ Name types.String `tfsdk:"name"`
+ ValueString types.String `tfsdk:"value_string"`
+ ValueList []types.String `tfsdk:"value_list"`
+}
+
+func (r GACSettingsResourceModel) RefreshPropertyValues(settingsRecordModel globalappconfiguration.SettingsRecordModel, diagnostics *diag.Diagnostics) GACSettingsResourceModel {
+
+ var serviceUrlModel = settingsRecordModel.GetServiceURL()
+ r.ServiceUrl = types.StringValue(serviceUrlModel.GetUrl())
+
+ var settings = settingsRecordModel.GetSettings()
+ r.Name = types.StringValue(settings.GetName())
+ r.Description = types.StringValue(settings.GetDescription())
+ r.UseForAppConfig = types.BoolValue(settings.GetUseForAppConfig())
+
+ var appSettings = settings.GetAppSettings()
+ var windowsSettings = appSettings.GetWindows()
+ var iosSettings = appSettings.GetIos()
+ var androidSettings = appSettings.GetAndroid()
+ var chromeosSettings = appSettings.GetChromeos()
+ var html5Settings = appSettings.GetHtml5()
+ var macosSettings = appSettings.GetMacos()
+
+ if r.AppSettings == nil {
+ r.AppSettings = &AppSettings{}
+ }
+ r.AppSettings.Windows = r.getWindowsSettings(windowsSettings, diagnostics)
+ r.AppSettings.Ios = r.getIosSettings(iosSettings, diagnostics)
+ r.AppSettings.Android = r.getAndroidSettings(androidSettings, diagnostics)
+ r.AppSettings.Chromeos = r.getChromeosSettings(chromeosSettings, diagnostics)
+ r.AppSettings.Html5 = r.getHtml5Settings(html5Settings, diagnostics)
+ r.AppSettings.Macos = r.getMacosSettings(macosSettings, diagnostics)
+
+ return r
+}
+
+func (r GACSettingsResourceModel) getWindowsSettings(remoteWindowsSettings []globalappconfiguration.PlatformSettings, diagnostics *diag.Diagnostics) []Windows {
+ var stateWindowsSettings []Windows
+ if r.AppSettings != nil && r.AppSettings.Windows != nil {
+ stateWindowsSettings = r.AppSettings.Windows
+ }
+
+ type RemoteWindowsSettingsTracker struct {
+ platformSetting globalappconfiguration.PlatformSettings
+ IsVisited bool
+ }
+
+ // Create a map of category -> RemoteWindowsSettingsTracker for remote
+ remoteWindowsSettingsMap := map[string]*RemoteWindowsSettingsTracker{}
+ for _, remoteWindowsSetting := range remoteWindowsSettings {
+ remoteWindowsSettingsMap[remoteWindowsSetting.GetCategory()] = &RemoteWindowsSettingsTracker{
+ platformSetting: remoteWindowsSetting,
+ IsVisited: false,
+ }
+ }
+
+ // Prepare the windows settings list to be stored in the state
+ var windowsSettingsForState []Windows
+ for _, stateWindowsSetting := range stateWindowsSettings {
+ remoteWindowsSetting, exists := remoteWindowsSettingsMap[stateWindowsSetting.Category.ValueString()]
+ if !exists {
+ // If windows setting is not present in the remote, then don't add it to the state
+ continue
+ }
+
+ windowsSettingsForState = append(windowsSettingsForState, Windows{
+ Category: types.StringValue(remoteWindowsSetting.platformSetting.GetCategory()),
+ UserOverride: types.BoolValue(remoteWindowsSetting.platformSetting.GetUserOverride()),
+ Settings: getWindowsCategorySettings(stateWindowsSetting.Settings, remoteWindowsSetting.platformSetting.GetSettings(), diagnostics),
+ })
+
+ remoteWindowsSetting.IsVisited = true
+
+ }
+
+ // Add the windows settings from remote which are not present in the state
+ for _, remoteWindowsSetting := range remoteWindowsSettingsMap {
+ if !remoteWindowsSetting.IsVisited {
+ windowsSettingsForState = append(windowsSettingsForState, Windows{
+ Category: types.StringValue(remoteWindowsSetting.platformSetting.GetCategory()),
+ UserOverride: types.BoolValue(remoteWindowsSetting.platformSetting.GetUserOverride()),
+ Settings: parseWindowsSettings(remoteWindowsSetting.platformSetting.GetSettings(), diagnostics),
+ })
+ }
+ }
+
+ return windowsSettingsForState
+}
+
+func (r GACSettingsResourceModel) getIosSettings(remoteIosSettings []globalappconfiguration.PlatformSettings, diagnostics *diag.Diagnostics) []Ios {
+ var stateIosSettings []Ios
+ if r.AppSettings != nil && r.AppSettings.Ios != nil {
+ stateIosSettings = r.AppSettings.Ios
+ }
+
+ type RemoteIosSettingsTracker struct {
+ platformSetting globalappconfiguration.PlatformSettings
+ IsVisited bool
+ }
+
+ // Create a map of category -> RemoteIosSettingsTracker for remote
+ remoteIosSettingsMap := map[string]*RemoteIosSettingsTracker{}
+ for _, remoteIosSetting := range remoteIosSettings {
+ remoteIosSettingsMap[remoteIosSetting.GetCategory()] = &RemoteIosSettingsTracker{
+ platformSetting: remoteIosSetting,
+ IsVisited: false,
+ }
+ }
+
+ // Prepare the ios settings list to be stored in the state
+ var iosSettingsForState []Ios
+ for _, stateIosSetting := range stateIosSettings {
+ remoteIosSetting, exists := remoteIosSettingsMap[stateIosSetting.Category.ValueString()]
+ if !exists {
+ // If ios setting is not present in the remote, then don't add it to the state
+ continue
+ }
+
+ iosSettingsForState = append(iosSettingsForState, Ios{
+ Category: types.StringValue(remoteIosSetting.platformSetting.GetCategory()),
+ UserOverride: types.BoolValue(remoteIosSetting.platformSetting.GetUserOverride()),
+ Settings: getIosCategorySettings(stateIosSetting.Settings, remoteIosSetting.platformSetting.GetSettings(), diagnostics),
+ })
+
+ remoteIosSetting.IsVisited = true
+
+ }
+
+ // Add the ios settings from remote which are not present in the state
+ for _, remoteIosSetting := range remoteIosSettingsMap {
+ if !remoteIosSetting.IsVisited {
+ iosSettingsForState = append(iosSettingsForState, Ios{
+ Category: types.StringValue(remoteIosSetting.platformSetting.GetCategory()),
+ UserOverride: types.BoolValue(remoteIosSetting.platformSetting.GetUserOverride()),
+ Settings: parseIosSettings(remoteIosSetting.platformSetting.GetSettings(), diagnostics),
+ })
+ }
+ }
+
+ return iosSettingsForState
+}
+
+func (r GACSettingsResourceModel) getAndroidSettings(remoteAndroidSettings []globalappconfiguration.PlatformSettings, diagnostics *diag.Diagnostics) []Android {
+ var stateAndroidSettings []Android
+ if r.AppSettings != nil && r.AppSettings.Android != nil {
+ stateAndroidSettings = r.AppSettings.Android
+ }
+
+ type RemoteAndroidSettingsTracker struct {
+ platformSetting globalappconfiguration.PlatformSettings
+ IsVisited bool
+ }
+
+ // Create a map of category -> RemoteAndroidSettingsTracker for remote
+ remoteAndroidSettingsMap := map[string]*RemoteAndroidSettingsTracker{}
+ for _, remoteAndroidSetting := range remoteAndroidSettings {
+ remoteAndroidSettingsMap[remoteAndroidSetting.GetCategory()] = &RemoteAndroidSettingsTracker{
+ platformSetting: remoteAndroidSetting,
+ IsVisited: false,
+ }
+ }
+
+ // Prepare the android settings list to be stored in the state
+ var androidSettingsForState []Android
+ for _, stateAndroidSetting := range stateAndroidSettings {
+ remoteAndroidSetting, exists := remoteAndroidSettingsMap[stateAndroidSetting.Category.ValueString()]
+ if !exists {
+ // If android setting is not present in the remote, then don't add it to the state
+ continue
+ }
+
+ androidSettingsForState = append(androidSettingsForState, Android{
+ Category: types.StringValue(remoteAndroidSetting.platformSetting.GetCategory()),
+ UserOverride: types.BoolValue(remoteAndroidSetting.platformSetting.GetUserOverride()),
+ Settings: getAndroidCategorySettings(stateAndroidSetting.Settings, remoteAndroidSetting.platformSetting.GetSettings(), diagnostics),
+ })
+
+ remoteAndroidSetting.IsVisited = true
+
+ }
+
+ // Add the android settings from remote which are not present in the state
+ for _, remoteAndroidSetting := range remoteAndroidSettingsMap {
+ if !remoteAndroidSetting.IsVisited {
+ androidSettingsForState = append(androidSettingsForState, Android{
+ Category: types.StringValue(remoteAndroidSetting.platformSetting.GetCategory()),
+ UserOverride: types.BoolValue(remoteAndroidSetting.platformSetting.GetUserOverride()),
+ Settings: parseAndroidSettings(remoteAndroidSetting.platformSetting.GetSettings(), diagnostics),
+ })
+ }
+ }
+
+ return androidSettingsForState
+}
+
+func (r GACSettingsResourceModel) getHtml5Settings(remoteHtml5Settings []globalappconfiguration.PlatformSettings, diagnostics *diag.Diagnostics) []Html5 {
+ var stateHtml5Settings []Html5
+ if r.AppSettings != nil && r.AppSettings.Html5 != nil {
+ stateHtml5Settings = r.AppSettings.Html5
+ }
+
+ type RemoteHtml5SettingsTracker struct {
+ platformSetting globalappconfiguration.PlatformSettings
+ IsVisited bool
+ }
+
+ // Create a map of category -> RemoteHtml5SettingsTracker for remote
+ remoteHtml5SettingsMap := map[string]*RemoteHtml5SettingsTracker{}
+ for _, remoteHtml5Setting := range remoteHtml5Settings {
+ remoteHtml5SettingsMap[remoteHtml5Setting.GetCategory()] = &RemoteHtml5SettingsTracker{
+ platformSetting: remoteHtml5Setting,
+ IsVisited: false,
+ }
+ }
+
+ // Prepare the html5 settings list to be stored in the state
+ var html5SettingsForState []Html5
+ for _, stateHtml5Setting := range stateHtml5Settings {
+ remoteHtml5Setting, exists := remoteHtml5SettingsMap[stateHtml5Setting.Category.ValueString()]
+ if !exists {
+ // If html5 setting is not present in the remote, then don't add it to the state
+ continue
+ }
+
+ html5SettingsForState = append(html5SettingsForState, Html5{
+ Category: types.StringValue(remoteHtml5Setting.platformSetting.GetCategory()),
+ UserOverride: types.BoolValue(remoteHtml5Setting.platformSetting.GetUserOverride()),
+ Settings: getHtml5CategorySettings(stateHtml5Setting.Settings, remoteHtml5Setting.platformSetting.GetSettings(), diagnostics),
+ })
+
+ remoteHtml5Setting.IsVisited = true
+
+ }
+
+ // Add the html5 settings from remote which are not present in the state
+ for _, remoteHtml5Setting := range remoteHtml5SettingsMap {
+ if !remoteHtml5Setting.IsVisited {
+ html5SettingsForState = append(html5SettingsForState, Html5{
+ Category: types.StringValue(remoteHtml5Setting.platformSetting.GetCategory()),
+ UserOverride: types.BoolValue(remoteHtml5Setting.platformSetting.GetUserOverride()),
+ Settings: parseHtml5Settings(remoteHtml5Setting.platformSetting.GetSettings(), diagnostics),
+ })
+ }
+ }
+
+ return html5SettingsForState
+}
+
+func (r GACSettingsResourceModel) getChromeosSettings(remoteChromeosSettings []globalappconfiguration.PlatformSettings, diagnostics *diag.Diagnostics) []Chromeos {
+ var stateChromeosSettings []Chromeos
+ if r.AppSettings != nil && r.AppSettings.Chromeos != nil {
+ stateChromeosSettings = r.AppSettings.Chromeos
+ }
+
+ type RemoteChromeosSettingsTracker struct {
+ platformSetting globalappconfiguration.PlatformSettings
+ IsVisited bool
+ }
+
+ // Create a map of category -> RemoteChromeosSettingsTracker for remote
+ remoteChromeosSettingsMap := map[string]*RemoteChromeosSettingsTracker{}
+ for _, remoteChromeosSetting := range remoteChromeosSettings {
+ remoteChromeosSettingsMap[remoteChromeosSetting.GetCategory()] = &RemoteChromeosSettingsTracker{
+ platformSetting: remoteChromeosSetting,
+ IsVisited: false,
+ }
+ }
+
+ // Prepare the chromeos settings list to be stored in the state
+ var chromeosSettingsForState []Chromeos
+ for _, stateChromeosSetting := range stateChromeosSettings {
+ remoteChromeosSetting, exists := remoteChromeosSettingsMap[stateChromeosSetting.Category.ValueString()]
+ if !exists {
+ // If chromeos setting is not present in the remote, then don't add it to the state
+ continue
+ }
+
+ chromeosSettingsForState = append(chromeosSettingsForState, Chromeos{
+ Category: types.StringValue(remoteChromeosSetting.platformSetting.GetCategory()),
+ UserOverride: types.BoolValue(remoteChromeosSetting.platformSetting.GetUserOverride()),
+ Settings: getChromeosCategorySettings(stateChromeosSetting.Settings, remoteChromeosSetting.platformSetting.GetSettings(), diagnostics),
+ })
+
+ remoteChromeosSetting.IsVisited = true
+
+ }
+
+ // Add the chromeos settings from remote which are not present in the state
+ for _, remoteChromeosSetting := range remoteChromeosSettingsMap {
+ if !remoteChromeosSetting.IsVisited {
+ chromeosSettingsForState = append(chromeosSettingsForState, Chromeos{
+ Category: types.StringValue(remoteChromeosSetting.platformSetting.GetCategory()),
+ UserOverride: types.BoolValue(remoteChromeosSetting.platformSetting.GetUserOverride()),
+ Settings: parseChromeosSettings(remoteChromeosSetting.platformSetting.GetSettings(), diagnostics),
+ })
+ }
+ }
+
+ return chromeosSettingsForState
+}
+
+func (r GACSettingsResourceModel) getMacosSettings(remoteMacosSettings []globalappconfiguration.PlatformSettings, diagnostics *diag.Diagnostics) []Macos {
+ var stateMacosSettings []Macos
+ if r.AppSettings != nil && r.AppSettings.Macos != nil {
+ stateMacosSettings = r.AppSettings.Macos
+ }
+
+ type RemoteMacosSettingsTracker struct {
+ platformSetting globalappconfiguration.PlatformSettings
+ IsVisited bool
+ }
+
+ // Create a map of category -> RemoteMacosSettingsTracker for remote
+ remoteMacosSettingsMap := map[string]*RemoteMacosSettingsTracker{}
+ for _, remoteMacosSetting := range remoteMacosSettings {
+ remoteMacosSettingsMap[remoteMacosSetting.GetCategory()] = &RemoteMacosSettingsTracker{
+ platformSetting: remoteMacosSetting,
+ IsVisited: false,
+ }
+ }
+
+ // Prepare the macos settings list to be stored in the state
+ var macosSettingsForState []Macos
+ for _, stateMacosSetting := range stateMacosSettings {
+ remoteMacosSetting, exists := remoteMacosSettingsMap[stateMacosSetting.Category.ValueString()]
+ if !exists {
+ // If macos setting is not present in the remote, then don't add it to the state
+ continue
+ }
+
+ macosSettingsForState = append(macosSettingsForState, Macos{
+ Category: types.StringValue(remoteMacosSetting.platformSetting.GetCategory()),
+ UserOverride: types.BoolValue(remoteMacosSetting.platformSetting.GetUserOverride()),
+ Settings: getMacosCategorySettings(stateMacosSetting.Settings, remoteMacosSetting.platformSetting.GetSettings(), diagnostics),
+ })
+
+ remoteMacosSetting.IsVisited = true
+
+ }
+
+ // Add the macos settings from remote which are not present in the state
+ for _, remoteMacosSetting := range remoteMacosSettingsMap {
+ if !remoteMacosSetting.IsVisited {
+ macosSettingsForState = append(macosSettingsForState, Macos{
+ Category: types.StringValue(remoteMacosSetting.platformSetting.GetCategory()),
+ UserOverride: types.BoolValue(remoteMacosSetting.platformSetting.GetUserOverride()),
+ Settings: parseMacosSettings(remoteMacosSetting.platformSetting.GetSettings(), diagnostics),
+ })
+ }
+ }
+
+ return macosSettingsForState
+}
+
+func parseWindowsSettings(remoteWindowsSettings []globalappconfiguration.CategorySettings, diagnostics *diag.Diagnostics) []WindowsSettings {
+ var windowsSettings []WindowsSettings
+ var errMsg string
+
+ for _, remoteWindowsSetting := range remoteWindowsSettings {
+ var windowsSetting WindowsSettings
+ windowsSetting.Name = types.StringValue(remoteWindowsSetting.GetName())
+ valueType := reflect.TypeOf(remoteWindowsSetting.GetValue())
+ switch valueType.Kind() {
+ case reflect.String:
+ windowsSetting.ValueString = types.StringValue(remoteWindowsSetting.GetValue().(string))
+ case reflect.Slice:
+ windowsSetting.ValueList, errMsg = util.ConvertPrimitiveInterfaceArrayToBaseStringArray(remoteWindowsSetting.Value.([]interface{}))
+ default:
+ errMsg = fmt.Sprintf("Unsupported type for windows setting value: %v", valueType.Kind())
+ }
+ if errMsg != "" {
+ diagnostics.AddError(
+ "Could not parse value for the setting:"+windowsSetting.Name.ValueString(),
+ errMsg,
+ )
+ }
+
+ windowsSettings = append(windowsSettings, windowsSetting)
+ }
+
+ return windowsSettings
+}
+
+func parseIosSettings(remoteIosSettings []globalappconfiguration.CategorySettings, diagnostics *diag.Diagnostics) []IosSettings {
+ var iosSettings []IosSettings
+ var errMsg string
+
+ for _, remoteIosSetting := range remoteIosSettings {
+ var iosSetting IosSettings
+ iosSetting.Name = types.StringValue(remoteIosSetting.GetName())
+ valueType := reflect.TypeOf(remoteIosSetting.GetValue())
+ switch valueType.Kind() {
+ case reflect.String:
+ iosSetting.ValueString = types.StringValue(remoteIosSetting.GetValue().(string))
+ default:
+ errMsg = fmt.Sprintf("Unsupported type for ios setting value: %v", valueType.Kind())
+ }
+ if errMsg != "" {
+ diagnostics.AddError(
+ "Could not parse value for the setting:"+iosSetting.Name.ValueString(),
+ errMsg,
+ )
+ }
+
+ iosSettings = append(iosSettings, iosSetting)
+ }
+
+ return iosSettings
+}
+
+func parseAndroidSettings(remoteAndroidSettings []globalappconfiguration.CategorySettings, diagnostics *diag.Diagnostics) []AndroidSettings {
+ var androidSettings []AndroidSettings
+ var errMsg string
+
+ for _, remoteAndroidSetting := range remoteAndroidSettings {
+ var androidSetting AndroidSettings
+ androidSetting.Name = types.StringValue(remoteAndroidSetting.GetName())
+ valueType := reflect.TypeOf(remoteAndroidSetting.GetValue())
+ switch valueType.Kind() {
+ case reflect.String:
+ androidSetting.ValueString = types.StringValue(remoteAndroidSetting.GetValue().(string))
+ case reflect.Slice:
+ androidSetting.ValueList, errMsg = util.ConvertPrimitiveInterfaceArrayToBaseStringArray(remoteAndroidSetting.Value.([]interface{}))
+ default:
+ errMsg = fmt.Sprintf("Unsupported type for android setting value: %v", valueType.Kind())
+ }
+ if errMsg != "" {
+ diagnostics.AddError(
+ "Could not parse value for the setting:"+androidSetting.Name.ValueString(),
+ errMsg,
+ )
+ }
+
+ androidSettings = append(androidSettings, androidSetting)
+ }
+
+ return androidSettings
+}
+
+func parseHtml5Settings(remoteHtml5Settings []globalappconfiguration.CategorySettings, diagnostics *diag.Diagnostics) []Html5Settings {
+ var html5Settings []Html5Settings
+ var errMsg string
+
+ for _, remoteHtml5Setting := range remoteHtml5Settings {
+ var html5Setting Html5Settings
+ html5Setting.Name = types.StringValue(remoteHtml5Setting.GetName())
+ valueType := reflect.TypeOf(remoteHtml5Setting.GetValue())
+ switch valueType.Kind() {
+ case reflect.String:
+ html5Setting.ValueString = types.StringValue(remoteHtml5Setting.GetValue().(string))
+ case reflect.Slice:
+ html5Setting.ValueList, errMsg = util.ConvertPrimitiveInterfaceArrayToBaseStringArray(remoteHtml5Setting.Value.([]interface{}))
+ default:
+ errMsg = fmt.Sprintf("Unsupported type for html5 setting value: %v", valueType.Kind())
+ }
+ if errMsg != "" {
+ diagnostics.AddError(
+ "Could not parse value for the setting:"+html5Setting.Name.ValueString(),
+ errMsg,
+ )
+ }
+
+ html5Settings = append(html5Settings, html5Setting)
+ }
+
+ return html5Settings
+}
+
+func parseMacosSettings(remoteMacosSettings []globalappconfiguration.CategorySettings, diagnostics *diag.Diagnostics) []MacosSettings {
+ var macosSettings []MacosSettings
+ var errMsg string
+
+ for _, remoteMacosSetting := range remoteMacosSettings {
+ var macosSetting MacosSettings
+ macosSetting.Name = types.StringValue(remoteMacosSetting.GetName())
+ valueType := reflect.TypeOf(remoteMacosSetting.GetValue())
+ switch valueType.Kind() {
+ case reflect.String:
+ macosSetting.ValueString = types.StringValue(remoteMacosSetting.GetValue().(string))
+ case reflect.Slice:
+ macosSetting.ValueList, errMsg = util.ConvertPrimitiveInterfaceArrayToBaseStringArray(remoteMacosSetting.Value.([]interface{}))
+ default:
+ errMsg = fmt.Sprintf("Unsupported type for macos setting value: %v", valueType.Kind())
+ }
+ if errMsg != "" {
+ diagnostics.AddError(
+ "Could not parse value for the setting:"+macosSetting.Name.ValueString(),
+ errMsg,
+ )
+ }
+
+ macosSettings = append(macosSettings, macosSetting)
+ }
+
+ return macosSettings
+}
+
+func parseChromeosSettings(remoteChromeosSettings []globalappconfiguration.CategorySettings, diagnostics *diag.Diagnostics) []ChromeosSettings {
+ var chromeosSettings []ChromeosSettings
+ var errMsg string
+
+ for _, remoteChromeosSetting := range remoteChromeosSettings {
+ var chromeosSetting ChromeosSettings
+ chromeosSetting.Name = types.StringValue(remoteChromeosSetting.GetName())
+ valueType := reflect.TypeOf(remoteChromeosSetting.GetValue())
+ switch valueType.Kind() {
+ case reflect.String:
+ chromeosSetting.ValueString = types.StringValue(remoteChromeosSetting.GetValue().(string))
+ case reflect.Slice:
+ chromeosSetting.ValueList, errMsg = util.ConvertPrimitiveInterfaceArrayToBaseStringArray(remoteChromeosSetting.Value.([]interface{}))
+ default:
+ errMsg = fmt.Sprintf("Unsupported type for chrome os setting value: %v", valueType.Kind())
+ }
+ if errMsg != "" {
+ diagnostics.AddError(
+ "Could not parse value for the setting:"+chromeosSetting.Name.ValueString(),
+ errMsg,
+ )
+ }
+
+ chromeosSettings = append(chromeosSettings, chromeosSetting)
+ }
+
+ return chromeosSettings
+}
+
+func getWindowsCategorySettings(stateWindowsSettings []WindowsSettings, remoteWindowsSettings []globalappconfiguration.CategorySettings, diagnostics *diag.Diagnostics) []WindowsSettings {
+
+ var windowsSettingsForState []WindowsSettings
+ var errMsg string
+
+ type RemoteSettingsTracker struct {
+ Value interface{}
+ IsVisited bool
+ }
+
+ // Create a map of name -> RemoteSettingsTracker for remote
+ remoteWindowsCategorySettingsMap := map[string]*RemoteSettingsTracker{}
+ for _, remoteWindowsSetting := range remoteWindowsSettings {
+ remoteWindowsCategorySettingsMap[remoteWindowsSetting.GetName()] = &RemoteSettingsTracker{
+ Value: remoteWindowsSetting.GetValue(),
+ IsVisited: false,
+ }
+ }
+
+ // Prepare the windows settings list to be stored in the state
+ for _, stateWindowsSetting := range stateWindowsSettings {
+ remoteWindowsSetting, exists := remoteWindowsCategorySettingsMap[stateWindowsSetting.Name.ValueString()]
+ if !exists {
+ // If windows setting is not present in the remote, then don't add it to the state
+ continue
+ }
+
+ var windowsSetting WindowsSettings
+ errMsg = ""
+
+ windowsSetting.Name = stateWindowsSetting.Name // Since this value is present as the map key, it is same as remote
+ valueType := reflect.TypeOf(remoteWindowsSetting.Value)
+ switch valueType.Kind() {
+ case reflect.String:
+ windowsSetting.ValueString = types.StringValue(remoteWindowsSetting.Value.(string))
+ case reflect.Slice:
+ windowsSetting.ValueList, errMsg = util.ConvertPrimitiveInterfaceArrayToBaseStringArray(remoteWindowsSetting.Value.([]interface{}))
+ default:
+ errMsg = fmt.Sprintf("Unsupported type for windows setting value: %v", valueType.Kind())
+ }
+ if errMsg != "" {
+ diagnostics.AddError(
+ "Could not parse value for the setting:"+windowsSetting.Name.ValueString(),
+ errMsg,
+ )
+ }
+
+ windowsSettingsForState = append(windowsSettingsForState, windowsSetting)
+ remoteWindowsSetting.IsVisited = true
+ }
+
+ // Add the windows settings from remote which are not present in the state
+ for settingName, remoteWindowsSetting := range remoteWindowsCategorySettingsMap {
+ if !remoteWindowsSetting.IsVisited {
+ var windowsSetting WindowsSettings
+ errMsg = ""
+ windowsSetting.Name = types.StringValue(settingName)
+ valueType := reflect.TypeOf(remoteWindowsSetting.Value)
+ switch valueType.Kind() {
+ case reflect.String:
+ windowsSetting.ValueString = types.StringValue(remoteWindowsSetting.Value.(string))
+ case reflect.Slice:
+ windowsSetting.ValueList, errMsg = util.ConvertPrimitiveInterfaceArrayToBaseStringArray(remoteWindowsSetting.Value.([]interface{}))
+ default:
+ errMsg = fmt.Sprintf("Unsupported type for windows setting value: %v", valueType.Kind())
+ }
+ if errMsg != "" {
+ diagnostics.AddError(
+ "Could not parse value for the setting:"+windowsSetting.Name.ValueString(),
+ errMsg,
+ )
+ }
+
+ windowsSettingsForState = append(windowsSettingsForState, windowsSetting)
+ }
+ }
+
+ return windowsSettingsForState
+}
+
+func getIosCategorySettings(stateIosSettings []IosSettings, remoteIosSettings []globalappconfiguration.CategorySettings, diagnostics *diag.Diagnostics) []IosSettings {
+
+ var iosSettingsForState []IosSettings
+ var errMsg string
+
+ type RemoteSettingsTracker struct {
+ Value interface{}
+ IsVisited bool
+ }
+
+ // Create a map of name -> RemoteSettingsTracker for remote
+ remoteIosCategorySettingsMap := map[string]*RemoteSettingsTracker{}
+ for _, remoteIosSetting := range remoteIosSettings {
+ remoteIosCategorySettingsMap[remoteIosSetting.GetName()] = &RemoteSettingsTracker{
+ Value: remoteIosSetting.GetValue(),
+ IsVisited: false,
+ }
+ }
+
+ // Prepare the ios settings list to be stored in the state
+ for _, stateIosSetting := range stateIosSettings {
+ remoteIosSetting, exists := remoteIosCategorySettingsMap[stateIosSetting.Name.ValueString()]
+ if !exists {
+ // If ios setting is not present in the remote, then don't add it to the state
+ continue
+ }
+
+ var iosSetting IosSettings
+ errMsg = ""
+
+ iosSetting.Name = stateIosSetting.Name // Since this value is present as the map key, it is same as remote
+ valueType := reflect.TypeOf(remoteIosSetting.Value)
+ switch valueType.Kind() {
+ case reflect.String:
+ iosSetting.ValueString = types.StringValue(remoteIosSetting.Value.(string))
+ default:
+ errMsg = fmt.Sprintf("Unsupported type for ios setting value: %v", valueType.Kind())
+ }
+ if errMsg != "" {
+ diagnostics.AddError(
+ "Could not parse value for the setting:"+iosSetting.Name.ValueString(),
+ errMsg,
+ )
+ }
+
+ iosSettingsForState = append(iosSettingsForState, iosSetting)
+ remoteIosSetting.IsVisited = true
+ }
+
+ // Add the ios settings from remote which are not present in the state
+ for settingName, remoteIosSetting := range remoteIosCategorySettingsMap {
+ if !remoteIosSetting.IsVisited {
+ var iosSetting IosSettings
+ errMsg = ""
+ iosSetting.Name = types.StringValue(settingName)
+ valueType := reflect.TypeOf(remoteIosSetting.Value)
+ switch valueType.Kind() {
+ case reflect.String:
+ iosSetting.ValueString = types.StringValue(remoteIosSetting.Value.(string))
+ default:
+ fmt.Errorf("Unsupported type for ios setting value: %v", valueType.Kind())
+ }
+ if errMsg != "" {
+ diagnostics.AddError(
+ "Could not parse value for the setting:"+iosSetting.Name.ValueString(),
+ errMsg,
+ )
+ }
+
+ iosSettingsForState = append(iosSettingsForState, iosSetting)
+ }
+ }
+
+ return iosSettingsForState
+}
+
+func getAndroidCategorySettings(stateAndroidSettings []AndroidSettings, remoteAndroidSettings []globalappconfiguration.CategorySettings, diagnostics *diag.Diagnostics) []AndroidSettings {
+
+ var androidSettingsForState []AndroidSettings
+ var errMsg string
+
+ type RemoteSettingsTracker struct {
+ Value interface{}
+ IsVisited bool
+ }
+
+ // Create a map of name -> RemoteSettingsTracker for remote
+ remoteAndroidCategorySettingsMap := map[string]*RemoteSettingsTracker{}
+ for _, remoteAndroidSetting := range remoteAndroidSettings {
+ remoteAndroidCategorySettingsMap[remoteAndroidSetting.GetName()] = &RemoteSettingsTracker{
+ Value: remoteAndroidSetting.GetValue(),
+ IsVisited: false,
+ }
+ }
+
+ // Prepare the android settings list to be stored in the state
+ for _, stateAndroidSetting := range stateAndroidSettings {
+ remoteAndroidSetting, exists := remoteAndroidCategorySettingsMap[stateAndroidSetting.Name.ValueString()]
+ if !exists {
+ // If android setting is not present in the remote, then don't add it to the state
+ continue
+ }
+
+ var androidSetting AndroidSettings
+ androidSetting.Name = stateAndroidSetting.Name // Since this value is present as the map key, it is same as remote
+ valueType := reflect.TypeOf(remoteAndroidSetting.Value)
+ switch valueType.Kind() {
+ case reflect.String:
+ androidSetting.ValueString = types.StringValue(remoteAndroidSetting.Value.(string))
+ case reflect.Slice:
+ androidSetting.ValueList, errMsg = util.ConvertPrimitiveInterfaceArrayToBaseStringArray(remoteAndroidSetting.Value.([]interface{}))
+ default:
+ errMsg = fmt.Sprintf("Unsupported type for android setting value: %v", valueType.Kind())
+ }
+ if errMsg != "" {
+ diagnostics.AddError(
+ "Could not parse value for the setting:"+androidSetting.Name.ValueString(),
+ errMsg,
+ )
+ }
+
+ androidSettingsForState = append(androidSettingsForState, androidSetting)
+ remoteAndroidSetting.IsVisited = true
+ }
+
+ // Add the android settings from remote which are not present in the state
+ for settingName, remoteAndroidSetting := range remoteAndroidCategorySettingsMap {
+ if !remoteAndroidSetting.IsVisited {
+ var androidSetting AndroidSettings
+ errMsg = ""
+ androidSetting.Name = types.StringValue(settingName)
+ valueType := reflect.TypeOf(remoteAndroidSetting.Value)
+ switch valueType.Kind() {
+ case reflect.String:
+ androidSetting.ValueString = types.StringValue(remoteAndroidSetting.Value.(string))
+ case reflect.Slice:
+ androidSetting.ValueList, errMsg = util.ConvertPrimitiveInterfaceArrayToBaseStringArray(remoteAndroidSetting.Value.([]interface{}))
+ default:
+ errMsg = fmt.Sprintf("Unsupported type for android setting value: %v", valueType.Kind())
+ }
+ if errMsg != "" {
+ diagnostics.AddError(
+ "Could not parse value for the setting:"+androidSetting.Name.ValueString(),
+ errMsg,
+ )
+ }
+
+ androidSettingsForState = append(androidSettingsForState, androidSetting)
+ }
+ }
+
+ return androidSettingsForState
+}
+
+func getChromeosCategorySettings(stateChromeosSettings []ChromeosSettings, remoteChromeosSettings []globalappconfiguration.CategorySettings, diagnostics *diag.Diagnostics) []ChromeosSettings {
+
+ var chromeosSettingsForState []ChromeosSettings
+ var errMsg string
+
+ type RemoteSettingsTracker struct {
+ Value interface{}
+ IsVisited bool
+ }
+
+ // Create a map of name -> RemoteSettingsTracker for remote
+ remoteChromeosCategorySettingsMap := map[string]*RemoteSettingsTracker{}
+ for _, remoteChromeosSetting := range remoteChromeosSettings {
+ remoteChromeosCategorySettingsMap[remoteChromeosSetting.GetName()] = &RemoteSettingsTracker{
+ Value: remoteChromeosSetting.GetValue(),
+ IsVisited: false,
+ }
+ }
+
+ // Prepare the chromeos settings list to be stored in the state
+ for _, stateChromeosSetting := range stateChromeosSettings {
+ remoteChromeosSetting, exists := remoteChromeosCategorySettingsMap[stateChromeosSetting.Name.ValueString()]
+ if !exists {
+ // If chromeos setting is not present in the remote, then don't add it to the state
+ continue
+ }
+
+ var chromeosSetting ChromeosSettings
+ errMsg = ""
+
+ chromeosSetting.Name = stateChromeosSetting.Name // Since this value is present as the map key, it is same as remote
+ valueType := reflect.TypeOf(remoteChromeosSetting.Value)
+ switch valueType.Kind() {
+ case reflect.String:
+ chromeosSetting.ValueString = types.StringValue(remoteChromeosSetting.Value.(string))
+ case reflect.Slice:
+ chromeosSetting.ValueList, errMsg = util.ConvertPrimitiveInterfaceArrayToBaseStringArray(remoteChromeosSetting.Value.([]interface{}))
+ default:
+ errMsg = fmt.Sprintf("Unsupported type for chromeos setting value: %v", valueType.Kind())
+ }
+ if errMsg != "" {
+ diagnostics.AddError(
+ "Could not parse value for the setting:"+chromeosSetting.Name.ValueString(),
+ errMsg,
+ )
+ }
+
+ chromeosSettingsForState = append(chromeosSettingsForState, chromeosSetting)
+ remoteChromeosSetting.IsVisited = true
+ }
+
+ // Add the chromeos settings from remote which are not present in the state
+ for settingName, remoteChromeosSetting := range remoteChromeosCategorySettingsMap {
+ if !remoteChromeosSetting.IsVisited {
+ var chromeosSetting ChromeosSettings
+ errMsg = ""
+
+ chromeosSetting.Name = types.StringValue(settingName)
+ valueType := reflect.TypeOf(remoteChromeosSetting.Value)
+ switch valueType.Kind() {
+ case reflect.String:
+ chromeosSetting.ValueString = types.StringValue(remoteChromeosSetting.Value.(string))
+ case reflect.Slice:
+ chromeosSetting.ValueList, errMsg = util.ConvertPrimitiveInterfaceArrayToBaseStringArray(remoteChromeosSetting.Value.([]interface{}))
+ default:
+ errMsg = fmt.Sprintf("Unsupported type for chromeos setting value: %v", valueType.Kind())
+ }
+ if errMsg != "" {
+ diagnostics.AddError(
+ "Could not parse value for the setting:"+chromeosSetting.Name.ValueString(),
+ errMsg,
+ )
+ }
+
+ chromeosSettingsForState = append(chromeosSettingsForState, chromeosSetting)
+ }
+ }
+
+ return chromeosSettingsForState
+}
+
+func getHtml5CategorySettings(stateHtml5Settings []Html5Settings, remoteHtml5Settings []globalappconfiguration.CategorySettings, diagnostics *diag.Diagnostics) []Html5Settings {
+
+ var html5SettingsForState []Html5Settings
+ var errMsg string
+
+ type RemoteSettingsTracker struct {
+ Value interface{}
+ IsVisited bool
+ }
+
+ // Create a map of name -> RemoteSettingsTracker for remote
+ remoteHtml5CategorySettingsMap := map[string]*RemoteSettingsTracker{}
+ for _, remoteHtml5Setting := range remoteHtml5Settings {
+ remoteHtml5CategorySettingsMap[remoteHtml5Setting.GetName()] = &RemoteSettingsTracker{
+ Value: remoteHtml5Setting.GetValue(),
+ IsVisited: false,
+ }
+ }
+
+ // Prepare the html5 settings list to be stored in the state
+ for _, stateHtml5Setting := range stateHtml5Settings {
+ remoteHtml5Setting, exists := remoteHtml5CategorySettingsMap[stateHtml5Setting.Name.ValueString()]
+ if !exists {
+ // If html5 setting is not present in the remote, then don't add it to the state
+ continue
+ }
+
+ var html5Setting Html5Settings
+ errMsg = ""
+
+ html5Setting.Name = stateHtml5Setting.Name // Since this value is present as the map key, it is same as remote
+ valueType := reflect.TypeOf(remoteHtml5Setting.Value)
+ switch valueType.Kind() {
+ case reflect.String:
+ html5Setting.ValueString = types.StringValue(remoteHtml5Setting.Value.(string))
+ case reflect.Slice:
+ html5Setting.ValueList, errMsg = util.ConvertPrimitiveInterfaceArrayToBaseStringArray(remoteHtml5Setting.Value.([]interface{}))
+ default:
+ errMsg = fmt.Sprintf("Unsupported type for html5 setting value: %v", valueType.Kind())
+ }
+ if errMsg != "" {
+ diagnostics.AddError(
+ "Could not parse value for the setting:"+html5Setting.Name.ValueString(),
+ errMsg,
+ )
+ }
+
+ html5SettingsForState = append(html5SettingsForState, html5Setting)
+ remoteHtml5Setting.IsVisited = true
+ }
+
+ // Add the html5 settings from remote which are not present in the state
+ for settingName, remoteHtml5Setting := range remoteHtml5CategorySettingsMap {
+ if !remoteHtml5Setting.IsVisited {
+ var html5Setting Html5Settings
+ errMsg = ""
+
+ html5Setting.Name = types.StringValue(settingName)
+ valueType := reflect.TypeOf(remoteHtml5Setting.Value)
+ switch valueType.Kind() {
+ case reflect.String:
+ html5Setting.ValueString = types.StringValue(remoteHtml5Setting.Value.(string))
+ case reflect.Slice:
+ html5Setting.ValueList, errMsg = util.ConvertPrimitiveInterfaceArrayToBaseStringArray(remoteHtml5Setting.Value.([]interface{}))
+ default:
+ errMsg = fmt.Sprintf("Unsupported type for html5 setting value: %v", valueType.Kind())
+ }
+ if errMsg != "" {
+ diagnostics.AddError(
+ "Could not parse value for the setting:"+html5Setting.Name.ValueString(),
+ errMsg,
+ )
+ }
+
+ html5SettingsForState = append(html5SettingsForState, html5Setting)
+ }
+ }
+
+ return html5SettingsForState
+}
+
+func getMacosCategorySettings(stateMacosSettings []MacosSettings, remoteMacosSettings []globalappconfiguration.CategorySettings, diagnostics *diag.Diagnostics) []MacosSettings {
+
+ var macosSettingsForState []MacosSettings
+ var errMsg string
+
+ type RemoteSettingsTracker struct {
+ Value interface{}
+ IsVisited bool
+ }
+
+ // Create a map of name -> RemoteSettingsTracker for remote
+ remoteMacosCategorySettingsMap := map[string]*RemoteSettingsTracker{}
+ for _, remoteMacosSetting := range remoteMacosSettings {
+ remoteMacosCategorySettingsMap[remoteMacosSetting.GetName()] = &RemoteSettingsTracker{
+ Value: remoteMacosSetting.GetValue(),
+ IsVisited: false,
+ }
+ }
+
+ // Prepare the macos settings list to be stored in the state
+ for _, stateMacosSetting := range stateMacosSettings {
+ remoteMacosSetting, exists := remoteMacosCategorySettingsMap[stateMacosSetting.Name.ValueString()]
+ if !exists {
+ // If macos setting is not present in the remote, then don't add it to the state
+ continue
+ }
+
+ var macosSetting MacosSettings
+ errMsg = ""
+
+ macosSetting.Name = stateMacosSetting.Name // Since this value is present as the map key, it is same as remote
+ valueType := reflect.TypeOf(remoteMacosSetting.Value)
+ switch valueType.Kind() {
+ case reflect.String:
+ macosSetting.ValueString = types.StringValue(remoteMacosSetting.Value.(string))
+ case reflect.Slice:
+ macosSetting.ValueList, errMsg = util.ConvertPrimitiveInterfaceArrayToBaseStringArray(remoteMacosSetting.Value.([]interface{}))
+ default:
+ errMsg = fmt.Sprintf("Unsupported type for macos setting value: %v", valueType.Kind())
+ }
+ if errMsg != "" {
+ diagnostics.AddError(
+ "Could not parse value for the setting:"+macosSetting.Name.ValueString(),
+ errMsg,
+ )
+ }
+
+ macosSettingsForState = append(macosSettingsForState, macosSetting)
+ remoteMacosSetting.IsVisited = true
+ }
+
+ // Add the macos settings from remote which are not present in the state
+ for settingName, remoteMacosSetting := range remoteMacosCategorySettingsMap {
+ if !remoteMacosSetting.IsVisited {
+ var macosSetting MacosSettings
+ errMsg = ""
+
+ macosSetting.Name = types.StringValue(settingName)
+ valueType := reflect.TypeOf(remoteMacosSetting.Value)
+ switch valueType.Kind() {
+ case reflect.String:
+ macosSetting.ValueString = types.StringValue(remoteMacosSetting.Value.(string))
+ case reflect.Slice:
+ macosSetting.ValueList, errMsg = util.ConvertPrimitiveInterfaceArrayToBaseStringArray(remoteMacosSetting.Value.([]interface{}))
+ default:
+ errMsg = fmt.Sprintf("Unsupported type for macos setting value: %v", valueType.Kind())
+ }
+ if errMsg != "" {
+ diagnostics.AddError(
+ "Could not parse value for the setting:"+macosSetting.Name.ValueString(),
+ errMsg,
+ )
+ }
+
+ macosSettingsForState = append(macosSettingsForState, macosSetting)
+ }
+ }
+
+ return macosSettingsForState
+}
diff --git a/internal/daas/hypervisor_resource_pool/aws_hypervisor_resource_pool_resource.go b/internal/daas/hypervisor_resource_pool/aws_hypervisor_resource_pool_resource.go
index 8e985e1..3067acb 100644
--- a/internal/daas/hypervisor_resource_pool/aws_hypervisor_resource_pool_resource.go
+++ b/internal/daas/hypervisor_resource_pool/aws_hypervisor_resource_pool_resource.go
@@ -17,7 +17,6 @@ import (
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
- "github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
@@ -82,9 +81,6 @@ func (r *awsHypervisorResourcePoolResource) Schema(_ context.Context, _ resource
ElementType: types.StringType,
Description: "List of subnets to allocate VDAs within the virtual private cloud.",
Required: true,
- PlanModifiers: []planmodifier.List{
- listplanmodifier.RequiresReplaceIfConfigured(),
- },
Validators: []validator.List{
listvalidator.SizeAtLeast(1),
},
@@ -239,6 +235,14 @@ func (r *awsHypervisorResourcePoolResource) Update(ctx context.Context, req reso
editHypervisorResourcePool.SetName(plan.Name.ValueString())
editHypervisorResourcePool.SetConnectionType(citrixorchestration.HYPERVISORCONNECTIONTYPE_AWS)
+ planSubnet := util.ConvertBaseStringArrayToPrimitiveStringArray(plan.Subnets)
+ availabilityZonePath := fmt.Sprintf("%s.virtualprivatecloud/%s.availabilityzone", plan.Vpc.ValueString(), plan.AvailabilityZone.ValueString())
+ subnets, err := util.GetFilteredResourcePathList(ctx, r.client, plan.Hypervisor.ValueString(), availabilityZonePath, util.NetworkResourceType, planSubnet, citrixorchestration.HYPERVISORCONNECTIONTYPE_AWS, "")
+ if err != nil {
+ return
+ }
+ editHypervisorResourcePool.SetNetworks(subnets)
+
updatedResourcePool, err := UpdateHypervisorResourcePool(ctx, r.client, &resp.Diagnostics, plan.Hypervisor.ValueString(), plan.Id.ValueString(), editHypervisorResourcePool)
if err != nil {
return
@@ -256,6 +260,8 @@ func (r *awsHypervisorResourcePoolResource) Update(ctx context.Context, req reso
}
func (r *awsHypervisorResourcePoolResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
idParts := strings.Split(req.ID, ",")
if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
diff --git a/internal/daas/hypervisor_resource_pool/azure_hypervisor_resource_pool_resource.go b/internal/daas/hypervisor_resource_pool/azure_hypervisor_resource_pool_resource.go
index 356dd43..1466b42 100644
--- a/internal/daas/hypervisor_resource_pool/azure_hypervisor_resource_pool_resource.go
+++ b/internal/daas/hypervisor_resource_pool/azure_hypervisor_resource_pool_resource.go
@@ -18,7 +18,6 @@ import (
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
- "github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
@@ -90,9 +89,6 @@ func (r *azureHypervisorResourcePoolResource) Schema(_ context.Context, _ resour
ElementType: types.StringType,
Description: "List of subnets to allocate VDAs within the virtual network.",
Required: true,
- PlanModifiers: []planmodifier.List{
- listplanmodifier.RequiresReplaceIfConfigured(),
- },
Validators: []validator.List{
listvalidator.SizeAtLeast(1),
},
@@ -278,6 +274,16 @@ func (r *azureHypervisorResourcePoolResource) Update(ctx context.Context, req re
editHypervisorResourcePool.SetName(plan.Name.ValueString())
editHypervisorResourcePool.SetConnectionType(citrixorchestration.HYPERVISORCONNECTIONTYPE_AZURE_RM)
+ planSubnet := util.ConvertBaseStringArrayToPrimitiveStringArray(plan.Subnets)
+ regionPath := fmt.Sprintf("%s.region", plan.Region.ValueString())
+ resourceGroupPath := fmt.Sprintf("%s.resourcegroup", plan.VirtualNetworkResourceGroup.ValueString())
+ vnetPath := fmt.Sprintf("%s.virtualprivatecloud", plan.VirtualNetwork.ValueString())
+ subnets, err := util.GetFilteredResourcePathList(ctx, r.client, plan.Hypervisor.ValueString(), fmt.Sprintf("%s/virtualprivatecloud.folder/%s/%s", regionPath, resourceGroupPath, vnetPath), util.NetworkResourceType, planSubnet, citrixorchestration.HYPERVISORCONNECTIONTYPE_AZURE_RM, "")
+ if err != nil {
+ return
+ }
+ editHypervisorResourcePool.SetSubnets(subnets)
+
updatedResourcePool, err := UpdateHypervisorResourcePool(ctx, r.client, &resp.Diagnostics, plan.Hypervisor.ValueString(), plan.Id.ValueString(), editHypervisorResourcePool)
if err != nil {
return
@@ -295,6 +301,8 @@ func (r *azureHypervisorResourcePoolResource) Update(ctx context.Context, req re
}
func (r *azureHypervisorResourcePoolResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
idParts := strings.Split(req.ID, ",")
if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
diff --git a/internal/daas/hypervisor_resource_pool/gcp_hypervisor_resource_pool_resource.go b/internal/daas/hypervisor_resource_pool/gcp_hypervisor_resource_pool_resource.go
index bdcc1fc..61a30d4 100644
--- a/internal/daas/hypervisor_resource_pool/gcp_hypervisor_resource_pool_resource.go
+++ b/internal/daas/hypervisor_resource_pool/gcp_hypervisor_resource_pool_resource.go
@@ -19,7 +19,6 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier"
- "github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
@@ -84,9 +83,6 @@ func (r *gcpHypervisorResourcePoolResource) Schema(_ context.Context, _ resource
ElementType: types.StringType,
Description: "List of subnets to allocate VDAs within the virtual network.",
Required: true,
- PlanModifiers: []planmodifier.List{
- listplanmodifier.RequiresReplaceIfConfigured(),
- },
Validators: []validator.List{
listvalidator.SizeAtLeast(1),
},
@@ -274,6 +270,19 @@ func (r *gcpHypervisorResourcePoolResource) Update(ctx context.Context, req reso
editHypervisorResourcePool.SetName(plan.Name.ValueString())
editHypervisorResourcePool.SetConnectionType(citrixorchestration.HYPERVISORCONNECTIONTYPE_GOOGLE_CLOUD_PLATFORM)
+ planSubnet := util.ConvertBaseStringArrayToPrimitiveStringArray(plan.Subnets)
+ regionPath := fmt.Sprintf("%s.project/%s.region", plan.ProjectName.ValueString(), plan.Region.ValueString())
+ vnetPath := fmt.Sprintf("%s/%s.virtualprivatecloud", regionPath, plan.Vpc.ValueString())
+ if plan.SharedVpc.ValueBool() {
+ // Support shared VPC if specified as true
+ vnetPath = fmt.Sprintf("%s/%s.sharedvirtualprivatecloud", regionPath, plan.Vpc.ValueString())
+ }
+ subnets, err := util.GetFilteredResourcePathList(ctx, r.client, plan.Hypervisor.ValueString(), vnetPath, util.NetworkResourceType, planSubnet, citrixorchestration.HYPERVISORCONNECTIONTYPE_GOOGLE_CLOUD_PLATFORM, "")
+ if err != nil {
+ return
+ }
+ editHypervisorResourcePool.SetNetworks(subnets)
+
updatedResourcePool, err := UpdateHypervisorResourcePool(ctx, r.client, &resp.Diagnostics, plan.Hypervisor.ValueString(), plan.Id.ValueString(), editHypervisorResourcePool)
if err != nil {
return
@@ -291,6 +300,8 @@ func (r *gcpHypervisorResourcePoolResource) Update(ctx context.Context, req reso
}
func (r *gcpHypervisorResourcePoolResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
idParts := strings.Split(req.ID, ",")
if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
diff --git a/internal/daas/hypervisor_resource_pool/nutanix_hypervisor_resource_pool_resource.go b/internal/daas/hypervisor_resource_pool/nutanix_hypervisor_resource_pool_resource.go
index 140bf9e..660de0b 100644
--- a/internal/daas/hypervisor_resource_pool/nutanix_hypervisor_resource_pool_resource.go
+++ b/internal/daas/hypervisor_resource_pool/nutanix_hypervisor_resource_pool_resource.go
@@ -239,6 +239,8 @@ func (r *nutanixHypervisorResourcePoolResource) Update(ctx context.Context, req
}
func (r *nutanixHypervisorResourcePoolResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
idParts := strings.Split(req.ID, ",")
if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
diff --git a/internal/daas/hypervisor_resource_pool/vsphere_hypervisor_resource_pool_resource.go b/internal/daas/hypervisor_resource_pool/vsphere_hypervisor_resource_pool_resource.go
index e3a1e64..02e88c6 100644
--- a/internal/daas/hypervisor_resource_pool/vsphere_hypervisor_resource_pool_resource.go
+++ b/internal/daas/hypervisor_resource_pool/vsphere_hypervisor_resource_pool_resource.go
@@ -408,6 +408,8 @@ func (r *vsphereHypervisorResourcePoolResource) Update(ctx context.Context, req
}
func (r *vsphereHypervisorResourcePoolResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
idParts := strings.Split(req.ID, ",")
if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
diff --git a/internal/daas/hypervisor_resource_pool/xenserver_hypervisor_resource_pool_resource.go b/internal/daas/hypervisor_resource_pool/xenserver_hypervisor_resource_pool_resource.go
index a2135f9..75ea7dc 100644
--- a/internal/daas/hypervisor_resource_pool/xenserver_hypervisor_resource_pool_resource.go
+++ b/internal/daas/hypervisor_resource_pool/xenserver_hypervisor_resource_pool_resource.go
@@ -307,6 +307,8 @@ func (r *xenserverHypervisorResourcePoolResource) Update(ctx context.Context, re
}
func (r *xenserverHypervisorResourcePoolResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
idParts := strings.Split(req.ID, ",")
if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
diff --git a/internal/daas/machine_catalog/machine_catalog_mcs_utils.go b/internal/daas/machine_catalog/machine_catalog_mcs_utils.go
index 5fe59cc..4235c06 100644
--- a/internal/daas/machine_catalog/machine_catalog_mcs_utils.go
+++ b/internal/daas/machine_catalog/machine_catalog_mcs_utils.go
@@ -35,6 +35,7 @@ var MappedCustomProperties = map[string]string{
"UseSharedImageGallery": "use_azure_compute_gallery",
"SharedImageGalleryReplicaRatio": "replica_ratio",
"SharedImageGalleryReplicaMaximum": "replica_maximum",
+ "UseEphemeralOsDisk": "storage_type",
}
func getProvSchemeForMcsCatalog(plan MachineCatalogResourceModel, ctx context.Context, client *citrixdaasclient.CitrixDaasClient, diagnostics *diag.Diagnostics, isOnPremises bool) (*citrixorchestration.CreateMachineCatalogProvisioningSchemeRequestModel, error) {
@@ -176,15 +177,8 @@ func buildProvSchemeForMcsCatalog(ctx context.Context, client *citrixdaasclient.
machineProfile := plan.ProvisioningScheme.AzureMachineConfig.MachineProfile
if machineProfile != nil {
- machine := machineProfile.MachineProfileVmName.ValueString()
- machineProfileResourceGroup := machineProfile.MachineProfileResourceGroup.ValueString()
- queryPath = fmt.Sprintf("machineprofile.folder\\%s.resourcegroup", machineProfileResourceGroup)
- machineProfilePath, err := util.GetSingleResourcePathFromHypervisor(ctx, client, hypervisor.GetName(), hypervisorResourcePool.GetName(), queryPath, machine, util.VirtualMachineResourceType, "")
+ machineProfilePath, err := handleMachineProfileForAzureMcsCatalog(ctx, client, diag, hypervisor.GetName(), hypervisorResourcePool.GetName(), *machineProfile, "creating")
if err != nil {
- diag.AddError(
- "Error creating Machine Catalog",
- fmt.Sprintf("Failed to locate machine profile %s on Azure, error: %s", plan.ProvisioningScheme.AzureMachineConfig.MachineProfile.MachineProfileVmName.ValueString(), err.Error()),
- )
return nil, err
}
provisioningScheme.SetMachineProfilePath(machineProfilePath)
@@ -389,7 +383,7 @@ func buildProvSchemeForMcsCatalog(ctx context.Context, client *citrixdaasclient.
}
if plan.ProvisioningScheme.NetworkMapping != nil {
- networkMapping, err := parseNetworkMappingToClientModel(*plan.ProvisioningScheme.NetworkMapping, hypervisorResourcePool, hypervisor.GetPluginId())
+ networkMapping, err := parseNetworkMappingToClientModel(plan.ProvisioningScheme.NetworkMapping, hypervisorResourcePool, hypervisor.GetPluginId())
if err != nil {
diag.AddError(
"Error creating Machine Catalog",
@@ -466,7 +460,7 @@ func setProvSchemePropertiesForUpdateCatalog(plan MachineCatalogResourceModel, b
}
if plan.ProvisioningScheme.NetworkMapping != nil {
- networkMapping, err := parseNetworkMappingToClientModel(*plan.ProvisioningScheme.NetworkMapping, hypervisorResourcePool, hypervisor.GetPluginId())
+ networkMapping, err := parseNetworkMappingToClientModel(plan.ProvisioningScheme.NetworkMapping, hypervisorResourcePool, hypervisor.GetPluginId())
if err != nil {
diagnostics.AddError(
"Error updating Machine Catalog",
@@ -727,15 +721,8 @@ func updateCatalogImageAndMachineProfile(ctx context.Context, client *citrixdaas
}
if azureMachineProfile != nil {
- machineProfileName := azureMachineProfile.MachineProfileVmName.ValueString()
- machineProfileResourceGroup := plan.ProvisioningScheme.AzureMachineConfig.MachineProfile.MachineProfileResourceGroup.ValueString()
- queryPath := fmt.Sprintf("machineprofile.folder\\%s.resourcegroup", machineProfileResourceGroup)
- machineProfilePath, err = util.GetSingleResourcePathFromHypervisor(ctx, client, hypervisor.GetName(), hypervisorResourcePool.GetName(), queryPath, machineProfileName, util.VirtualMachineResourceType, "")
+ machineProfilePath, err = handleMachineProfileForAzureMcsCatalog(ctx, client, &resp.Diagnostics, hypervisor.GetName(), hypervisorResourcePool.GetName(), *azureMachineProfile, "updating")
if err != nil {
- resp.Diagnostics.AddError(
- "Error updating Machine Catalog",
- fmt.Sprintf("Failed to locate machine profile %s on Azure, error: %s", plan.ProvisioningScheme.AzureMachineConfig.MachineProfile.MachineProfileVmName.ValueString(), err.Error()),
- )
return err
}
}
@@ -994,21 +981,7 @@ func (r MachineCatalogResourceModel) updateCatalogWithProvScheme(ctx context.Con
networkMaps := provScheme.GetNetworkMaps()
if len(networkMaps) > 0 && r.ProvisioningScheme.NetworkMapping != nil {
- r.ProvisioningScheme.NetworkMapping = &NetworkMappingModel{}
- r.ProvisioningScheme.NetworkMapping.NetworkDevice = types.StringValue(networkMaps[0].GetDeviceId())
- network := networkMaps[0].GetNetwork()
- segments := strings.Split(network.GetXDPath(), "\\")
- lastIndex := len(segments)
-
- networkName := (strings.Split(segments[lastIndex-1], "."))[0]
- if *connectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_AWS {
- /* For AWS Network, the XDPath looks like:
- * XDHyp:\\HostingUnits\\{resource pool}\\{availability zone}.availabilityzone\\{network ip}`/{prefix length} (vpc-{vpc-id}).network
- * The Network property should be set to {network ip}/{prefix length}
- */
- networkName = strings.ReplaceAll(strings.Split((strings.Split(segments[lastIndex-1], ".network"))[0], " ")[0], "`/", "/")
- }
- r.ProvisioningScheme.NetworkMapping.Network = types.StringValue(networkName)
+ r.ProvisioningScheme.NetworkMapping = util.RefreshListProperties[NetworkMappingModel, citrixorchestration.NetworkMapResponseModel](r.ProvisioningScheme.NetworkMapping, "NetworkDevice", networkMaps, "DeviceId", "RefreshListItem")
} else {
r.ProvisioningScheme.NetworkMapping = nil
}
@@ -1051,7 +1024,11 @@ func parseCustomPropertiesToClientModel(provisioningScheme ProvisioningSchemeMod
util.AppendNameValueStringPair(res, "Zones", "")
}
if !provisioningScheme.AzureMachineConfig.StorageType.IsNull() {
- util.AppendNameValueStringPair(res, "StorageType", provisioningScheme.AzureMachineConfig.StorageType.ValueString())
+ if provisioningScheme.AzureMachineConfig.StorageType.ValueString() == util.AzureEphemeralOSDisk {
+ util.AppendNameValueStringPair(res, "UseEphemeralOsDisk", "true")
+ } else {
+ util.AppendNameValueStringPair(res, "StorageType", provisioningScheme.AzureMachineConfig.StorageType.ValueString())
+ }
}
if !provisioningScheme.AzureMachineConfig.VdaResourceGroup.IsNull() {
util.AppendNameValueStringPair(res, "ResourceGroups", provisioningScheme.AzureMachineConfig.VdaResourceGroup.ValueString())
@@ -1126,44 +1103,49 @@ func parseCustomPropertiesToClientModel(provisioningScheme ProvisioningSchemeMod
return *res
}
-func parseNetworkMappingToClientModel(networkMapping NetworkMappingModel, resourcePool *citrixorchestration.HypervisorResourcePoolDetailResponseModel, hypervisorPluginId string) ([]citrixorchestration.NetworkMapRequestModel, error) {
+func parseNetworkMappingToClientModel(networkMappings []NetworkMappingModel, resourcePool *citrixorchestration.HypervisorResourcePoolDetailResponseModel, hypervisorPluginId string) ([]citrixorchestration.NetworkMapRequestModel, error) {
var networks []citrixorchestration.HypervisorResourceRefResponseModel
if resourcePool.ConnectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_AZURE_RM {
networks = resourcePool.Subnets
} else if resourcePool.ConnectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_AWS ||
resourcePool.ConnectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_GOOGLE_CLOUD_PLATFORM ||
resourcePool.ConnectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_V_CENTER ||
+ resourcePool.ConnectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_XEN_SERVER ||
resourcePool.ConnectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_CUSTOM && hypervisorPluginId == util.NUTANIX_PLUGIN_ID {
networks = resourcePool.Networks
}
var res = []citrixorchestration.NetworkMapRequestModel{}
- var networkName string
- if resourcePool.ConnectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_AZURE_RM ||
- resourcePool.ConnectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_GOOGLE_CLOUD_PLATFORM ||
- resourcePool.ConnectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_V_CENTER ||
- resourcePool.ConnectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_CUSTOM && hypervisorPluginId == util.NUTANIX_PLUGIN_ID {
- networkName = networkMapping.Network.ValueString()
- } else if resourcePool.ConnectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_AWS {
- networkName = fmt.Sprintf("%s (%s)", networkMapping.Network.ValueString(), resourcePool.GetResourcePoolRootId())
- }
- network := slices.IndexFunc(networks, func(c citrixorchestration.HypervisorResourceRefResponseModel) bool {
- return strings.EqualFold(c.GetName(), networkName)
- })
- if network == -1 {
- return res, fmt.Errorf("network %s not found", networkName)
- }
+ for _, networkMapping := range networkMappings {
+ var networkName string
+ if resourcePool.ConnectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_AZURE_RM ||
+ resourcePool.ConnectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_GOOGLE_CLOUD_PLATFORM ||
+ resourcePool.ConnectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_V_CENTER ||
+ resourcePool.ConnectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_XEN_SERVER ||
+ resourcePool.ConnectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_CUSTOM && hypervisorPluginId == util.NUTANIX_PLUGIN_ID {
+ networkName = networkMapping.Network.ValueString()
+ } else if resourcePool.ConnectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_AWS {
+ networkName = fmt.Sprintf("%s (%s)", networkMapping.Network.ValueString(), resourcePool.GetResourcePoolRootId())
+ }
+ network := slices.IndexFunc(networks, func(c citrixorchestration.HypervisorResourceRefResponseModel) bool {
+ return strings.EqualFold(c.GetName(), networkName)
+ })
+ if network == -1 {
+ return res, fmt.Errorf("network %s not found", networkName)
+ }
- networkMapRequestModel := citrixorchestration.NetworkMapRequestModel{
- NetworkDeviceNameOrId: *citrixorchestration.NewNullableString(networkMapping.NetworkDevice.ValueStringPointer()),
- NetworkPath: networks[network].GetXDPath(),
- }
+ networkMapRequestModel := citrixorchestration.NetworkMapRequestModel{
+ NetworkDeviceNameOrId: *citrixorchestration.NewNullableString(networkMapping.NetworkDevice.ValueStringPointer()),
+ NetworkPath: networks[network].GetXDPath(),
+ }
- if resourcePool.GetConnectionType() == citrixorchestration.HYPERVISORCONNECTIONTYPE_V_CENTER || (resourcePool.GetConnectionType() == citrixorchestration.HYPERVISORCONNECTIONTYPE_CUSTOM && hypervisorPluginId == util.NUTANIX_PLUGIN_ID) {
- networkMapRequestModel.SetDeviceNameOrId(networks[network].GetId())
+ if resourcePool.GetConnectionType() == citrixorchestration.HYPERVISORCONNECTIONTYPE_V_CENTER || (resourcePool.GetConnectionType() == citrixorchestration.HYPERVISORCONNECTIONTYPE_CUSTOM && hypervisorPluginId == util.NUTANIX_PLUGIN_ID) {
+ networkMapRequestModel.SetDeviceNameOrId(networks[network].GetId())
+ }
+
+ res = append(res, networkMapRequestModel)
}
- res = append(res, networkMapRequestModel)
return res, nil
}
@@ -1196,3 +1178,40 @@ func getOnPremImagePath(ctx context.Context, client *citrixdaasclient.CitrixDaas
return imagePath, nil
}
+
+func handleMachineProfileForAzureMcsCatalog(ctx context.Context, client *citrixdaasclient.CitrixDaasClient, diag *diag.Diagnostics, hypervisorName, resourcePoolName string, machineProfile AzureMachineProfileModel, action string) (string, error) {
+ machineProfileResourceGroup := machineProfile.MachineProfileResourceGroup.ValueString()
+ machineProfileVmOrTemplateSpecVersion := machineProfile.MachineProfileVmName.ValueString()
+ resourceType := util.VirtualMachineResourceType
+ queryPath := fmt.Sprintf("machineprofile.folder\\%s.resourcegroup", machineProfileResourceGroup)
+ errorMessage := fmt.Sprintf("Failed to locate machine profile vm %s on Azure", machineProfile.MachineProfileVmName.ValueString())
+ isUsingTemplateSpec := false
+ if machineProfile.MachineProfileVmName.IsNull() {
+ isUsingTemplateSpec = true
+ machineProfileVmOrTemplateSpecVersion = machineProfile.MachineProfileTemplateSpecVersion.ValueString()
+ queryPath = fmt.Sprintf("%s\\%s.templatespec", queryPath, machineProfile.MachineProfileTemplateSpecName.ValueString())
+ resourceType = ""
+ errorMessage = fmt.Sprintf("Failed to locate machine profile template spec %s with version %s on Azure", machineProfile.MachineProfileTemplateSpecName.ValueString(), machineProfile.MachineProfileTemplateSpecVersion.ValueString())
+ }
+ machineProfileResource, err := util.GetSingleResourceFromHypervisor(ctx, client, hypervisorName, resourcePoolName, queryPath, machineProfileVmOrTemplateSpecVersion, resourceType, "")
+ if err != nil {
+ diag.AddError(
+ fmt.Sprintf("Error %s Machine Catalog", action),
+ fmt.Sprintf("%s, error: %s", errorMessage, err.Error()),
+ )
+ return "", err
+ }
+ if isUsingTemplateSpec {
+ // validate the template spec
+ isValid, errorMsg := util.ValidateHypervisorResource(ctx, client, hypervisorName, resourcePoolName, machineProfileResource.GetRelativePath())
+ if !isValid {
+ diag.AddError(
+ fmt.Sprintf("Error %s Machine Catalog", action),
+ fmt.Sprintf("Failed to validate template spec %s with version %s, %s", machineProfile.MachineProfileTemplateSpecName.ValueString(), machineProfileVmOrTemplateSpecVersion, errorMsg),
+ )
+ return "", fmt.Errorf("failed to validate template spec %s with version %s, %s", machineProfile.MachineProfileTemplateSpecName.ValueString(), machineProfileVmOrTemplateSpecVersion, errorMsg)
+ }
+ }
+
+ return machineProfileResource.GetXDPath(), nil
+}
diff --git a/internal/daas/machine_catalog/machine_catalog_resource.go b/internal/daas/machine_catalog/machine_catalog_resource.go
index daa42b8..80c43b0 100644
--- a/internal/daas/machine_catalog/machine_catalog_resource.go
+++ b/internal/daas/machine_catalog/machine_catalog_resource.go
@@ -591,7 +591,7 @@ func (r *machineCatalogResource) ValidateConfig(ctx context.Context, req resourc
resp.Diagnostics.AddAttributeError(
path.Root("custom_properties"),
"Duplicated Custom Property",
- fmt.Sprintf("Use Terraform field \"%s\" for customer property \"%s\".", val, propertyName),
+ fmt.Sprintf("Use Terraform field \"%s\" for custom property \"%s\".", val, propertyName),
)
}
}
diff --git a/internal/daas/machine_catalog/machine_catalog_resource_model.go b/internal/daas/machine_catalog/machine_catalog_resource_model.go
index a4c5ed7..1919f7e 100644
--- a/internal/daas/machine_catalog/machine_catalog_resource_model.go
+++ b/internal/daas/machine_catalog/machine_catalog_resource_model.go
@@ -5,9 +5,12 @@ package machine_catalog
import (
"context"
"reflect"
+ "regexp"
+ "strings"
citrixorchestration "github.com/citrix/citrix-daas-rest-go/citrixorchestration"
citrixclient "github.com/citrix/citrix-daas-rest-go/client"
+ "github.com/citrix/terraform-provider-citrix/internal/util"
"github.com/hashicorp/terraform-plugin-framework/types"
)
@@ -58,7 +61,7 @@ type ProvisioningSchemeModel struct {
XenserverMachineConfig *XenserverMachineConfigModel `tfsdk:"xenserver_machine_config"`
NutanixMachineConfigModel *NutanixMachineConfigModel `tfsdk:"nutanix_machine_config"`
NumTotalMachines types.Int64 `tfsdk:"number_of_total_machines"`
- NetworkMapping *NetworkMappingModel `tfsdk:"network_mapping"`
+ NetworkMapping []NetworkMappingModel `tfsdk:"network_mapping"`
AvailabilityZones types.String `tfsdk:"availability_zones"`
IdentityType types.String `tfsdk:"identity_type"`
MachineDomainIdentity *MachineDomainIdentityModel `tfsdk:"machine_domain_identity"`
@@ -146,3 +149,22 @@ func (r MachineCatalogResourceModel) RefreshPropertyValues(ctx context.Context,
return r
}
+
+func (networkMapping NetworkMappingModel) RefreshListItem(nic citrixorchestration.NetworkMapResponseModel) NetworkMappingModel {
+ networkMapping.NetworkDevice = types.StringValue(nic.GetDeviceId())
+ network := nic.GetNetwork()
+ segments := strings.Split(network.GetXDPath(), "\\")
+ lastIndex := len(segments)
+
+ networkName := (strings.Split(segments[lastIndex-1], "."))[0]
+ matchAws := regexp.MustCompile(util.AwsNetworkNameRegex)
+ if matchAws.MatchString(networkName) {
+ /* For AWS Network, the XDPath looks like:
+ * XDHyp:\\HostingUnits\\{resource pool}\\{availability zone}.availabilityzone\\{network ip}`/{prefix length} (vpc-{vpc-id}).network
+ * The Network property should be set to {network ip}/{prefix length}
+ */
+ networkName = strings.ReplaceAll(strings.Split((strings.Split(segments[lastIndex-1], ".network"))[0], " ")[0], "`/", "/")
+ }
+ networkMapping.Network = types.StringValue(networkName)
+ return networkMapping
+}
diff --git a/internal/daas/machine_catalog/machine_catalog_schema_utils.go b/internal/daas/machine_catalog/machine_catalog_schema_utils.go
index 635f20f..15ec158 100644
--- a/internal/daas/machine_catalog/machine_catalog_schema_utils.go
+++ b/internal/daas/machine_catalog/machine_catalog_schema_utils.go
@@ -3,6 +3,7 @@
package machine_catalog
import (
+ "context"
"regexp"
citrixorchestration "github.com/citrix/citrix-daas-rest-go/citrixorchestration"
@@ -197,7 +198,7 @@ func getSchemaForMachineCatalogResource() schema.Schema {
Computed: true,
Default: stringdefault.StaticString("L7_20"),
Validators: []validator.String{
- util.GetValidatorFromEnum(citrixorchestration.AllowedFunctionalLevelEnumValues),
+ stringvalidator.OneOfCaseInsensitive(util.GetAllowedFunctionalLevelValues()...),
},
},
"provisioning_scheme": schema.SingleNestedAttribute{
@@ -311,6 +312,15 @@ func getSchemaForMachineCatalogResource() schema.Schema {
util.AzureEphemeralOSDisk,
),
},
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplaceIf(
+ func(_ context.Context, req planmodifier.StringRequest, resp *stringplanmodifier.RequiresReplaceIfFuncResponse) {
+ resp.RequiresReplace = req.StateValue.ValueString() == util.AzureEphemeralOSDisk || req.PlanValue.ValueString() == util.AzureEphemeralOSDisk
+ },
+ "Updating storage_type is not allowed when using Azure Ephemeral OS Disk.",
+ "Updating storage_type is not allowed when using Azure Ephemeral OS Disk.",
+ ),
+ },
},
"use_azure_compute_gallery": schema.SingleNestedAttribute{
Description: "Use this to place prepared image in Azure Compute Gallery. Required when `storage_type = Azure_Ephemeral_OS_Disk`.",
@@ -375,19 +385,49 @@ func getSchemaForMachineCatalogResource() schema.Schema {
},
},
"machine_profile": schema.SingleNestedAttribute{
- Description: "The name of the virtual machine template that will be used to identify the default value for the tags, virtual machine size, boot diagnostics, host cache property of OS disk, accelerated networking and availability zone." + "
" +
+ Description: "The name of the virtual machine or template spec that will be used to identify the default value for the tags, virtual machine size, boot diagnostics, host cache property of OS disk, accelerated networking and availability zone." + "
" +
"Required when identity_type is set to `AzureAD`",
Optional: true,
Attributes: map[string]schema.Attribute{
"machine_profile_vm_name": schema.StringAttribute{
Description: "The name of the machine profile virtual machine.",
- Required: true,
+ Optional: true,
+ },
+ "machine_profile_template_spec_name": schema.StringAttribute{
+ Description: "The name of the machine profile template spec.",
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.AlsoRequires(path.Expressions{
+ path.MatchRelative().AtParent().AtName("machine_profile_template_spec_version"),
+ }...),
+ stringvalidator.ExactlyOneOf(path.Expressions{
+ path.MatchRelative().AtParent().AtName("machine_profile_vm_name"),
+ }...),
+ },
+ },
+ "machine_profile_template_spec_version": schema.StringAttribute{
+ Description: "The version of the machine profile template spec.",
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.AlsoRequires(path.Expressions{
+ path.MatchRelative().AtParent().AtName("machine_profile_template_spec_name"),
+ }...),
+ },
},
"machine_profile_resource_group": schema.StringAttribute{
- Description: "The resource group name where machine profile VM is located in.",
+ Description: "The name of the resource group where the machine profile VM or template spec is located.",
Required: true,
},
},
+ PlanModifiers: []planmodifier.Object{
+ objectplanmodifier.RequiresReplaceIf(
+ func(_ context.Context, req planmodifier.ObjectRequest, resp *objectplanmodifier.RequiresReplaceIfFuncResponse) {
+ resp.RequiresReplace = req.ConfigValue.IsNull() != req.StateValue.IsNull()
+ },
+ "Force replace when machine_profile is added or removed. Update is allowed only if previously set.",
+ "Force replace when machine_profile is added or removed. Update is allowed only if previously set.",
+ ),
+ },
},
"writeback_cache": schema.SingleNestedAttribute{
Description: "Write-back Cache config. Leave this empty to disable Write-back Cache. Write-back Cache requires Machine image with Write-back Cache plugin installed.",
@@ -730,28 +770,30 @@ func getSchemaForMachineCatalogResource() schema.Schema {
int64validator.AtLeast(0),
},
},
- "network_mapping": schema.SingleNestedAttribute{
+ "network_mapping": schema.ListNestedAttribute{
Description: "Specifies how the attached NICs are mapped to networks. If this parameter is omitted, provisioned VMs are created with a single NIC, which is mapped to the default network in the hypervisor resource pool. If this parameter is supplied, machines are created with the number of NICs specified in the map, and each NIC is attached to the specified network." + "
" +
"Required when `provisioning_scheme.identity_type` is `AzureAD`.",
Optional: true,
- Attributes: map[string]schema.Attribute{
- "network_device": schema.StringAttribute{
- Description: "Name or Id of the network device.",
- Required: true,
- Validators: []validator.String{
- stringvalidator.AlsoRequires(path.Expressions{
- path.MatchRelative().AtParent().AtName("network"),
- }...),
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "network_device": schema.StringAttribute{
+ Description: "Name or Id of the network device.",
+ Required: true,
+ Validators: []validator.String{
+ stringvalidator.AlsoRequires(path.Expressions{
+ path.MatchRelative().AtParent().AtName("network"),
+ }...),
+ },
},
- },
- "network": schema.StringAttribute{
- Description: "The name of the virtual network that the device should be attached to. This must be a subnet within a Virtual Private Cloud item in the resource pool to which the Machine Catalog is associated." + "
" +
- "For AWS, please specify the network mask of the network you want to use within the VPC.",
- Required: true,
- Validators: []validator.String{
- stringvalidator.AlsoRequires(path.Expressions{
- path.MatchRelative().AtParent().AtName("network_device"),
- }...),
+ "network": schema.StringAttribute{
+ Description: "The name of the virtual network that the device should be attached to. This must be a subnet within a Virtual Private Cloud item in the resource pool to which the Machine Catalog is associated." + "
" +
+ "For AWS, please specify the network mask of the network you want to use within the VPC.",
+ Required: true,
+ Validators: []validator.String{
+ stringvalidator.AlsoRequires(path.Expressions{
+ path.MatchRelative().AtParent().AtName("network_device"),
+ }...),
+ },
},
},
},
diff --git a/internal/daas/machine_catalog/machine_config.go b/internal/daas/machine_catalog/machine_config.go
index 1b3089d..678d313 100644
--- a/internal/daas/machine_catalog/machine_config.go
+++ b/internal/daas/machine_catalog/machine_config.go
@@ -87,8 +87,10 @@ type AzureMasterImageModel struct {
}
type AzureMachineProfileModel struct {
- MachineProfileVmName types.String `tfsdk:"machine_profile_vm_name"`
- MachineProfileResourceGroup types.String `tfsdk:"machine_profile_resource_group"`
+ MachineProfileVmName types.String `tfsdk:"machine_profile_vm_name"`
+ MachineProfileTemplateSpecName types.String `tfsdk:"machine_profile_template_spec_name"`
+ MachineProfileTemplateSpecVersion types.String `tfsdk:"machine_profile_template_spec_version"`
+ MachineProfileResourceGroup types.String `tfsdk:"machine_profile_resource_group"`
}
// WritebackCacheModel maps the write back cacheconfiguration schema data.
@@ -286,6 +288,10 @@ func (mc *AzureMachineConfigModel) RefreshProperties(catalog citrixorchestration
replicaMaximum, _ := strconv.Atoi(stringPair.GetValue())
mc.UseAzureComputeGallery.ReplicaMaximum = types.Int64Value(int64(replicaMaximum))
}
+ case "UseEphemeralOsDisk":
+ if strings.EqualFold(stringPair.GetValue(), "true") {
+ mc.StorageType = types.StringValue(util.AzureEphemeralOSDisk)
+ }
default:
}
}
@@ -463,13 +469,31 @@ func (mc *NutanixMachineConfigModel) RefreshProperties(catalog citrixorchestrati
func parseAzureMachineProfileResponseToModel(machineProfileResponse citrixorchestration.HypervisorResourceRefResponseModel) *AzureMachineProfileModel {
machineProfileModel := AzureMachineProfileModel{}
if machineProfileName := machineProfileResponse.GetName(); machineProfileName != "" {
- machineProfileModel.MachineProfileVmName = types.StringValue(machineProfileName)
machineProfileSegments := strings.Split(machineProfileResponse.GetXDPath(), "\\")
lastIndex := len(machineProfileSegments) - 1
- machineProfileParent := machineProfileSegments[lastIndex-1]
- machineProfileParentType := strings.Split(machineProfileParent, ".")[1]
- if machineProfileParentType == "resourcegroup" {
- machineProfileModel.MachineProfileResourceGroup = types.StringValue(strings.Split(machineProfileParent, ".")[0])
+ resourceType := strings.Split(machineProfileSegments[lastIndex], ".")[1]
+ if strings.EqualFold(resourceType, "templatespecversion") {
+ machineProfileModel.MachineProfileTemplateSpecVersion = types.StringValue(machineProfileName)
+
+ templateSpecIndex := slices.IndexFunc(machineProfileSegments, func(machineProfileSegment string) bool {
+ return strings.Contains(machineProfileSegment, ".templatespec")
+ })
+
+ if templateSpecIndex != -1 {
+ templateSpec := strings.Split(machineProfileSegments[templateSpecIndex], ".")[0]
+ machineProfileModel.MachineProfileTemplateSpecName = types.StringValue(templateSpec)
+ }
+ } else {
+ machineProfileModel.MachineProfileVmName = types.StringValue(machineProfileName)
+ }
+
+ resourceGroupIndex := slices.IndexFunc(machineProfileSegments, func(machineProfileSegment string) bool {
+ return strings.Contains(machineProfileSegment, ".resourcegroup")
+ })
+
+ if resourceGroupIndex != -1 {
+ resourceGroup := strings.Split(machineProfileSegments[resourceGroupIndex], ".")[0]
+ machineProfileModel.MachineProfileResourceGroup = types.StringValue(resourceGroup)
}
} else {
machineProfileModel.MachineProfileVmName = types.StringNull()
diff --git a/internal/daas/policies/policy_set_resource.go b/internal/daas/policies/policy_set_resource.go
index 2de8c93..480c0c2 100644
--- a/internal/daas/policies/policy_set_resource.go
+++ b/internal/daas/policies/policy_set_resource.go
@@ -79,6 +79,12 @@ func (r *policySetResource) ModifyPlan(ctx context.Context, req resource.ModifyP
serverValue = fmt.Sprintf("%s.xendesktop.net", r.client.ClientConfig.CustomerId)
}
+ // Validate DDC Version
+ isDdcVersionSupported := util.CheckProductVersion(r.client, &resp.Diagnostics, 118, 7, 41, "policy set")
+ if !isDdcVersionSupported {
+ return
+ }
+
allScopeContained := false
for _, scope := range plan.Scopes {
if strings.EqualFold(scope.ValueString(), "All") {
diff --git a/internal/daas/resource_locations/resource_locations_resource.go b/internal/daas/resource_locations/resource_locations_resource.go
new file mode 100644
index 0000000..045e767
--- /dev/null
+++ b/internal/daas/resource_locations/resource_locations_resource.go
@@ -0,0 +1,282 @@
+// Copyright © 2023. Citrix Systems, Inc.
+
+package resource_locations
+
+import (
+ "context"
+
+ resourcelocations "github.com/citrix/citrix-daas-rest-go/ccresourcelocations"
+ citrixdaasclient "github.com/citrix/citrix-daas-rest-go/client"
+ "github.com/citrix/terraform-provider-citrix/internal/util"
+
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/resource"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+)
+
+// Ensure the implementation satisfies the expected interfaces.
+var (
+ _ resource.Resource = &resourceLocationResource{}
+ _ resource.ResourceWithConfigure = &resourceLocationResource{}
+ _ resource.ResourceWithImportState = &resourceLocationResource{}
+ _ resource.ResourceWithModifyPlan = &resourceLocationResource{}
+)
+
+// NewResourceLocationResource is a helper function to simplify the provider implementation.
+func NewResourceLocationResource() resource.Resource {
+ return &resourceLocationResource{}
+}
+
+// resourceLocationResource is the resource implementation.
+type resourceLocationResource struct {
+ client *citrixdaasclient.CitrixDaasClient
+}
+
+// Metadata returns the resource type name.
+func (r *resourceLocationResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_resource_location"
+}
+
+// Schema defines the schema for the resource.
+func (r *resourceLocationResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ // This description is used by the documentation generator and the language server.
+ Description: "Manages a Citrix Cloud resource location.",
+
+ Attributes: map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ Description: "ID of the resource location.",
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "name": schema.StringAttribute{
+ Description: "Name of the resource location.",
+ Required: true,
+ },
+ "internal_only": schema.BoolAttribute{
+ Description: "Flag to determine if the resource location can only be used internally. Defaults to `false`.",
+ Computed: true,
+ Optional: true,
+ Default: booldefault.StaticBool(false),
+ },
+ "time_zone": schema.StringAttribute{
+ Description: "Timezone associated with the resource location. Please refer to the `Timezone` column in the following [table](https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/default-time-zones?view=windows-11#time-zones) for allowed values.",
+ Computed: true,
+ Optional: true,
+ Default: stringdefault.StaticString("GMT Standard Time"),
+ },
+ },
+ }
+}
+
+// Configure adds the provider configured client to the resource.
+func (r *resourceLocationResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ r.client = req.ProviderData.(*citrixdaasclient.CitrixDaasClient)
+}
+
+// Create creates the resource and sets the initial Terraform state.
+func (r *resourceLocationResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Retrieve values from plan
+ var plan ResourceLocationResourceModel
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Create resource location
+ var body resourcelocations.CitrixCloudServicesRegistryApiModelsLocationsResourceLocationModel
+ body.SetName(plan.Name.ValueString())
+ body.SetInternalOnly(plan.InternalOnly.ValueBool())
+ body.SetTimeZone(plan.TimeZone.ValueString())
+
+ createResourceLocationRequest := r.client.ResourceLocationsClient.LocationsDAAS.LocationsCreate(ctx)
+ createResourceLocationRequest = createResourceLocationRequest.Model(body)
+
+ // Create resource location
+ resourceLocation, httpResp, err := citrixdaasclient.AddRequestData(createResourceLocationRequest, r.client).Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error creating resource location",
+ "TransactionId: "+citrixdaasclient.GetTransactionIdFromHttpResponse(httpResp)+
+ "\nError message: "+util.ReadClientError(err),
+ )
+ return
+ }
+
+ resourceLocationId := resourceLocation.GetId()
+
+ // Get resource location from remote using id
+ resourceLocation, err = getResourceLocation(ctx, r.client, &resp.Diagnostics, resourceLocationId)
+ if err != nil {
+ return
+ }
+
+ // Map response body to schema and populate computed attribute values
+ plan = plan.RefreshPropertyValues(resourceLocation)
+
+ // Set state to fully populated data
+ diags = resp.State.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Read refreshes the Terraform state with the latest data.
+func (r *resourceLocationResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Get current state
+ var state ResourceLocationResourceModel
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Get resource location from remote using id
+ resourceLocation, err := readResourceLocation(ctx, r.client, resp, state.Id.ValueString())
+ if err != nil {
+ return
+ }
+
+ state = state.RefreshPropertyValues(resourceLocation)
+
+ // Set refreshed state
+ diags = resp.State.Set(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+}
+
+// Update updates the resource and sets the updated Terraform state on success.
+func (r *resourceLocationResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Retrieve values from plan
+ var plan ResourceLocationResourceModel
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ var body resourcelocations.CitrixCloudServicesRegistryApiModelsLocationsResourceLocationUpdateModel
+ body.SetName(plan.Name.ValueString())
+ body.SetInternalOnly(plan.InternalOnly.ValueBool())
+ body.SetTimeZone(plan.TimeZone.ValueString())
+
+ updateResourceLocationRequest := r.client.ResourceLocationsClient.LocationsDAAS.LocationsUpdate(ctx, plan.Id.ValueString())
+ updateResourceLocationRequest = updateResourceLocationRequest.Model(body)
+
+ // Update resource location
+ _, httpResp, err := citrixdaasclient.AddRequestData(updateResourceLocationRequest, r.client).Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error updating resource location with id: "+plan.Id.ValueString(),
+ "TransactionId: "+citrixdaasclient.GetTransactionIdFromHttpResponse(httpResp)+
+ "\nError message: "+util.ReadClientError(err),
+ )
+ return
+ }
+
+ // Get resource location from remote using id
+ updatedResourceLocation, err := getResourceLocation(ctx, r.client, &resp.Diagnostics, plan.Id.ValueString())
+ if err != nil {
+ return
+ }
+
+ // Map response body to schema and populate computed attribute values
+ plan = plan.RefreshPropertyValues(updatedResourceLocation)
+
+ diags = resp.State.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Delete deletes the resource and removes the Terraform state on success.
+func (r *resourceLocationResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Retrieve values from state
+ var state ResourceLocationResourceModel
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ deleteResourceLocationRequest := r.client.ResourceLocationsClient.LocationsDAAS.LocationsDelete(ctx, state.Id.ValueString())
+ httpResp, err := citrixdaasclient.AddRequestData(deleteResourceLocationRequest, r.client).Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error deleting resource location with id: "+state.Id.ValueString(),
+ "TransactionId: "+citrixdaasclient.GetTransactionIdFromHttpResponse(httpResp)+
+ "\nError message: "+util.ReadClientError(err),
+ )
+ return
+ }
+}
+
+func (r *resourceLocationResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ // Retrieve import ID and save to id attribute
+ resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
+}
+
+func getResourceLocation(ctx context.Context, client *citrixdaasclient.CitrixDaasClient, diagnostics *diag.Diagnostics, resourceLocationId string) (*resourcelocations.CitrixCloudServicesRegistryApiModelsLocationsResourceLocationModel, error) {
+ // Get resource location
+ getResourceLocationRequest := client.ResourceLocationsClient.LocationsDAAS.LocationsGet(ctx, resourceLocationId)
+ resourceLocation, httpResp, err := citrixdaasclient.ExecuteWithRetry[*resourcelocations.CitrixCloudServicesRegistryApiModelsLocationsResourceLocationModel](getResourceLocationRequest, client)
+ if err != nil {
+ diagnostics.AddError(
+ "Error reading resource location with id: "+resourceLocationId,
+ "TransactionId: "+citrixdaasclient.GetTransactionIdFromHttpResponse(httpResp)+
+ "\nError message: "+util.ReadClientError(err),
+ )
+ }
+
+ return resourceLocation, err
+}
+
+func readResourceLocation(ctx context.Context, client *citrixdaasclient.CitrixDaasClient, resp *resource.ReadResponse, resourceLocationId string) (*resourcelocations.CitrixCloudServicesRegistryApiModelsLocationsResourceLocationModel, error) {
+ getResourceLocationRequest := client.ResourceLocationsClient.LocationsDAAS.LocationsGet(ctx, resourceLocationId)
+ resourceLocation, _, err := util.ReadResource[*resourcelocations.CitrixCloudServicesRegistryApiModelsLocationsResourceLocationModel](getResourceLocationRequest, ctx, client, resp, "Resource Location", resourceLocationId)
+ return resourceLocation, err
+}
+
+// Resource Location is a cloud concept which is not supported for on-prem environment
+func (r *resourceLocationResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ if r.client.AuthConfig.OnPremises {
+ resp.Diagnostics.AddError("Error managing resource location", "Resource locations are only supported for Cloud customers. On-premises customers can use the Zone resource directly.")
+ }
+
+ // Retrieve values from plan
+ if !req.Plan.Raw.IsNull() {
+ var plan ResourceLocationResourceModel
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+ }
+}
diff --git a/internal/daas/resource_locations/resource_locations_resource_model.go b/internal/daas/resource_locations/resource_locations_resource_model.go
new file mode 100644
index 0000000..734ae6c
--- /dev/null
+++ b/internal/daas/resource_locations/resource_locations_resource_model.go
@@ -0,0 +1,28 @@
+// Copyright © 2023. Citrix Systems, Inc.
+
+package resource_locations
+
+import (
+ ccresourcelocations "github.com/citrix/citrix-daas-rest-go/ccresourcelocations"
+
+ "github.com/hashicorp/terraform-plugin-framework/types"
+)
+
+// ResourceLocationResourceModel maps the resource schema data.
+type ResourceLocationResourceModel struct {
+ Id types.String `tfsdk:"id"`
+ Name types.String `tfsdk:"name"`
+ InternalOnly types.Bool `tfsdk:"internal_only"`
+ TimeZone types.String `tfsdk:"time_zone"`
+}
+
+func (r ResourceLocationResourceModel) RefreshPropertyValues(ccResourceLocation *ccresourcelocations.CitrixCloudServicesRegistryApiModelsLocationsResourceLocationModel) ResourceLocationResourceModel {
+
+ // Overwrite resource location with refreshed state
+ r.Id = types.StringValue(ccResourceLocation.GetId())
+ r.Name = types.StringValue(ccResourceLocation.GetName())
+ r.InternalOnly = types.BoolValue(ccResourceLocation.GetInternalOnly())
+ r.TimeZone = types.StringValue(ccResourceLocation.GetTimeZone())
+
+ return r
+}
diff --git a/internal/daas/storefront_server/storefront_server_resource.go b/internal/daas/storefront_server/storefront_server_resource.go
new file mode 100644
index 0000000..bd1146f
--- /dev/null
+++ b/internal/daas/storefront_server/storefront_server_resource.go
@@ -0,0 +1,296 @@
+// Copyright © 2023. Citrix Systems, Inc.
+
+package storefront_server
+
+import (
+ "context"
+ "net/http"
+
+ citrixorchestration "github.com/citrix/citrix-daas-rest-go/citrixorchestration"
+ citrixdaasclient "github.com/citrix/citrix-daas-rest-go/client"
+ "github.com/citrix/terraform-provider-citrix/internal/util"
+
+ "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/resource"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/schema/validator"
+)
+
+// Ensure the implementation satisfies the expected interfaces.
+var (
+ _ resource.Resource = &storeFrontServerResource{}
+ _ resource.ResourceWithConfigure = &storeFrontServerResource{}
+ _ resource.ResourceWithImportState = &storeFrontServerResource{}
+)
+
+// NewStoreFrontServerResource is a helper function to simplify the provider implementation.
+func NewStoreFrontServerResource() resource.Resource {
+ return &storeFrontServerResource{}
+}
+
+// storeFrontServerResource is the resource implementation.
+type storeFrontServerResource struct {
+ client *citrixdaasclient.CitrixDaasClient
+}
+
+// Metadata returns the resource type name.
+func (r *storeFrontServerResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_storefront_server"
+}
+
+// Schema defines the schema for the resource.
+func (r *storeFrontServerResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ Description: "Manages a StoreFront server.",
+ Attributes: map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ Description: "GUID identifier of the StoreFront server.",
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "name": schema.StringAttribute{
+ Description: "Name of the StoreFront server.",
+ Required: true,
+ },
+ "description": schema.StringAttribute{
+ Description: "Description of the StoreFront server.",
+ Required: true,
+ Validators: []validator.String{
+ stringvalidator.LengthAtLeast(1),
+ },
+ },
+ "url": schema.StringAttribute{
+ Description: "URL for connecting to the StoreFront server.",
+ Required: true,
+ },
+ "enabled": schema.BoolAttribute{
+ Description: "Indicates if the StoreFront server is enabled.",
+ Required: true,
+ },
+ },
+ }
+}
+
+// Configure adds the provider configured client to the resource.
+func (r *storeFrontServerResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ r.client = req.ProviderData.(*citrixdaasclient.CitrixDaasClient)
+}
+
+// Create creates the resource and sets the initial Terraform state.
+func (r *storeFrontServerResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Retrieve values from plan
+ var plan StoreFrontServerResourceModel
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Generate API request body from plan
+ var body citrixorchestration.StoreFrontServerRequestModel
+ body.SetName(plan.Name.ValueString())
+ body.SetDescription(plan.Description.ValueString())
+ body.SetUrl(plan.Url.ValueString())
+ body.SetEnabled(plan.Enabled.ValueBool())
+
+ createStoreFrontServerRequest := r.client.ApiClient.StoreFrontServersAPIsDAAS.StoreFrontServersCreateStoreFrontServer(ctx)
+ createStoreFrontServerRequest = createStoreFrontServerRequest.StoreFrontServerRequestModel(body).Async(true)
+
+ // Create new StoreFront server
+ _, httpResp, err := citrixdaasclient.AddRequestData(createStoreFrontServerRequest, r.client).Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error creating StoreFront Server "+plan.Name.ValueString(),
+ "TransactionId: "+citrixdaasclient.GetTransactionIdFromHttpResponse(httpResp)+
+ "\nError message: "+util.ReadClientError(err),
+ )
+ return
+ }
+
+ err = util.ProcessAsyncJobResponse(ctx, r.client, httpResp, "Error creating StoreFront Server "+plan.Name.ValueString(), &resp.Diagnostics, 10, true)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error creating StoreFront Server "+plan.Name.ValueString(),
+ "TransactionId: "+citrixdaasclient.GetTransactionIdFromHttpResponse(httpResp)+
+ "\nError message: "+util.ReadClientError(err),
+ )
+ return
+ }
+
+ // Try getting the new StoreFront server with StoreFront server name
+ sfserver, _, err := getStoreFrontServer(ctx, r.client, plan.Name.ValueString())
+ if err != nil {
+ return
+ }
+
+ // Map response body to schema and populate Computed attribute values
+ plan = plan.RefreshPropertyValues(sfserver)
+
+ // Set state to fully populated data
+ diags = resp.State.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Read refreshes the Terraform state with the latest data.
+func (r *storeFrontServerResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Get current state
+ var state StoreFrontServerResourceModel
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ sfServerId := state.Id.ValueString()
+
+ // Get refreshed StoreFront server properties from Orchestration
+ sfServer, httpResp, err := getStoreFrontServer(ctx, r.client, sfServerId)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error reading Machine Catalog "+sfServerId,
+ "TransactionId: "+citrixdaasclient.GetTransactionIdFromHttpResponse(httpResp)+
+ "\nError message: "+util.ReadClientError(err),
+ )
+
+ return
+ }
+
+ state = state.RefreshPropertyValues(sfServer)
+
+ // Set refreshed state
+ diags = resp.State.Set(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Update updates the resource and sets the updated Terraform state on success.
+func (r *storeFrontServerResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Retrieve values from plan
+ var plan StoreFrontServerResourceModel
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ var state StoreFrontServerResourceModel
+ diags = req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Get refreshed StoreFront server properties from Orchestration
+ sfServerId := state.Id.ValueString()
+ sfServerName := state.Name.ValueString()
+
+ // Construct the update model
+ var editStoreFrontServerRequestBody = &citrixorchestration.StoreFrontServerRequestModel{}
+ editStoreFrontServerRequestBody.SetName(plan.Name.ValueString())
+ editStoreFrontServerRequestBody.SetDescription(plan.Description.ValueString())
+ editStoreFrontServerRequestBody.SetUrl(plan.Url.ValueString())
+ editStoreFrontServerRequestBody.SetEnabled(plan.Enabled.ValueBool())
+
+ // Update StoreFront server
+ editStoreFronteServerRequest := r.client.ApiClient.StoreFrontServersAPIsDAAS.StoreFrontServersUpdateStoreFrontServer(ctx, sfServerId)
+ editStoreFronteServerRequest = editStoreFronteServerRequest.StoreFrontServerRequestModel(*editStoreFrontServerRequestBody).Async(true)
+ _, httpResp, err := citrixdaasclient.AddRequestData(editStoreFronteServerRequest, r.client).Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error updating StoreFront Server "+sfServerName,
+ "TransactionId: "+citrixdaasclient.GetTransactionIdFromHttpResponse(httpResp)+
+ "\nError message: "+util.ReadClientError(err),
+ )
+ return
+ }
+
+ err = util.ProcessAsyncJobResponse(ctx, r.client, httpResp, "Error updating StoreFront Server "+sfServerName, &resp.Diagnostics, 10, true)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error updating StoreFront Server "+sfServerName,
+ "TransactionId: "+citrixdaasclient.GetTransactionIdFromHttpResponse(httpResp)+
+ "\nError message: "+util.ReadClientError(err),
+ )
+ return
+ }
+
+ // Fetch updated StoreFront server from getStoreFrontServer.
+ updatedStoreFrontServer, _, err := getStoreFrontServer(ctx, r.client, sfServerId)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error reading updated StoreFront Server "+sfServerName,
+ "TransactionId: "+citrixdaasclient.GetTransactionIdFromHttpResponse(httpResp)+
+ "\nError message: "+util.ReadClientError(err),
+ )
+ return
+ }
+
+ // Update resource state with updated property values
+ plan = plan.RefreshPropertyValues(updatedStoreFrontServer)
+
+ diags = resp.State.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Delete deletes the resource and removes the Terraform state on success.
+func (r *storeFrontServerResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Retrieve values from state
+ var state StoreFrontServerResourceModel
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Delete existing StoreFront server
+ sfServerId := state.Id.ValueString()
+ sfServerName := state.Name.ValueString()
+ deleteStoreFrontServerRequest := r.client.ApiClient.StoreFrontServersAPIsDAAS.StoreFrontServersDeleteStoreFrontServer(ctx, sfServerId)
+ httpResp, err := citrixdaasclient.AddRequestData(deleteStoreFrontServerRequest, r.client).Execute()
+ if err != nil && httpResp.StatusCode != http.StatusNotFound {
+ resp.Diagnostics.AddError(
+ "Error deleting StoreFront Server "+sfServerName,
+ "TransactionId: "+citrixdaasclient.GetTransactionIdFromHttpResponse(httpResp)+
+ "\nError message: "+util.ReadClientError(err),
+ )
+ return
+ }
+}
+
+func (r *storeFrontServerResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ // Retrieve import ID and save to id attribute
+ resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
+}
+
+// Gets the StoreFront server and logs any errors
+func getStoreFrontServer(ctx context.Context, client *citrixdaasclient.CitrixDaasClient, storeFrontServerId string) (*citrixorchestration.StoreFrontServerResponseModel, *http.Response, error) {
+ getStoreFrontRequest := client.ApiClient.StoreFrontServersAPIsDAAS.StoreFrontServersGetStoreFrontServer(ctx, storeFrontServerId)
+ sfServer, httpResp, err := citrixdaasclient.ExecuteWithRetry[*citrixorchestration.StoreFrontServerResponseModel](getStoreFrontRequest, client)
+
+ return sfServer, httpResp, err
+}
diff --git a/internal/daas/storefront_server/storefront_server_resource_model.go b/internal/daas/storefront_server/storefront_server_resource_model.go
new file mode 100644
index 0000000..5002366
--- /dev/null
+++ b/internal/daas/storefront_server/storefront_server_resource_model.go
@@ -0,0 +1,35 @@
+// Copyright © 2023. Citrix Systems, Inc.
+
+package storefront_server
+
+import (
+ citrixorchestration "github.com/citrix/citrix-daas-rest-go/citrixorchestration"
+
+ "github.com/hashicorp/terraform-plugin-framework/types"
+)
+
+// StoreFrontServerResourceModel maps the resource schema data.
+type StoreFrontServerResourceModel struct {
+ Id types.String `tfsdk:"id"`
+ Name types.String `tfsdk:"name"`
+ Description types.String `tfsdk:"description"`
+ Url types.String `tfsdk:"url"`
+ Enabled types.Bool `tfsdk:"enabled"`
+}
+
+func (r StoreFrontServerResourceModel) RefreshPropertyValues(sfServer *citrixorchestration.StoreFrontServerResponseModel) StoreFrontServerResourceModel {
+ // Overwrite StoreFront server with refreshed state
+ r.Id = types.StringValue(sfServer.GetId())
+ r.Name = types.StringValue(sfServer.GetName())
+ r.Description = types.StringValue(sfServer.GetDescription())
+ r.Enabled = types.BoolValue(sfServer.GetEnabled())
+
+ remoteUrl := sfServer.GetUrl()
+ planUrl := r.Url.ValueString()
+ if remoteUrl[len(remoteUrl)-1] == '/' && (len(planUrl) == 0 || planUrl[len(planUrl)-1] != '/') {
+ remoteUrl = remoteUrl[:len(remoteUrl)-1]
+ }
+ r.Url = types.StringValue(remoteUrl)
+
+ return r
+}
diff --git a/internal/daas/vda/vda_data_source.go b/internal/daas/vda/vda_data_source.go
index bbae55d..a18c15b 100644
--- a/internal/daas/vda/vda_data_source.go
+++ b/internal/daas/vda/vda_data_source.go
@@ -88,6 +88,8 @@ func (d *VdaDataSource) Configure(ctx context.Context, req datasource.ConfigureR
}
func (d *VdaDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
var data VdaDataSourceModel
// Read Terraform configuration data into the model
diff --git a/internal/examples/resources/citrix_gac_settings/import.sh b/internal/examples/resources/citrix_gac_settings/import.sh
new file mode 100644
index 0000000..ad7660d
--- /dev/null
+++ b/internal/examples/resources/citrix_gac_settings/import.sh
@@ -0,0 +1,2 @@
+# Global App Configuration settings can be imported by specifying the service url
+terraform import citrix_gac_settings.test_gac_settings https://example.com:443
\ No newline at end of file
diff --git a/internal/examples/resources/citrix_gac_settings/resource.tf b/internal/examples/resources/citrix_gac_settings/resource.tf
new file mode 100644
index 0000000..ac07adc
--- /dev/null
+++ b/internal/examples/resources/citrix_gac_settings/resource.tf
@@ -0,0 +1,76 @@
+// Currently, only settings objects with value type of integer, boolean, strings and list of strings is supported.
+resource "citrix_gac_settings" "test_settings_configuration" {
+ service_url = "https://:443"
+ name = "test-settings"
+ description = "Test settings configuration"
+ app_settings = {
+ windows = [
+ {
+ user_override = false,
+ category = "ICA Client",
+ settings = [
+ {
+ name = "Allow Client Clipboard Redirection",
+ value_string = "true"
+ }
+ ]
+ },
+ {
+ user_override = false,
+ category = "Browser",
+ settings = [
+ {
+ name = "delete browsing data on exit",
+ value_list = [
+ "browsing_history",
+ "download_history"
+ ]
+ },
+ {
+ name = "relaunch notification period",
+ value_string = "3600000"
+ }
+ ]
+ }
+ ],
+ html5 = [
+ {
+ category = "Virtual Channel",
+ user_override = false,
+ settings = [
+ {
+ name = "Clipboard Operations Between VDA And Local Device",
+ value_string = "true"
+ }
+ ]
+ }
+ ],
+ ios = [
+ {
+ category = "Audio",
+ user_override = false,
+ settings = [
+ {
+ name = "audio",
+ value_string = "true"
+ }
+ ]
+ }
+ ],
+ macos = [
+ {
+ category = "ica client",
+ user_override = false,
+ settings = [
+ {
+ name = "Reconnect Apps and Desktops",
+ value_list = [
+ "startWorkspace",
+ "refreshApps"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/internal/examples/resources/citrix_machine_catalog/resource.tf b/internal/examples/resources/citrix_machine_catalog/resource.tf
index c654da0..acf196d 100644
--- a/internal/examples/resources/citrix_machine_catalog/resource.tf
+++ b/internal/examples/resources/citrix_machine_catalog/resource.tf
@@ -38,10 +38,12 @@ resource "citrix_machine_catalog" "example-azure-mtsession" {
storage_cost_saving = true
}
}
- network_mapping = {
- network_device = "0"
- network = ""
- }
+ network_mapping = [
+ {
+ network_device = "0"
+ network = ""
+ }
+ ]
availability_zones = "1,2,..."
number_of_total_machines = 1
machine_account_creation_rules ={
@@ -79,10 +81,12 @@ resource "citrix_machine_catalog" "example-aws-mtsession" {
]
tenancy_type = "Shared"
}
- network_mapping = {
- network_device = "0"
- network = "10.0.128.0/20"
- }
+ network_mapping = [
+ {
+ network_device = "0"
+ network = "10.0.128.0/20"
+ }
+ ]
number_of_total_machines = 1
machine_account_creation_rules ={
naming_scheme = "aws-multi-##"
@@ -315,10 +319,12 @@ resource "citrix_machine_catalog" "example-non-domain-joined-azure-mcs" {
storage_type = "Standard_LRS"
use_managed_disks = true
service_offering = "Standard_D2_v2"
- resource_group = ""
- storage_account = ""
- container = ""
- master_image = ""
+ azure_master_image = {
+ resource_group = ""
+ storage_account = ""
+ container = ""
+ master_image = ""
+ }
writeback_cache = {
wbc_disk_storage_type = "pd-standard"
persist_wbc = true
diff --git a/internal/examples/resources/citrix_resource_location/import.sh b/internal/examples/resources/citrix_resource_location/import.sh
new file mode 100644
index 0000000..7015bcc
--- /dev/null
+++ b/internal/examples/resources/citrix_resource_location/import.sh
@@ -0,0 +1,2 @@
+# Resource Location can be imported by specifying the resource location GUID
+terraform import citrix_resource_location.test_resource_location 00000000-0000-0000-0000-000000000000
\ No newline at end of file
diff --git a/internal/examples/resources/citrix_resource_location/resource.tf b/internal/examples/resources/citrix_resource_location/resource.tf
new file mode 100644
index 0000000..e5996a6
--- /dev/null
+++ b/internal/examples/resources/citrix_resource_location/resource.tf
@@ -0,0 +1,3 @@
+resource "citrix_resource_location" "example-resource-location" {
+ name = "example-resource-location"
+}
\ No newline at end of file
diff --git a/internal/examples/resources/citrix_stf_authentication_service/import.sh b/internal/examples/resources/citrix_stf_authentication_service/import.sh
new file mode 100644
index 0000000..7653ad6
--- /dev/null
+++ b/internal/examples/resources/citrix_stf_authentication_service/import.sh
@@ -0,0 +1,2 @@
+# StoreFront Authentication Service can be imported with the IIS Site Id and Virtual Path
+terraform import citrix_stf_deployment.example-stf-deployment 1,"/Citrix/Auth"
diff --git a/internal/examples/resources/citrix_stf_authentication_service/resource.tf b/internal/examples/resources/citrix_stf_authentication_service/resource.tf
new file mode 100644
index 0000000..51d1298
--- /dev/null
+++ b/internal/examples/resources/citrix_stf_authentication_service/resource.tf
@@ -0,0 +1,5 @@
+resource "citrix_stf_authentication_service" "example-stf-authentication-service" {
+ site_id = "1"
+ friendly_name = "Example STF Authentication Service"
+ virtual_path = "/Citrix/Authentication"
+}
\ No newline at end of file
diff --git a/internal/examples/resources/citrix_stf_deployment/import.sh b/internal/examples/resources/citrix_stf_deployment/import.sh
new file mode 100644
index 0000000..0a1b679
--- /dev/null
+++ b/internal/examples/resources/citrix_stf_deployment/import.sh
@@ -0,0 +1,2 @@
+# StoreFront Deployment can be imported with the IIS Site ID
+terraform import citrix_stf_deployment.example-stf-deployment "1"
\ No newline at end of file
diff --git a/internal/examples/resources/citrix_stf_deployment/resource.tf b/internal/examples/resources/citrix_stf_deployment/resource.tf
new file mode 100644
index 0000000..da27858
--- /dev/null
+++ b/internal/examples/resources/citrix_stf_deployment/resource.tf
@@ -0,0 +1,4 @@
+resource "citrix_stf_deployment" "example-stf-deployment" {
+ site_id = "1"
+ host_base_url = "https://example.com"
+}
\ No newline at end of file
diff --git a/internal/examples/resources/citrix_stf_store_service/import.sh b/internal/examples/resources/citrix_stf_store_service/import.sh
new file mode 100644
index 0000000..df2ee88
--- /dev/null
+++ b/internal/examples/resources/citrix_stf_store_service/import.sh
@@ -0,0 +1,2 @@
+# StoreFront Store Service can be imported with the IIS Site Id and Virtual Path
+terraform import citrix_stf_store_service.example-stf-store-service 1,"/Citrix/Store"
\ No newline at end of file
diff --git a/internal/examples/resources/citrix_stf_store_service/resource.tf b/internal/examples/resources/citrix_stf_store_service/resource.tf
new file mode 100644
index 0000000..1ef1ea2
--- /dev/null
+++ b/internal/examples/resources/citrix_stf_store_service/resource.tf
@@ -0,0 +1,19 @@
+resource "citrix_stf_storeservice" "example-stf-store-service" {
+ site_id = "1"
+ virtual_path = "/Citrix/Store"
+ friendly_name = "Store"
+ authentication_service = "${citrix_stf_authentication_service.example-stf-authentication-service.virtual_path}"
+ farm_config = {
+ farm_name = "Controller"
+ farm_type = "XenDesktop"
+ servers = ["cvad.storefront.com", "cvad.storefront2.com"]
+ }
+}
+
+// Anonymous Authentication Service
+resource "citrix_stf_store_service" "example-stf-store-service" {
+ site_id = "1"
+ virtual_path = "/Citrix/Store"
+ friedly_name = "Store"
+ anonymous = true
+}
\ No newline at end of file
diff --git a/internal/examples/resources/citrix_stf_webreceiver_service/import.sh b/internal/examples/resources/citrix_stf_webreceiver_service/import.sh
new file mode 100644
index 0000000..f096b69
--- /dev/null
+++ b/internal/examples/resources/citrix_stf_webreceiver_service/import.sh
@@ -0,0 +1,2 @@
+# StoreFront Webreceiver Service can be imported with the IIS Virtual Path
+terraform import citrix_stf_webreceiver_service.example-stf-webreceiver-service 1,"/Citrix/StoreWeb"
\ No newline at end of file
diff --git a/internal/examples/resources/citrix_stf_webreceiver_service/resource.tf b/internal/examples/resources/citrix_stf_webreceiver_service/resource.tf
new file mode 100644
index 0000000..2bfdfac
--- /dev/null
+++ b/internal/examples/resources/citrix_stf_webreceiver_service/resource.tf
@@ -0,0 +1,16 @@
+resource "citrix_stf_webreceiver_service" "example-stf-webreceiver-service"{
+ site_id = "citrix_stf_deployment.testSTFDeployment.site_id"
+ virtual_path = "/Citrix/StoreWeb"
+ friendly_name = "Receiver"
+ store_service = "${citrix_stf_store_service.example-stf-store-service.virtual_path}"
+ authentication_methods = [
+ "ExplicitForms",
+ "CitrixAGBasic"
+ ]
+ plugin_assistant = {
+ enabled = true
+ html5_single_tab_launch = true
+ upgrade_at_login = true
+ html5_enabled = "Fallback"
+ }
+}
diff --git a/internal/examples/resources/citrix_storefront_server/import.sh b/internal/examples/resources/citrix_storefront_server/import.sh
new file mode 100644
index 0000000..3a06a20
--- /dev/null
+++ b/internal/examples/resources/citrix_storefront_server/import.sh
@@ -0,0 +1,2 @@
+# StoreFront Server can be imported by specifying the GUID
+terraform import citrix_storefront_server.example-storefront-server f60476fd-360d-4d35-861d-da8404652b166
\ No newline at end of file
diff --git a/internal/examples/resources/citrix_storefront_server/resource.tf b/internal/examples/resources/citrix_storefront_server/resource.tf
new file mode 100644
index 0000000..f08b9e0
--- /dev/null
+++ b/internal/examples/resources/citrix_storefront_server/resource.tf
@@ -0,0 +1,6 @@
+resource "citrix_storefront_server" "example-storefront_server" {
+ name = "example-storefront-server"
+ description = "StoreFront server example"
+ url = "https://storefront.example.com/citrix/store"
+ enabled = true
+}
\ No newline at end of file
diff --git a/internal/provider/provider.go b/internal/provider/provider.go
index 90be1c8..5011464 100644
--- a/internal/provider/provider.go
+++ b/internal/provider/provider.go
@@ -22,7 +22,14 @@ import (
"github.com/citrix/terraform-provider-citrix/internal/daas/admin_role"
"github.com/citrix/terraform-provider-citrix/internal/daas/admin_user"
"github.com/citrix/terraform-provider-citrix/internal/daas/application"
+ "github.com/citrix/terraform-provider-citrix/internal/daas/gac_settings"
+ "github.com/citrix/terraform-provider-citrix/internal/daas/resource_locations"
+ "github.com/citrix/terraform-provider-citrix/internal/daas/storefront_server"
"github.com/citrix/terraform-provider-citrix/internal/daas/vda"
+ "github.com/citrix/terraform-provider-citrix/internal/storefront/stf_authentication"
+ "github.com/citrix/terraform-provider-citrix/internal/storefront/stf_deployment"
+ "github.com/citrix/terraform-provider-citrix/internal/storefront/stf_store"
+ "github.com/citrix/terraform-provider-citrix/internal/storefront/stf_webreceiver"
"github.com/citrix/terraform-provider-citrix/internal/daas/admin_scope"
"github.com/citrix/terraform-provider-citrix/internal/daas/delivery_group"
@@ -71,12 +78,19 @@ type citrixProvider struct {
// citrixProviderModel maps provider schema data to a Go type.
type citrixProviderModel struct {
- Hostname types.String `tfsdk:"hostname"`
- Environment types.String `tfsdk:"environment"`
- CustomerId types.String `tfsdk:"customer_id"`
- ClientId types.String `tfsdk:"client_id"`
- ClientSecret types.String `tfsdk:"client_secret"`
- DisableSslVerification types.Bool `tfsdk:"disable_ssl_verification"`
+ Hostname types.String `tfsdk:"hostname"`
+ Environment types.String `tfsdk:"environment"`
+ CustomerId types.String `tfsdk:"customer_id"`
+ ClientId types.String `tfsdk:"client_id"`
+ ClientSecret types.String `tfsdk:"client_secret"`
+ DisableSslVerification types.Bool `tfsdk:"disable_ssl_verification"`
+ StoreFrontRemoteHost *storefrontConfig `tfsdk:"storefront_remote_host"`
+}
+
+type storefrontConfig struct {
+ ComputerName types.String `tfsdk:"computer_name"`
+ ADadminUserName types.String `tfsdk:"ad_admin_username"`
+ AdAdminPassword types.String `tfsdk:"ad_admin_password"`
}
// Metadata returns the provider type name.
@@ -140,6 +154,31 @@ func (p *citrixProvider) Schema(_ context.Context, _ provider.SchemaRequest, res
"Can be set via Environment Variable **CITRIX_DISABLE_SSL_VERIFICATION**.",
Optional: true,
},
+ "storefront_remote_host": schema.SingleNestedAttribute{
+ Description: "StoreFront Remote Host for Citrix DaaS service. " + "
" +
+ "Only applicable for Citrix on-premises StoreFront. Use this to specify StoreFront Remote Host. " + "
",
+ Optional: true,
+ Attributes: map[string]schema.Attribute{
+ "computer_name": schema.StringAttribute{
+ Required: true,
+ Description: "StoreFront server computer Name " + "
" +
+ "Only applicable for Citrix on-premises customers. Use this to specify StoreFront server computer name " + "
" +
+ "Can be set via Environment Variable **SF_COMPUTER_NAME**.",
+ },
+ "ad_admin_username": schema.StringAttribute{
+ Description: "Active Directory Admin Username to connect to storefront server " + "
" +
+ "Only applicable for Citrix on-premises customers. Use this to specify AD admin username " + "
" +
+ "Can be set via Environment Variable **SF_AD_ADMAIN_USERNAME**.",
+ Required: true,
+ },
+ "ad_admin_password": schema.StringAttribute{
+ Description: "Active Directory Admin Password to connect to storefront server " + "
" +
+ "Only applicable for Citrix on-premises customers. Use this to specify AD admin password" + "
" +
+ "Can be set via Environment Variable **SF_AD_ADMAIN_PASSWORD**.",
+ Required: true,
+ },
+ },
+ },
},
}
}
@@ -311,6 +350,9 @@ func (p *citrixProvider) Configure(ctx context.Context, req provider.ConfigureRe
clientId := os.Getenv("CITRIX_CLIENT_ID")
clientSecret := os.Getenv("CITRIX_CLIENT_SECRET")
disableSslVerification := strings.EqualFold(os.Getenv("CITRIX_DISABLE_SSL_VERIFICATION"), "true")
+ storefront_computer_name := os.Getenv("SF_COMPUTER_NAME")
+ storefront_ad_admin_username := os.Getenv("SF_AD_ADMAIN_USERNAME")
+ storefront_ad_admin_password := os.Getenv("SF_AD_ADMAIN_PASSWORD")
if !config.Hostname.IsNull() {
hostname = config.Hostname.ValueString()
@@ -336,6 +378,18 @@ func (p *citrixProvider) Configure(ctx context.Context, req provider.ConfigureRe
disableSslVerification = config.DisableSslVerification.ValueBool()
}
+ if config.StoreFrontRemoteHost != nil {
+ if !config.StoreFrontRemoteHost.ComputerName.IsNull() {
+ storefront_computer_name = config.StoreFrontRemoteHost.ComputerName.ValueString()
+ }
+ if !config.StoreFrontRemoteHost.ADadminUserName.IsNull() {
+ storefront_ad_admin_username = config.StoreFrontRemoteHost.ADadminUserName.ValueString()
+ }
+ if !config.StoreFrontRemoteHost.AdAdminPassword.IsNull() {
+ storefront_ad_admin_password = config.StoreFrontRemoteHost.AdAdminPassword.ValueString()
+ }
+ }
+
if environment == "" {
environment = "Production" // default to production
}
@@ -395,22 +449,30 @@ func (p *citrixProvider) Configure(ctx context.Context, req provider.ConfigureRe
// Indicate whether Citrix Cloud requests should go through API Gateway
apiGateway := true
+ ccUrl := ""
if !onPremises {
+ if environment == "Production" {
+ ccUrl = "api.cloud.com"
+ } else if environment == "Staging" {
+ ccUrl = "api.cloudburrito.com"
+ } else if environment == "Japan" {
+ ccUrl = "api.citrixcloud.jp"
+ } else if environment == "JapanStaging" {
+ ccUrl = "api.citrixcloudstaging.jp"
+ } else if environment == "Gov" {
+ ccUrl = fmt.Sprintf("registry.citrixworkspacesapi.us/%s", customerId)
+ } else if environment == "GovStaging" {
+ ccUrl = fmt.Sprintf("registry.ctxwsstgapi.us/%s", customerId)
+ }
if hostname == "" {
- if environment == "Production" {
- hostname = "api.cloud.com"
- } else if environment == "Staging" {
- hostname = "api.cloudburrito.com"
- } else if environment == "Japan" {
- hostname = "api.citrixcloud.jp"
- } else if environment == "JapanStaging" {
- hostname = "api.citrixcloudstaging.jp"
- } else if environment == "Gov" {
+ if environment == "Gov" {
hostname = fmt.Sprintf("%s.xendesktop.us", customerId)
apiGateway = false
} else if environment == "GovStaging" {
hostname = fmt.Sprintf("%s.xdstaging.us", customerId)
apiGateway = false
+ } else {
+ hostname = ccUrl
}
} else if !strings.HasPrefix(hostname, "api.") {
// When a cloud customer sets explicit hostname to the cloud DDC, bypass API Gateway
@@ -455,7 +517,7 @@ func (p *citrixProvider) Configure(ctx context.Context, req provider.ConfigureRe
userAgent := "citrix-terraform-provider/" + p.version + " (https://github.com/citrix/terraform-provider-citrix)"
// Create a new Citrix API client using the configuration values
- client, httpResp, err := citrixclient.NewCitrixDaasClient(ctx, authUrl, hostname, customerId, clientId, clientSecret, onPremises, apiGateway, isGov, disableSslVerification, &userAgent, middlewareAuthFunc)
+ client, httpResp, err := citrixclient.NewCitrixDaasClient(ctx, authUrl, ccUrl, hostname, customerId, clientId, clientSecret, onPremises, apiGateway, isGov, disableSslVerification, &userAgent, middlewareAuthFunc)
if err != nil {
if httpResp != nil {
if httpResp.StatusCode == 401 {
@@ -530,6 +592,9 @@ func (p *citrixProvider) Configure(ctx context.Context, req provider.ConfigureRe
return
}
+ //Set Storefront Client
+ client = citrixclient.NewStoreFrontClient(ctx, storefront_computer_name, storefront_ad_admin_username, storefront_ad_admin_password, client)
+
// Make the Citrix API client available during DataSource and Resource
// type Configure methods.
resp.DataSourceData = client
@@ -564,12 +629,20 @@ func (p *citrixProvider) Resources(_ context.Context) []func() resource.Resource
hypervisor_resource_pool.NewNutanixHypervisorResourcePoolResource,
machine_catalog.NewMachineCatalogResource,
delivery_group.NewDeliveryGroupResource,
+ storefront_server.NewStoreFrontServerResource,
application.NewApplicationResource,
application.NewApplicationFolderResource,
admin_scope.NewAdminScopeResource,
admin_role.NewAdminRoleResource,
policies.NewPolicySetResource,
admin_user.NewAdminUserResource,
- //Add resource here
+ gac_settings.NewAGacSettingsResource,
+ resource_locations.NewResourceLocationResource,
+ // StoreFront Resources
+ stf_deployment.NewSTFDeploymentResource,
+ stf_authentication.NewSTFAuthenticationServiceResource,
+ stf_store.NewSTFStoreServiceResource,
+ stf_webreceiver.NewSTFWebReceiverResource,
+ // Add resource here
}
}
diff --git a/internal/storefront/stf_authentication/stf_authentication_service_resource.go b/internal/storefront/stf_authentication/stf_authentication_service_resource.go
new file mode 100644
index 0000000..1013dc5
--- /dev/null
+++ b/internal/storefront/stf_authentication/stf_authentication_service_resource.go
@@ -0,0 +1,365 @@
+// Copyright © 2023. Citrix Systems, Inc.
+
+package stf_authentication
+
+import (
+ "context"
+ "fmt"
+ "strconv"
+ "strings"
+
+ citrixstorefront "github.com/citrix/citrix-daas-rest-go/citrixstorefront/models"
+ citrixdaasclient "github.com/citrix/citrix-daas-rest-go/client"
+ "github.com/citrix/terraform-provider-citrix/internal/util"
+
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/resource"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+)
+
+// Ensure the implementation satisfies the expected interfaces.
+var (
+ _ resource.Resource = &stfAuthenticationServiceResource{}
+ _ resource.ResourceWithConfigure = &stfAuthenticationServiceResource{}
+ _ resource.ResourceWithImportState = &stfAuthenticationServiceResource{}
+)
+
+// NewSTFAuthenticationServiceResource is a helper function to simplify the provider implementation.
+func NewSTFAuthenticationServiceResource() resource.Resource {
+ return &stfAuthenticationServiceResource{}
+}
+
+// stfAuthenticationServiceResource is the resource implementation.
+type stfAuthenticationServiceResource struct {
+ client *citrixdaasclient.CitrixDaasClient
+}
+
+// Metadata returns the resource type name.
+func (r *stfAuthenticationServiceResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_stf_authentication_service"
+}
+
+// Schema defines the schema for the resource.
+func (r *stfAuthenticationServiceResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ Description: "Storefront Authentication Service.",
+ Attributes: map[string]schema.Attribute{
+ "site_id": schema.StringAttribute{
+ Description: "The IIS site to configure the authentication service for. Defaults to `1`.",
+ Optional: true,
+ Computed: true,
+ Default: stringdefault.StaticString("1"),
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "virtual_path": schema.StringAttribute{
+ Description: "The IIS virtual path to use for the authentication service. Defaults to `/Citrix/Authentication`.",
+ Optional: true,
+ Computed: true,
+ Default: stringdefault.StaticString("/Citrix/Authentication"),
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "friendly_name": schema.StringAttribute{
+ Description: "The friendly name the authentication service should be known as. Defaults to `Authentication Service`.",
+ Optional: true,
+ Computed: true,
+ Default: stringdefault.StaticString("Authentication Service"),
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ },
+ }
+}
+
+// Configure adds the provider configured client to the resource.
+func (r *stfAuthenticationServiceResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ r.client = req.ProviderData.(*citrixdaasclient.CitrixDaasClient)
+}
+
+// Create implements resource.Resource.
+func (r *stfAuthenticationServiceResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Retrieve values from plan
+ var plan STFAuthenticationServiceResourceModel
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Generate API request body from plan
+ var body citrixstorefront.AddSTFAuthenticationServiceRequestModel
+
+ siteIdInt, err := strconv.ParseInt(plan.SiteId.ValueString(), 10, 64)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error updating Storefront Authentication Service ",
+ "\nError message: "+err.Error(),
+ )
+ return
+ }
+
+ body.SetSiteId(siteIdInt)
+ body.SetVirtualPath(plan.VirtualPath.ValueString())
+ body.SetFriendlyName(plan.FriendlyName.ValueString())
+
+ addAuthenticationServiceRequest := r.client.StorefrontClient.AuthenticationServiceSF.STFAuthenticationCreateSTFAuthenticationService(ctx, body)
+
+ // Create new STF Deployment
+ authenticationServiceDetail, err := addAuthenticationServiceRequest.Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error adding Storefront Authentication Service",
+ fmt.Sprintf("Error Message: %s", err.Error()),
+ )
+ return
+ }
+
+ // Map response body to schema and populate Computed attribute values
+ plan.RefreshPropertyValues(&authenticationServiceDetail)
+
+ // Set state to fully populated data
+ diags = resp.State.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Read implements resource.Resource.
+func (r *stfAuthenticationServiceResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Get current state
+ var state STFAuthenticationServiceResourceModel
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ STFAuthenticationService, err := getSTFAuthenticationService(ctx, r.client, &resp.Diagnostics, state)
+ if err != nil {
+ return
+ }
+
+ if STFAuthenticationService == nil {
+ resp.Diagnostics.AddWarning(
+ "Authentication Service not found",
+ "Authentication Service was not found and will be removed from the state file. An apply action will result in the creation of a new resource.",
+ )
+ resp.State.RemoveResource(ctx)
+ return
+ }
+
+ state.RefreshPropertyValues(STFAuthenticationService)
+
+ // Set refreshed state
+ diags = resp.State.Set(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Update implements resource.Resource.
+func (r *stfAuthenticationServiceResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Retrieve values from plan
+ var plan STFAuthenticationServiceResourceModel
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Get current state
+ var state STFAuthenticationServiceResourceModel
+ diags = req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ var getBody citrixstorefront.GetSTFAuthenticationServiceRequestModel
+ if !state.SiteId.IsNull() {
+ siteIdInt, err := strconv.ParseInt(state.SiteId.ValueString(), 10, 64)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error updating Storefront Authentication Service ",
+ "\nError message: "+err.Error(),
+ )
+ return
+ }
+ getBody.SetSiteId(siteIdInt)
+ }
+ if state.VirtualPath.ValueString() != "" {
+ getBody.SetVirtualPath(state.VirtualPath.ValueString())
+ }
+
+ // Remove existing STF Authentication Service
+ removeAuthenticationServiceRequest := r.client.StorefrontClient.AuthenticationServiceSF.STFAuthenticationRemoveSTFAuthenticationService(ctx, getBody)
+ err := removeAuthenticationServiceRequest.Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error updating Storefront Authentication Service ",
+ "\nError message: "+err.Error(),
+ )
+ return
+ }
+
+ // Add updated STF Authentication Service
+ var createBody citrixstorefront.AddSTFAuthenticationServiceRequestModel
+
+ siteIdInt, err := strconv.ParseInt(plan.SiteId.ValueString(), 10, 64)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error updating Storefront Authentication Service ",
+ "\nError message: "+err.Error(),
+ )
+ return
+ }
+
+ createBody.SetSiteId(siteIdInt)
+ createBody.SetVirtualPath(plan.VirtualPath.ValueString())
+ createBody.SetFriendlyName(plan.FriendlyName.ValueString())
+
+ addAuthenticationServiceRequest := r.client.StorefrontClient.AuthenticationServiceSF.STFAuthenticationCreateSTFAuthenticationService(ctx, createBody)
+
+ authenticationServiceDetail, err := addAuthenticationServiceRequest.Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error adding Storefront Authentication Service",
+ fmt.Sprintf("Error Message: %s", err.Error()),
+ )
+ return
+ }
+
+ // Map response body to schema and populate Computed attribute values
+ plan.RefreshPropertyValues(&authenticationServiceDetail)
+
+ // Set refreshed state
+ diags = resp.State.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Delete implements resource.Resource.
+func (r *stfAuthenticationServiceResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Get current state
+ var state STFAuthenticationServiceResourceModel
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ var getBody citrixstorefront.GetSTFAuthenticationServiceRequestModel
+ if !state.SiteId.IsNull() {
+ siteIdInt, err := strconv.ParseInt(state.SiteId.ValueString(), 10, 64)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error removing Storefront Authentication Service ",
+ "\nError message: "+err.Error(),
+ )
+ return
+ }
+ getBody.SetSiteId(siteIdInt)
+ }
+ if state.VirtualPath.ValueString() != "" {
+ getBody.SetVirtualPath(state.VirtualPath.ValueString())
+ }
+
+ // Remove STF Authentication Service
+ removeAuthenticationServiceRequest := r.client.StorefrontClient.AuthenticationServiceSF.STFAuthenticationRemoveSTFAuthenticationService(ctx, getBody)
+ err := removeAuthenticationServiceRequest.Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error removing Storefront Authentication Service ",
+ "\nError message: "+err.Error(),
+ )
+ return
+ }
+}
+
+// ImportState implements resource.ResourceWithImportState.
+func (r *stfAuthenticationServiceResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ idSegments := strings.SplitN(req.ID, ",", 2)
+
+ if (len(idSegments) != 2) || (idSegments[0] == "" || idSegments[1] == "") {
+ resp.Diagnostics.AddError(
+ "Invalid Import Identifier",
+ fmt.Sprintf("Expected format: `site_id,virtual_path`, got: %q", req.ID),
+ )
+ return
+ }
+
+ _, err := strconv.Atoi(idSegments[0])
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Invalid Site ID in Import Identifier",
+ fmt.Sprintf("Site ID should be an integer, got: %q", idSegments[0]),
+ )
+ return
+ }
+
+ // Retrieve import ID and save to id attribute
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("site_id"), idSegments[0])...)
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("virtual_path"), idSegments[1])...)
+}
+
+// Gets the getSTFAuthenticationService and logs any errors
+func getSTFAuthenticationService(ctx context.Context, client *citrixdaasclient.CitrixDaasClient, diagnostics *diag.Diagnostics, state STFAuthenticationServiceResourceModel) (*citrixstorefront.STFAuthenticationServiceResponseModel, error) {
+ var body citrixstorefront.GetSTFAuthenticationServiceRequestModel
+ if state.SiteId.ValueString() != "" {
+ siteIdInt, err := strconv.ParseInt(state.SiteId.ValueString(), 10, 64)
+ if err != nil {
+ diagnostics.AddError(
+ "Error fetching state of Storefront Authentication Service ",
+ "Error message: "+err.Error(),
+ )
+ return nil, err
+ }
+ body.SetSiteId(siteIdInt)
+ }
+
+ if state.VirtualPath.ValueString() != "" {
+ body.SetVirtualPath(state.VirtualPath.ValueString())
+ }
+
+ getSTFAuthenticationServiceRequest := client.StorefrontClient.AuthenticationServiceSF.STFAuthenticationGetSTFAuthenticationService(ctx, body)
+
+ // Get refreshed STFAuthenticationService properties from Orchestration
+ STFAuthenticationService, err := getSTFAuthenticationServiceRequest.Execute()
+ if err != nil {
+ if strings.EqualFold(err.Error(), util.NOT_EXIST) {
+ return nil, nil
+ }
+ diagnostics.AddError(
+ "Error fetching state of Storefront Authentication Service ",
+ "Error message: "+err.Error(),
+ )
+ return &STFAuthenticationService, err
+ }
+ return &STFAuthenticationService, nil
+}
diff --git a/internal/storefront/stf_authentication/stf_authentication_service_resource_model.go b/internal/storefront/stf_authentication/stf_authentication_service_resource_model.go
new file mode 100644
index 0000000..aafdc33
--- /dev/null
+++ b/internal/storefront/stf_authentication/stf_authentication_service_resource_model.go
@@ -0,0 +1,26 @@
+// Copyright © 2023. Citrix Systems, Inc.
+
+package stf_authentication
+
+import (
+ citrixstorefront "github.com/citrix/citrix-daas-rest-go/citrixstorefront/models"
+
+ "github.com/hashicorp/terraform-plugin-framework/types"
+
+ "strconv"
+)
+
+// SFAuthenticationServiceResourceModel maps the resource schema data.
+
+type STFAuthenticationServiceResourceModel struct {
+ SiteId types.String `tfsdk:"site_id"`
+ VirtualPath types.String `tfsdk:"virtual_path"`
+ FriendlyName types.String `tfsdk:"friendly_name"`
+}
+
+func (r *STFAuthenticationServiceResourceModel) RefreshPropertyValues(authService *citrixstorefront.STFAuthenticationServiceResponseModel) {
+ // Overwrite SFDeploymentResourceModel with refreshed state
+ r.SiteId = types.StringValue(strconv.Itoa(*authService.SiteId.Get()))
+ r.VirtualPath = types.StringValue(*authService.VirtualPath.Get())
+ r.FriendlyName = types.StringValue(*authService.FriendlyName.Get())
+}
diff --git a/internal/storefront/stf_deployment/stf_deployment_resource.go b/internal/storefront/stf_deployment/stf_deployment_resource.go
new file mode 100644
index 0000000..458a4f1
--- /dev/null
+++ b/internal/storefront/stf_deployment/stf_deployment_resource.go
@@ -0,0 +1,272 @@
+// Copyright © 2023. Citrix Systems, Inc.
+package stf_deployment
+
+import (
+ "context"
+ "strconv"
+
+ citrixstorefront "github.com/citrix/citrix-daas-rest-go/citrixstorefront/models"
+ citrixdaasclient "github.com/citrix/citrix-daas-rest-go/client"
+ "github.com/citrix/terraform-provider-citrix/internal/util"
+
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/resource"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+)
+
+// Ensure the implementation satisfies the expected interfaces.
+var (
+ _ resource.Resource = &stfDeploymentResource{}
+ _ resource.ResourceWithConfigure = &stfDeploymentResource{}
+ _ resource.ResourceWithImportState = &stfDeploymentResource{}
+)
+
+// stfDeploymentResource is a helper function to simplify the provider implementation.
+func NewSTFDeploymentResource() resource.Resource {
+ return &stfDeploymentResource{}
+}
+
+// stfDeploymentResource is the resource implementation.
+type stfDeploymentResource struct {
+ client *citrixdaasclient.CitrixDaasClient
+}
+
+// Metadata returns the resource type name.
+func (r *stfDeploymentResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_stf_deployment"
+}
+
+// Schema defines the schema for the resource.
+func (r *stfDeploymentResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ Description: "Storefront Deployment.",
+ Attributes: map[string]schema.Attribute{
+ "site_id": schema.StringAttribute{
+ Description: "The IIS site id of the Storefront deployment. Defaults to 1.",
+ Optional: true,
+ Computed: true,
+ Default: stringdefault.StaticString("1"),
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "host_base_url": schema.StringAttribute{
+ Description: "Url used to access the StoreFront server group.",
+ Required: true,
+ },
+ },
+ }
+}
+
+// Configure adds the provider configured client to the resource.
+func (r *stfDeploymentResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ r.client = req.ProviderData.(*citrixdaasclient.CitrixDaasClient)
+}
+
+// Create creates the resource and sets the initial Terraform state.
+func (r *stfDeploymentResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Retrieve values from plan
+ var plan STFDeploymentResourceModel
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Generate API request body from plan
+ var body citrixstorefront.CreateSTFDeploymentRequestModel
+
+ siteIdInt, err := strconv.ParseInt(plan.SiteId.ValueString(), 10, 64)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error creating Storefront Deployment ",
+ "\nError message: "+err.Error(),
+ )
+ return
+ }
+
+ body.SetSiteId(siteIdInt)
+ body.SetHostBaseUrl(plan.HostBaseUrl.ValueString())
+
+ createDeploymentRequest := r.client.StorefrontClient.DeploymentSF.STFDeploymentCreateSTFDeployment(ctx, body)
+
+ // Create new STF Deployment
+ DeploymentDetail, err := createDeploymentRequest.Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error creating Storefront Deployment",
+ "TransactionId: ",
+ )
+ return
+ }
+
+ // Map response body to schema and populate Computed attribute values
+ plan.RefreshPropertyValues(&DeploymentDetail)
+
+ // Set state to fully populated data
+ diags = resp.State.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Read refreshes the Terraform state with the latest data.
+func (r *stfDeploymentResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Get current state
+ var state STFDeploymentResourceModel
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ STFDeployment, err := getSTFDeployment(ctx, r.client, &resp.Diagnostics, state.SiteId.ValueStringPointer())
+ if err != nil {
+ return
+ }
+ state.RefreshPropertyValues(STFDeployment)
+
+ // Set refreshed state
+ diags = resp.State.Set(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Update updates the resource and sets the updated Terraform state on success.
+func (r *stfDeploymentResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Retrieve values from plan
+ var plan STFDeploymentResourceModel
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Get refreshed STFDeployment
+ _, err := getSTFDeployment(ctx, r.client, &resp.Diagnostics, plan.SiteId.ValueStringPointer())
+ if err != nil {
+ return
+ }
+
+ // Construct the update model
+ var editSTFDeploymentBody = &citrixstorefront.SetSTFDeploymentRequestModel{}
+ editSTFDeploymentBody.SetHostBaseUrl(plan.HostBaseUrl.String())
+
+ siteIdInt, err := strconv.ParseInt(plan.SiteId.ValueString(), 10, 64)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error fetching state of Storefront Authentication Service ",
+ "Error message: "+err.Error(),
+ )
+ return
+ }
+ editSTFDeploymentBody.SetSiteId(siteIdInt)
+
+ // Update STFDeployment
+ editDeploymentRequest := r.client.StorefrontClient.DeploymentSF.STFDeploymentSetSTFDeployment(ctx, *editSTFDeploymentBody)
+ _, err = editDeploymentRequest.Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error updating Storefront Deployment ",
+ "\nError message: "+err.Error(),
+ )
+ }
+
+ // Fetch updated STFDeployment
+ updatedSTFDeployment, err := getSTFDeployment(ctx, r.client, &resp.Diagnostics, plan.SiteId.ValueStringPointer())
+ if err != nil {
+ return
+ }
+
+ // Update resource state with updated property values
+ plan.RefreshPropertyValues(updatedSTFDeployment)
+
+ diags = resp.State.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Delete deletes the resource and removes the Terraform state on success.
+func (r *stfDeploymentResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Retrieve values from state
+ var state STFDeploymentResourceModel
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ var body citrixstorefront.ClearSTFDeploymentRequestModel
+ if state.SiteId.ValueString() != "" {
+ siteIdInt, err := strconv.ParseInt(state.SiteId.ValueString(), 10, 64)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error deleting Storefront Deployment ",
+ "Error message: "+err.Error(),
+ )
+ return
+ }
+ body.SetSiteId(siteIdInt)
+ }
+
+ // Delete existing STF Deployment
+ deleteDeploymentRequest := r.client.StorefrontClient.DeploymentSF.STFDeploymentClearSTFDeployment(ctx, body)
+ _, err := deleteDeploymentRequest.Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error deleting Storefront Deployment ",
+ "\nError message: "+err.Error(),
+ )
+ return
+ }
+}
+
+func (r *stfDeploymentResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ // Retrieve import ID and save to id attribute
+ resource.ImportStatePassthroughID(ctx, path.Root("site_id"), req, resp)
+}
+
+// Gets the STFDeployment and logs any errors
+func getSTFDeployment(ctx context.Context, client *citrixdaasclient.CitrixDaasClient, diagnostics *diag.Diagnostics, siteId *string) (*citrixstorefront.STFDeploymentDetailModel, error) {
+ var body citrixstorefront.GetSTFDeploymentRequestModel
+ if siteId != nil {
+ siteIdInt, err := strconv.ParseInt(*siteId, 10, 64)
+ if err != nil {
+ diagnostics.AddError(
+ "Error fetching state of Storefront Deployment ",
+ "Error message: "+err.Error(),
+ )
+ return nil, err
+ }
+ body.SetSiteId(siteIdInt)
+ }
+ getSTFDeploymentRequest := client.StorefrontClient.DeploymentSF.STFDeploymentGetSTFDeployment(ctx, body)
+
+ // Get refreshed STFDeployment properties from Orchestration
+ STFDeployment, err := getSTFDeploymentRequest.Execute()
+ if err != nil {
+ return &STFDeployment, err
+ }
+ return &STFDeployment, nil
+}
diff --git a/internal/storefront/stf_deployment/stf_deployment_resource_model.go b/internal/storefront/stf_deployment/stf_deployment_resource_model.go
new file mode 100644
index 0000000..4fda333
--- /dev/null
+++ b/internal/storefront/stf_deployment/stf_deployment_resource_model.go
@@ -0,0 +1,25 @@
+// Copyright © 2023. Citrix Systems, Inc.
+
+package stf_deployment
+
+import (
+ "strconv"
+ "strings"
+
+ citrixstorefront "github.com/citrix/citrix-daas-rest-go/citrixstorefront/models"
+
+ "github.com/hashicorp/terraform-plugin-framework/types"
+)
+
+// SFDeploymentResourceModel maps the resource schema data.
+type STFDeploymentResourceModel struct {
+ SiteId types.String `tfsdk:"site_id"`
+ HostBaseUrl types.String `tfsdk:"host_base_url"`
+}
+
+func (r *STFDeploymentResourceModel) RefreshPropertyValues(deployment *citrixstorefront.STFDeploymentDetailModel) {
+ // Overwrite SFDeploymentResourceModel with refreshed state
+ r.SiteId = types.StringValue(strconv.Itoa(int(*deployment.SiteId.Get())))
+ r.HostBaseUrl = types.StringValue(strings.TrimRight(*deployment.HostBaseUrl.Get(), "/"))
+
+}
diff --git a/internal/storefront/stf_store/stf_store_service_resource.go b/internal/storefront/stf_store/stf_store_service_resource.go
new file mode 100644
index 0000000..dc71e55
--- /dev/null
+++ b/internal/storefront/stf_store/stf_store_service_resource.go
@@ -0,0 +1,362 @@
+// Copyright © 2023. Citrix Systems, Inc.
+package stf_store
+
+import (
+ "context"
+ "fmt"
+ "strconv"
+ "strings"
+
+ citrixstorefront "github.com/citrix/citrix-daas-rest-go/citrixstorefront/models"
+ citrixdaasclient "github.com/citrix/citrix-daas-rest-go/client"
+ "github.com/citrix/terraform-provider-citrix/internal/util"
+
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/resource"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+)
+
+// Ensure the implementation satisfies the expected interfaces.
+var (
+ _ resource.Resource = &stfStoreServiceResource{}
+ _ resource.ResourceWithConfigure = &stfStoreServiceResource{}
+ _ resource.ResourceWithImportState = &stfStoreServiceResource{}
+)
+
+// stfStoreServiceResource is a helper function to simplify the provider implementation.
+func NewSTFStoreServiceResource() resource.Resource {
+ return &stfStoreServiceResource{}
+}
+
+// stfStoreServiceResource is the resource implementation.
+type stfStoreServiceResource struct {
+ client *citrixdaasclient.CitrixDaasClient
+}
+
+// Metadata returns the resource type name.
+func (r *stfStoreServiceResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_stf_store_service"
+}
+
+// Schema defines the schema for the resource.
+func (r *stfStoreServiceResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ Description: "Storefront StoreService.",
+ Attributes: map[string]schema.Attribute{
+ "site_id": schema.StringAttribute{
+ Description: "The IIS site id of the Storefront storeservice. Defaults to 1.",
+ Optional: true,
+ Computed: true,
+ Default: stringdefault.StaticString("1"),
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "virtual_path": schema.StringAttribute{
+ Description: "The IIS VirtualPath at which the Store will be configured to be accessed by Receivers.",
+ Required: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "friendly_name": schema.StringAttribute{
+ Description: "The friendly name of the Store",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "authentication_service": schema.StringAttribute{
+ Description: "The StoreFront Authentication Service to use for authenticating users.",
+ Optional: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "anonymous": schema.BoolAttribute{
+ Description: "Whether the Store is anonymous. Anonymous Store not requiring authentication.",
+ Optional: true,
+ PlanModifiers: []planmodifier.Bool{
+ boolplanmodifier.RequiresReplace(),
+ },
+ },
+ "load_balance": schema.BoolAttribute{
+ Description: "Whether the Store is load balanced.",
+ Optional: true,
+ PlanModifiers: []planmodifier.Bool{
+ boolplanmodifier.RequiresReplace(),
+ },
+ },
+ "farm_config": schema.SingleNestedAttribute{
+ Description: "Farm configuration for the Store.",
+ Optional: true,
+ PlanModifiers: []planmodifier.Object{
+ objectplanmodifier.RequiresReplace(),
+ },
+ Attributes: map[string]schema.Attribute{
+ "farm_name": schema.StringAttribute{
+ Description: "The name of the Farm.",
+ Required: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "farm_type": schema.StringAttribute{
+ Description: "The type of the Farm.",
+ Required: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "servers": schema.ListAttribute{
+ ElementType: types.StringType,
+ Description: "The list of servers in the Farm.",
+ Required: true,
+ PlanModifiers: []planmodifier.List{
+ listplanmodifier.RequiresReplace(),
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
+// Configure adds the provider configured client to the resource.
+func (r *stfStoreServiceResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ r.client = req.ProviderData.(*citrixdaasclient.CitrixDaasClient)
+}
+
+// Create creates the resource and sets the initial Terraform state.
+func (r *stfStoreServiceResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Retrieve values from plan
+ var plan STFStoreServiceResourceModel
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Generate API request body from plan
+ var body citrixstorefront.CreateSTFStoreRequestModel
+
+ siteIdInt, err := strconv.ParseInt(plan.SiteId.ValueString(), 10, 64)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error creating Storefront StoreService ",
+ "\nError message: "+err.Error(),
+ )
+ return
+ }
+
+ body.SetSiteId(siteIdInt)
+ body.SetVirtualPath(plan.VirtualPath.String())
+ body.SetFriendlyName(plan.FriendlyName.ValueString())
+
+ if !plan.Anonymous.IsNull() && plan.Anonymous.ValueBool() {
+ body.SetAnonymous(true)
+ } else {
+ body.SetAuthenticationService("(Get-STFAuthenticationService -VirtualPath " + plan.AuthenticationService.ValueString() + " ) ")
+ }
+
+ if !plan.LoadBalance.IsNull() {
+ body.SetLoadBalance(plan.LoadBalance.ValueBool())
+ }
+
+ if plan.FarmConfig != nil {
+ body.SetFarmName(plan.FarmConfig.FarmName.ValueString())
+ body.SetFarmType(plan.FarmConfig.FarmType.ValueString())
+ body.SetServers(util.ConvertBaseStringArrayToPrimitiveStringArray(plan.FarmConfig.Servers))
+ }
+
+ createStoreServiceRequest := r.client.StorefrontClient.StoreSF.STFStoreCreateSTFStore(ctx, body)
+
+ // Create new STF StoreService
+ StoreServiceDetail, err := createStoreServiceRequest.Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error creating Storefront StoreService",
+ "TransactionId: ",
+ )
+ return
+ }
+
+ // Map response body to schema and populate Computed attribute values
+ plan.RefreshPropertyValues(&StoreServiceDetail)
+
+ // Set state to fully populated data
+ diags = resp.State.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Read refreshes the Terraform state with the latest data.
+func (r *stfStoreServiceResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Get current state
+ var state STFStoreServiceResourceModel
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ STFStoreService, err := getSTFStoreService(ctx, r.client, &resp.Diagnostics, state.SiteId.ValueStringPointer())
+ if err != nil {
+ return
+ }
+ state.RefreshPropertyValues(STFStoreService)
+
+ // Set refreshed state
+ diags = resp.State.Set(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Update updates the resource and sets the updated Terraform state on success.
+func (r *stfStoreServiceResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Retrieve values from plan
+ var plan STFStoreServiceResourceModel
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Get refreshed STFStoreService
+ _, err := getSTFStoreService(ctx, r.client, &resp.Diagnostics, plan.SiteId.ValueStringPointer())
+ if err != nil {
+ return
+ }
+
+ // Construct the update model
+ var editSTFStoreServiceBody = &citrixstorefront.SetSTFStoreRequestModel{}
+ editSTFStoreServiceBody.SetStoreService("(Get-STFStoreService -VirtualPath" + plan.VirtualPath.ValueString() + " )")
+
+ // Update STFStoreService
+ editStoreServiceRequest := r.client.StorefrontClient.StoreSF.STFStoreSetSTFStore(ctx, *editSTFStoreServiceBody)
+ _, err = editStoreServiceRequest.Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error updating Storefront StoreService ",
+ "\nError message: "+err.Error(),
+ )
+ }
+
+ // Fetch updated STFStoreService
+ updatedSTFStoreService, err := getSTFStoreService(ctx, r.client, &resp.Diagnostics, plan.SiteId.ValueStringPointer())
+ if err != nil {
+ return
+ }
+
+ // Update resource state with updated property values
+ plan.RefreshPropertyValues(updatedSTFStoreService)
+
+ diags = resp.State.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Delete deletes the resource and removes the Terraform state on success.
+func (r *stfStoreServiceResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Retrieve values from state
+ var state STFStoreServiceResourceModel
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ var body citrixstorefront.ClearSTFStoreRequestModel
+ if state.SiteId.ValueString() != "" {
+ body.SetStoreService("(Get-STFStoreService -VirtualPath " + state.VirtualPath.ValueString() + " -SiteId " + state.SiteId.ValueString() + " )")
+ }
+
+ // Delete existing STF StoreService
+ deleteStoreServiceRequest := r.client.StorefrontClient.StoreSF.STFStoreClearSTFStore(ctx, body)
+ _, err := deleteStoreServiceRequest.Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error deleting Storefront StoreService ",
+ "\nError message: "+err.Error(),
+ )
+ return
+ }
+}
+
+func (r *stfStoreServiceResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ idSegments := strings.SplitN(req.ID, ",", 2)
+
+ if (len(idSegments) != 2) || (idSegments[0] == "" || idSegments[1] == "") {
+ resp.Diagnostics.AddError(
+ "Invalid Import Identifier",
+ fmt.Sprintf("Expected format: `site_id,virtual_path`, got: %q", req.ID),
+ )
+ return
+ }
+
+ _, err := strconv.Atoi(idSegments[0])
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Invalid Site ID in Import Identifier",
+ fmt.Sprintf("Site ID should be an integer, got: %q", idSegments[0]),
+ )
+ return
+ }
+
+ // Retrieve import ID and save to id attribute
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("site_id"), idSegments[0])...)
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("virtual_path"), idSegments[1])...)
+}
+
+// Gets the STFStoreService and logs any errors
+func getSTFStoreService(ctx context.Context, client *citrixdaasclient.CitrixDaasClient, diagnostics *diag.Diagnostics, siteId *string) (*citrixstorefront.STFStoreDetailModel, error) {
+ var body citrixstorefront.GetSTFStoreRequestModel
+ if siteId != nil {
+ siteIdInt, err := strconv.ParseInt(*siteId, 10, 64)
+ if err != nil {
+ diagnostics.AddError(
+ "Error fetching state of Storefront StoreService ",
+ "Error message: "+err.Error(),
+ )
+ return nil, err
+ }
+ body.SetSiteId(siteIdInt)
+ }
+ getSTFStoreServiceRequest := client.StorefrontClient.StoreSF.STFStoreGetSTFStore(ctx, body)
+
+ // Get refreshed STFStoreService properties from Orchestration
+ STFStoreService, err := getSTFStoreServiceRequest.Execute()
+ if err != nil {
+ return &STFStoreService, err
+ }
+ return &STFStoreService, nil
+}
diff --git a/internal/storefront/stf_store/stf_store_service_resource_model.go b/internal/storefront/stf_store/stf_store_service_resource_model.go
new file mode 100644
index 0000000..929dcbd
--- /dev/null
+++ b/internal/storefront/stf_store/stf_store_service_resource_model.go
@@ -0,0 +1,35 @@
+// Copyright © 2023. Citrix Systems, Inc.
+
+package stf_store
+
+import (
+ "strconv"
+
+ citrixstorefront "github.com/citrix/citrix-daas-rest-go/citrixstorefront/models"
+
+ "github.com/hashicorp/terraform-plugin-framework/types"
+)
+
+// SFStoreServiceResourceModel maps the resource schema data.
+type STFStoreServiceResourceModel struct {
+ VirtualPath types.String `tfsdk:"virtual_path"`
+ SiteId types.String `tfsdk:"site_id"`
+ FriendlyName types.String `tfsdk:"friendly_name"`
+ AuthenticationService types.String `tfsdk:"authentication_service"`
+ Anonymous types.Bool `tfsdk:"anonymous"`
+ LoadBalance types.Bool `tfsdk:"load_balance"`
+ FarmConfig *FarmConfig `tfsdk:"farm_config"`
+}
+
+type FarmConfig struct {
+ FarmName types.String `tfsdk:"farm_name"`
+ FarmType types.String `tfsdk:"farm_type"`
+ Servers []types.String `tfsdk:"servers"`
+}
+
+func (r *STFStoreServiceResourceModel) RefreshPropertyValues(storeservice *citrixstorefront.STFStoreDetailModel) {
+ // Overwrite SFStoreServiceResourceModel with refreshed state
+ r.VirtualPath = types.StringValue(*storeservice.VirtualPath.Get())
+ r.SiteId = types.StringValue(strconv.Itoa(*storeservice.SiteId.Get()))
+ r.FriendlyName = types.StringValue(*storeservice.FriendlyName.Get())
+}
diff --git a/internal/storefront/stf_webreceiver/stf_webreceiver_resource.go b/internal/storefront/stf_webreceiver/stf_webreceiver_resource.go
new file mode 100644
index 0000000..a9224f5
--- /dev/null
+++ b/internal/storefront/stf_webreceiver/stf_webreceiver_resource.go
@@ -0,0 +1,510 @@
+// Copyright © 2023. Citrix Systems, Inc.
+package stf_webreceiver
+
+import (
+ "context"
+ "fmt"
+ "strconv"
+ "strings"
+
+ citrixstorefront "github.com/citrix/citrix-daas-rest-go/citrixstorefront/models"
+ citrixdaasclient "github.com/citrix/citrix-daas-rest-go/client"
+ "github.com/citrix/terraform-provider-citrix/internal/util"
+
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/resource"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/listdefault"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+)
+
+// Ensure the implementation satisfies the expected interfaces.
+var (
+ _ resource.Resource = &stfWebReceiverResource{}
+ _ resource.ResourceWithConfigure = &stfWebReceiverResource{}
+ _ resource.ResourceWithImportState = &stfWebReceiverResource{}
+)
+
+// stfWebReceiverResource is a helper function to simplify the provider implementation.
+func NewSTFWebReceiverResource() resource.Resource {
+ return &stfWebReceiverResource{}
+}
+
+// stfWebReceiverResource is the resource implementation.
+type stfWebReceiverResource struct {
+ client *citrixdaasclient.CitrixDaasClient
+}
+
+// Metadata returns the resource type name.
+func (r *stfWebReceiverResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_stf_webreceiver_service"
+}
+
+// Schema defines the schema for the resource.
+func (r *stfWebReceiverResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ Description: "Storefront WebReceiver.",
+ Attributes: map[string]schema.Attribute{
+ "site_id": schema.StringAttribute{
+ Description: "The IIS site id of the Storefront webreceiver. Defaults to 1.",
+ Optional: true,
+ Computed: true,
+ Default: stringdefault.StaticString("1"),
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "virtual_path": schema.StringAttribute{
+ Description: "The IIS VirtualPath at which the WebReceiver will be configured to be accessed by Receivers.",
+ Required: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "friendly_name": schema.StringAttribute{
+ Description: "The friendly name of the WebReceiver",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "store_service": schema.StringAttribute{
+ Description: "The StoreFront Store Service linked to the WebReceiver.",
+ Optional: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "authentication_methods": schema.ListAttribute{
+ ElementType: types.StringType,
+ Description: "The authentication methods supported by the WebReceiver.",
+ Optional: true,
+ Computed: true,
+ Default: listdefault.StaticValue(types.ListNull(types.StringType)),
+ },
+ "plugin_assistant": schema.SingleNestedAttribute{
+ Description: "Pluin Assistant configuration for the WebReceiver.",
+ Optional: true,
+ Attributes: map[string]schema.Attribute{
+ "enabled": schema.BoolAttribute{
+ Description: "Enable the Plugin Assistant.",
+ Optional: true,
+ Computed: true,
+ Default: booldefault.StaticBool(true),
+ },
+ "upgrade_at_login": schema.BoolAttribute{
+ Description: "Prompt to upgrade older clients.",
+ Optional: true,
+ Computed: true,
+ Default: booldefault.StaticBool(false),
+ },
+ "show_after_login": schema.BoolAttribute{
+ Description: "Show Plugin Assistant after the user logs in.",
+ Optional: true,
+ Computed: true,
+ Default: booldefault.StaticBool(false),
+ },
+ "win32_path": schema.StringAttribute{
+ Description: "Path to the Windows Receiver.",
+ Optional: true,
+ },
+ "macos_path": schema.StringAttribute{
+ Description: "Path to the MacOS Receiver.",
+ Optional: true,
+ },
+ "macos_minimum_supported_version": schema.StringAttribute{
+ Description: "Minimum version of the MacOS supported.",
+ Optional: true,
+ },
+ "html5_single_tab_launch": schema.BoolAttribute{
+ Description: "Launch Html5 Receiver in the same browser tab.",
+ Optional: true,
+ },
+ "html5_enabled": schema.StringAttribute{
+ Description: "Method of deploying and using the Html5 Receiver.",
+ Optional: true,
+ Computed: true,
+ Default: stringdefault.StaticString("Off"),
+ },
+ "html5_platforms": schema.StringAttribute{
+ Description: "The supported Html5 platforms.",
+ Optional: true,
+ },
+ "html5_preferences": schema.StringAttribute{
+ Description: "Html5 Receiver preferences.",
+ Optional: true,
+ },
+ "html5_chrome_app_origins": schema.StringAttribute{
+ Description: "The Html5 Chrome Application Origins settings.",
+ Optional: true,
+ },
+ "html5_chrome_app_preferences": schema.StringAttribute{
+ Description: "The Html5 Chrome Application preferences.",
+ Optional: true,
+ },
+ "protocol_handler_enabled": schema.BoolAttribute{
+ Description: "Enable the Receiver Protocol Handler.",
+ Optional: true,
+ Computed: true,
+ Default: booldefault.StaticBool(true),
+ },
+ "protocol_handler_platforms": schema.StringAttribute{
+ Description: "The supported Protocol Handler platforms.",
+ Optional: true,
+ },
+ "protocol_handler_skip_double_hop_check_when_disabled": schema.BoolAttribute{
+ Description: "Skip the Protocol Handle double hop check.",
+ Optional: true,
+ },
+ },
+ },
+ },
+ }
+}
+
+// Configure adds the provider configured client to the resource.
+func (r *stfWebReceiverResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ r.client = req.ProviderData.(*citrixdaasclient.CitrixDaasClient)
+}
+
+// Create creates the resource and sets the initial Terraform state.
+func (r *stfWebReceiverResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Retrieve values from plan
+ var plan STFWebReceiverResourceModel
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Generate API request body from plan
+ var body citrixstorefront.CreateSTFWebReceiverRequestModel
+ siteIdInt, err := strconv.ParseInt(plan.SiteId.ValueString(), 10, 64)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error creating Storefront WebReceiver ",
+ "\nError message: "+err.Error(),
+ )
+ return
+ }
+ body.SetSiteId(siteIdInt)
+ body.SetVirtualPath(plan.VirtualPath.String())
+ body.SetFriendlyName(plan.FriendlyName.ValueString())
+ body.SetStoreService("(Get-STFStoreService -VirtualPath " + plan.StoreService.ValueString() + " ) ")
+ createWebReceiverRequest := r.client.StorefrontClient.WebReceiverSF.STFWebReceiverCreateSTFWebReceiver(ctx, body)
+ // Create new STF WebReceiver
+ WebReceiverDetail, err := createWebReceiverRequest.Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error creating Storefront WebReceiver",
+ "TransactionId: ",
+ )
+ return
+ }
+
+ // Create the authentication methods Body
+ if plan.AuthenticationMethods != nil {
+ var authMethodCreateBody citrixstorefront.UpdateSTFWebReceiverAuthenticationMethodsRequestModel
+ authMethodCreateBody.SetWebReceiverService("(Get-STFWebReceiverService -VirtualPath " + plan.VirtualPath.ValueString() + " -SiteId " + plan.SiteId.ValueString() + " )")
+ authMethodCreateBody.SetAuthenticationMethods(util.ConvertBaseStringArrayToPrimitiveStringArray(plan.AuthenticationMethods))
+ creatAuthProtocolRequest := r.client.StorefrontClient.WebReceiverSF.STFWebReceiverSetSTFWebReceiverAuthenticationMethods(ctx, authMethodCreateBody)
+ // Create new STF WebReceiver Authentication Methods
+ _, err = creatAuthProtocolRequest.Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error creating Storefront WebReceiver Authentication Methods",
+ "TransactionId: ",
+ )
+ return
+ }
+ }
+
+ // Create the Plugin Assistant
+ if plan.PluginAssistant != nil {
+ var pluginAssistantBody citrixstorefront.UpdateSTFWebReceiverPluginAssistantRequestModel
+ pluginAssistantBody.SetWebReceiverService("(Get-STFWebReceiverService -VirtualPath " + plan.VirtualPath.ValueString() + " -SiteId " + plan.SiteId.ValueString() + " )")
+ pluginAssistantBody.SetEnabled(plan.PluginAssistant.Enabled.ValueBool())
+ pluginAssistantBody.SetUpgradeAtLogin(plan.PluginAssistant.UpgradeAtLogin.ValueBool())
+ pluginAssistantBody.SetShowAfterLogin(plan.PluginAssistant.ShowAfterLogin.ValueBool())
+ pluginAssistantBody.SetWin32Path(plan.PluginAssistant.Win32Path.ValueString())
+ pluginAssistantBody.SetMacOSPath(plan.PluginAssistant.MacOSPath.ValueString())
+ pluginAssistantBody.SetMacOSMinimumSupportedVersion(plan.PluginAssistant.MacOSMinimumSupportedVersion.ValueString())
+ pluginAssistantBody.SetHtml5SingleTabLaunch(plan.PluginAssistant.Html5SingleTabLaunch.ValueBool())
+ pluginAssistantBody.SetHtml5Enabled(plan.PluginAssistant.Html5Enabled.ValueString())
+ pluginAssistantBody.SetHtml5Platforms(plan.PluginAssistant.Html5Platforms.ValueString())
+ pluginAssistantBody.SetHtml5Preferences(plan.PluginAssistant.Html5Preferences.ValueString())
+ pluginAssistantBody.SetHtml5ChromeAppOrigins(plan.PluginAssistant.Html5ChromeAppOrigins.ValueString())
+ pluginAssistantBody.SetHtml5ChromeAppPreferences(plan.PluginAssistant.Html5ChromeAppPreferences.ValueString())
+ pluginAssistantBody.SetProtocolHandlerEnabled(plan.PluginAssistant.ProtocolHandlerEnabled.ValueBool())
+ pluginAssistantBody.SetProtocolHandlerPlatforms(plan.PluginAssistant.ProtocolHandlerPlatforms.ValueString())
+ pluginAssistantBody.SetProtocolHandlerSkipDoubleHopCheckWhenDisabled(plan.PluginAssistant.ProtocolHandlerSkipDoubleHopCheckWhenDisabled.ValueBool())
+ pluginAssistantRequest := r.client.StorefrontClient.WebReceiverSF.STFWebReceiverPluginAssistantUpdate(ctx, pluginAssistantBody)
+ // Create new STF WebReceiver Plugin Assistant
+ _, err = pluginAssistantRequest.Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error creating Storefront WebReceiver Plugin Assistant",
+ "TransactionId: ",
+ )
+ return
+ }
+
+ }
+
+ // Refresh the authentication methods
+ if plan.AuthenticationMethods != nil {
+ var authMethodGetBody citrixstorefront.GetSTFWebReceiverAuthenticationMethodsRequestModel
+ authMethodGetBody.SetWebReceiverService("(Get-STFWebReceiverService -VirtualPath " + plan.VirtualPath.ValueString() + " -SiteId " + plan.SiteId.ValueString() + " )")
+ getAuthProtocolRequest := r.client.StorefrontClient.WebReceiverSF.STFWebReceiverGetSTFWebReceiverAuthenticationMethods(ctx, authMethodGetBody)
+ authMethoResult, err := getAuthProtocolRequest.Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error fetching Storefront WebReceiver Authentication Methods",
+ "TransactionId: ",
+ )
+ return
+ }
+ util.RefreshList(plan.AuthenticationMethods, authMethoResult.Methods)
+ }
+
+ //Refresh Plugin Assistant
+ if plan.PluginAssistant != nil {
+ var pluginAssistantGetBody citrixstorefront.GetSTFWebReceiverPluginAssistantRequestModel
+ pluginAssistantGetBody.SetWebReceiverService("(Get-STFWebReceiverService -VirtualPath " + plan.VirtualPath.ValueString() + " -SiteId " + plan.SiteId.ValueString() + " )")
+ getPlugInAssistantRequest := r.client.StorefrontClient.WebReceiverSF.STFWebReceiverPluginAssistantGet(ctx, pluginAssistantGetBody)
+ assistant, err := getPlugInAssistantRequest.Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error fetching Storefront WebReceiver Plugin Assistant",
+ "TransactionId: ",
+ )
+ return
+ }
+ plan.RefreshPlugInAssistant(&assistant)
+ }
+
+ // Map response body to schema and populate Computed attribute values
+ plan.RefreshPropertyValues(&WebReceiverDetail)
+
+ // Set state to fully populated data
+ diags = resp.State.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Read refreshes the Terraform state with the latest data.
+func (r *stfWebReceiverResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Get current state
+ var state STFWebReceiverResourceModel
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ STFWebReceiver, err := getSTFWebReceiver(ctx, r.client, &resp.Diagnostics, state)
+ if err != nil {
+ return
+ }
+
+ //Refresh Plugin Assistant
+ if state.PluginAssistant != nil {
+ var pluginAssistantGetBody citrixstorefront.GetSTFWebReceiverPluginAssistantRequestModel
+ pluginAssistantGetBody.SetWebReceiverService("(Get-STFWebReceiverService -VirtualPath " + state.VirtualPath.ValueString() + " -SiteId " + state.SiteId.ValueString() + " )")
+ getPlugInAssistantRequest := r.client.StorefrontClient.WebReceiverSF.STFWebReceiverPluginAssistantGet(ctx, pluginAssistantGetBody)
+ assistant, err := getPlugInAssistantRequest.Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error fetching Storefront WebReceiver Plugin Assistant",
+ "TransactionId: ",
+ )
+ return
+ }
+ state.RefreshPlugInAssistant(&assistant)
+ }
+
+ state.RefreshPropertyValues(STFWebReceiver)
+
+ // Set refreshed state
+ diags = resp.State.Set(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Update updates the resource and sets the updated Terraform state on success.
+func (r *stfWebReceiverResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Retrieve values from plan
+ var plan STFWebReceiverResourceModel
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Get current state
+ var state STFWebReceiverResourceModel
+ diags = req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // Update the Auth Methods
+ if plan.AuthenticationMethods != nil {
+ var authMethodCreateBody citrixstorefront.UpdateSTFWebReceiverAuthenticationMethodsRequestModel
+ authMethodCreateBody.SetWebReceiverService("(Get-STFWebReceiverService -VirtualPath " + plan.VirtualPath.ValueString() + " -SiteId " + plan.SiteId.ValueString() + " )")
+ authMethodCreateBody.SetAuthenticationMethods(util.ConvertBaseStringArrayToPrimitiveStringArray(plan.AuthenticationMethods))
+ creatAuthProtocolRequest := r.client.StorefrontClient.WebReceiverSF.STFWebReceiverSetSTFWebReceiverAuthenticationMethods(ctx, authMethodCreateBody)
+ // Create new STF WebReceiver Authentication Methods
+ _, err := creatAuthProtocolRequest.Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error creating Storefront WebReceiver Authentication Methods",
+ "TransactionId: ",
+ )
+ return
+ }
+ }
+
+ // update the Plugin Assistant
+ if plan.PluginAssistant != nil {
+ var pluginAssistantBody citrixstorefront.UpdateSTFWebReceiverPluginAssistantRequestModel
+ pluginAssistantBody.SetWebReceiverService("(Get-STFWebReceiverService -VirtualPath " + plan.VirtualPath.ValueString() + " -SiteId " + plan.SiteId.ValueString() + " )")
+ pluginAssistantBody.SetEnabled(plan.PluginAssistant.Enabled.ValueBool())
+ pluginAssistantBody.SetUpgradeAtLogin(plan.PluginAssistant.UpgradeAtLogin.ValueBool())
+ pluginAssistantBody.SetShowAfterLogin(plan.PluginAssistant.ShowAfterLogin.ValueBool())
+ pluginAssistantBody.SetWin32Path(plan.PluginAssistant.Win32Path.ValueString())
+ pluginAssistantBody.SetMacOSPath(plan.PluginAssistant.MacOSPath.ValueString())
+ pluginAssistantBody.SetMacOSMinimumSupportedVersion(plan.PluginAssistant.MacOSMinimumSupportedVersion.ValueString())
+ pluginAssistantBody.SetHtml5SingleTabLaunch(plan.PluginAssistant.Html5SingleTabLaunch.ValueBool())
+ pluginAssistantBody.SetHtml5Enabled(plan.PluginAssistant.Html5Enabled.ValueString())
+ pluginAssistantBody.SetHtml5Platforms(plan.PluginAssistant.Html5Platforms.ValueString())
+ pluginAssistantBody.SetHtml5Preferences(plan.PluginAssistant.Html5Preferences.ValueString())
+ pluginAssistantBody.SetHtml5ChromeAppOrigins(plan.PluginAssistant.Html5ChromeAppOrigins.ValueString())
+ pluginAssistantBody.SetHtml5ChromeAppPreferences(plan.PluginAssistant.Html5ChromeAppPreferences.ValueString())
+ pluginAssistantBody.SetProtocolHandlerEnabled(plan.PluginAssistant.ProtocolHandlerEnabled.ValueBool())
+ pluginAssistantBody.SetProtocolHandlerPlatforms(plan.PluginAssistant.ProtocolHandlerPlatforms.ValueString())
+ pluginAssistantBody.SetProtocolHandlerSkipDoubleHopCheckWhenDisabled(plan.PluginAssistant.ProtocolHandlerSkipDoubleHopCheckWhenDisabled.ValueBool())
+ pluginAssistantRequest := r.client.StorefrontClient.WebReceiverSF.STFWebReceiverPluginAssistantUpdate(ctx, pluginAssistantBody)
+ // Create new STF WebReceiver Plugin Assistant
+ _, err := pluginAssistantRequest.Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error creating Storefront WebReceiver Plugin Assistant",
+ "TransactionId: ",
+ )
+ return
+ }
+
+ }
+
+ diags = resp.State.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+}
+
+// Delete deletes the resource and removes the Terraform state on success.
+func (r *stfWebReceiverResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ // Retrieve values from state
+ var state STFWebReceiverResourceModel
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ var body citrixstorefront.ClearSTFWebReceiverRequestModel
+ if state.SiteId.ValueString() != "" {
+ body.SetWebReceiverService("(Get-STFWebReceiverService -VirtualPath " + state.VirtualPath.ValueString() + " -SiteId " + state.SiteId.ValueString() + " )")
+ }
+
+ // Delete existing STF WebReceiver
+ deleteWebReceiverRequest := r.client.StorefrontClient.WebReceiverSF.STFWebReceiverClearSTFWebReceiver(ctx, body)
+ _, err := deleteWebReceiverRequest.Execute()
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Error deleting Storefront WebReceiver ",
+ "\nError message: "+err.Error(),
+ )
+ return
+ }
+}
+
+func (r *stfWebReceiverResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ defer util.PanicHandler(&resp.Diagnostics)
+
+ idSegments := strings.SplitN(req.ID, ",", 2)
+
+ if (len(idSegments) != 2) || (idSegments[0] == "" || idSegments[1] == "") {
+ resp.Diagnostics.AddError(
+ "Invalid Import Identifier",
+ fmt.Sprintf("Expected format: `site_id,virtual_path`, got: %q", req.ID),
+ )
+ return
+ }
+
+ _, err := strconv.Atoi(idSegments[0])
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Invalid Site ID in Import Identifier",
+ fmt.Sprintf("Site ID should be an integer, got: %q", idSegments[0]),
+ )
+ return
+ }
+
+ // Retrieve import ID and save to id attribute
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("site_id"), idSegments[0])...)
+ resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("virtual_path"), idSegments[1])...)
+}
+
+// Gets the STFWebReceiver and logs any errors
+func getSTFWebReceiver(ctx context.Context, client *citrixdaasclient.CitrixDaasClient, diagnostics *diag.Diagnostics, state STFWebReceiverResourceModel) (*citrixstorefront.STFWebReceiverDetailModel, error) {
+ var body citrixstorefront.GetSTFWebReceiverRequestModel
+ if !state.SiteId.IsNull() {
+ siteIdInt, err := strconv.ParseInt(state.SiteId.ValueString(), 10, 64)
+ if err != nil {
+ diagnostics.AddError(
+ "Error fetching state of Storefront WebReceiver ",
+ "Error message: "+err.Error(),
+ )
+ return nil, err
+ }
+ body.SetSiteId(siteIdInt)
+ }
+ if !state.VirtualPath.IsNull() {
+ body.SetVirtualPath(state.VirtualPath.ValueString())
+ }
+
+ getSTFWebReceiverRequest := client.StorefrontClient.WebReceiverSF.STFWebReceiverGetSTFWebReceiver(ctx, body)
+
+ // Get refreshed STFWebReceiver properties from Orchestration
+ STFWebReceiver, err := getSTFWebReceiverRequest.Execute()
+ if err != nil {
+ return &STFWebReceiver, err
+ }
+ return &STFWebReceiver, nil
+}
diff --git a/internal/storefront/stf_webreceiver/stf_webreceiver_resource_model.go b/internal/storefront/stf_webreceiver/stf_webreceiver_resource_model.go
new file mode 100644
index 0000000..e39f370
--- /dev/null
+++ b/internal/storefront/stf_webreceiver/stf_webreceiver_resource_model.go
@@ -0,0 +1,94 @@
+// Copyright © 2023. Citrix Systems, Inc.
+
+package stf_webreceiver
+
+import (
+ "strconv"
+
+ citrixstorefront "github.com/citrix/citrix-daas-rest-go/citrixstorefront/models"
+
+ "github.com/hashicorp/terraform-plugin-framework/types"
+)
+
+// SFWebReceiverResourceModel maps the resource schema data.
+type STFWebReceiverResourceModel struct {
+ VirtualPath types.String `tfsdk:"virtual_path"`
+ SiteId types.String `tfsdk:"site_id"`
+ FriendlyName types.String `tfsdk:"friendly_name"`
+ StoreService types.String `tfsdk:"store_service"`
+ PluginAssistant *PluginAssistant `tfsdk:"plugin_assistant"`
+ AuthenticationMethods []types.String `tfsdk:"authentication_methods"`
+}
+
+type PluginAssistant struct {
+ Enabled types.Bool `tfsdk:"enabled"` //Enable Receiver client detection.
+ UpgradeAtLogin types.Bool `tfsdk:"upgrade_at_login"` //Prompt to upgrade older clients.
+ ShowAfterLogin types.Bool `tfsdk:"show_after_login"` //Show Receiver client detection after the user logs in.
+ Win32Path types.String `tfsdk:"win32_path"` //Path to the Windows Receiver.
+ MacOSPath types.String `tfsdk:"macos_path"` //Path to the MacOS Receiver.
+ MacOSMinimumSupportedVersion types.String `tfsdk:"macos_minimum_supported_version"` //Minimum version of the MacOS supported.
+ Html5SingleTabLaunch types.Bool `tfsdk:"html5_single_tab_launch"` //Launch Html5 Receiver in the same browser tab.
+ Html5Enabled types.String `tfsdk:"html5_enabled"` //Method of deploying and using the Html5 Receiver.
+ Html5Platforms types.String `tfsdk:"html5_platforms"` //The supported Html5 platforms.
+ Html5Preferences types.String `tfsdk:"html5_preferences"` //Html5 Receiver preferences.
+ Html5ChromeAppOrigins types.String `tfsdk:"html5_chrome_app_origins"` //The Html5 Chrome Application Origins settings.
+ Html5ChromeAppPreferences types.String `tfsdk:"html5_chrome_app_preferences"` //The Html5 Chrome Application preferences.
+ ProtocolHandlerEnabled types.Bool `tfsdk:"protocol_handler_enabled"` //Enable the Receiver Protocol Handler.
+ ProtocolHandlerPlatforms types.String `tfsdk:"protocol_handler_platforms"` //The supported Protocol Handler platforms.
+ ProtocolHandlerSkipDoubleHopCheckWhenDisabled types.Bool `tfsdk:"protocol_handler_skip_double_hop_check_when_disabled"` //Skip the Protocol Handle double hop check.
+}
+
+func (r *STFWebReceiverResourceModel) RefreshPropertyValues(webreceiver *citrixstorefront.STFWebReceiverDetailModel) {
+ // Overwrite SFWebReceiverResourceModel with refreshed state
+ r.VirtualPath = types.StringValue(*webreceiver.VirtualPath.Get())
+ r.SiteId = types.StringValue(strconv.Itoa(*webreceiver.SiteId.Get()))
+ r.FriendlyName = types.StringValue(*webreceiver.FriendlyName.Get())
+
+}
+
+func (r *STFWebReceiverResourceModel) RefreshPlugInAssistant(assistant *citrixstorefront.WebReceiverPluginAssistantModel) {
+ // Overwrite SFWebReceiverResourceModel with refreshed state
+ r.PluginAssistant.Enabled = types.BoolValue(*assistant.Enabled.Get())
+ r.PluginAssistant.UpgradeAtLogin = types.BoolValue(*assistant.UpgradeAtLogin.Get())
+ r.PluginAssistant.ShowAfterLogin = types.BoolValue(*assistant.ShowAfterLogin.Get())
+ if !r.PluginAssistant.Win32Path.IsNull() {
+ r.PluginAssistant.Win32Path = types.StringValue(*assistant.Win32.Path.Get())
+ }
+ if !r.PluginAssistant.MacOSPath.IsNull() {
+ r.PluginAssistant.MacOSPath = types.StringValue(*assistant.MacOS.Path.Get())
+ }
+ if !r.PluginAssistant.MacOSMinimumSupportedVersion.IsNull() {
+ r.PluginAssistant.MacOSMinimumSupportedVersion = types.StringValue(*assistant.MacOS.MinimumSupportedVersion.Get())
+ }
+ if !r.PluginAssistant.Html5SingleTabLaunch.IsNull() {
+ r.PluginAssistant.Html5SingleTabLaunch = types.BoolValue(*assistant.HTML5.SingleTabLaunch.Get())
+ }
+ if !r.PluginAssistant.Html5Enabled.IsNull() {
+ if *assistant.HTML5.Enabled.Get() == 0 {
+ r.PluginAssistant.Html5Enabled = types.StringValue("Off")
+ } else if *assistant.HTML5.Enabled.Get() == 1 {
+ r.PluginAssistant.Html5Enabled = types.StringValue("Always")
+ } else {
+ r.PluginAssistant.Html5Enabled = types.StringValue("Fallback")
+ }
+ }
+ if !r.PluginAssistant.Html5Platforms.IsNull() {
+ r.PluginAssistant.Html5Platforms = types.StringValue(*assistant.HTML5.Platforms.Get())
+ }
+ if !r.PluginAssistant.Html5Preferences.IsNull() {
+ r.PluginAssistant.Html5Preferences = types.StringValue(*assistant.HTML5.Preferences.Get())
+ }
+ if !r.PluginAssistant.Html5ChromeAppOrigins.IsNull() {
+ r.PluginAssistant.Html5ChromeAppOrigins = types.StringValue(*assistant.HTML5.ChromeAppOrigins.Get())
+ }
+ if !r.PluginAssistant.Html5ChromeAppPreferences.IsNull() {
+ r.PluginAssistant.Html5ChromeAppPreferences = types.StringValue(*assistant.HTML5.ChromeAppPreferences.Get())
+ }
+ if !r.PluginAssistant.ProtocolHandlerEnabled.IsNull() {
+ r.PluginAssistant.ProtocolHandlerEnabled = types.BoolValue(*assistant.ProtocolHandler.Enabled.Get())
+ }
+ if !r.PluginAssistant.ProtocolHandlerPlatforms.IsNull() {
+ r.PluginAssistant.ProtocolHandlerPlatforms = types.StringValue(*assistant.ProtocolHandler.Platforms.Get())
+ }
+
+}
diff --git a/internal/test/admin_scope_resource_test.go b/internal/test/admin_scope_resource_test.go
index abfa1a6..0ed76ad 100644
--- a/internal/test/admin_scope_resource_test.go
+++ b/internal/test/admin_scope_resource_test.go
@@ -35,7 +35,15 @@ func TestAdminScopeResource(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildAdminScopeResource(t, adminScopeTestResource),
+ Config: composeTestResourceTf(
+ BuildAdminScopeResource(t, adminScopeTestResource),
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources),
+ BuildPolicySetResourceWithoutDeliveryGroup(t),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify the name of the admin scope
resource.TestCheckResourceAttr("citrix_admin_scope.test_scope", "name", name),
@@ -59,7 +67,15 @@ func TestAdminScopeResource(t *testing.T) {
},
// Update and Read testing
{
- Config: BuildAdminScopeResource(t, adminScopeTestResource_updated),
+ Config: composeTestResourceTf(
+ BuildAdminScopeResource(t, adminScopeTestResource_updated),
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources),
+ BuildPolicySetResourceWithoutDeliveryGroup(t),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify the name of the admin scope
resource.TestCheckResourceAttr("citrix_admin_scope.test_scope", "name", fmt.Sprintf("%s-updated", name)),
@@ -111,5 +127,5 @@ var (
)
func BuildAdminScopeResource(t *testing.T, adminScope string) string {
- return BuildDeliveryGroupResource(t, testDeliveryGroupResources) + fmt.Sprintf(adminScope, os.Getenv("TEST_ADMIN_SCOPE_NAME"))
+ return fmt.Sprintf(adminScope, os.Getenv("TEST_ADMIN_SCOPE_NAME"))
}
diff --git a/internal/test/admin_user_resource_test.go b/internal/test/admin_user_resource_test.go
index d367797..cc71695 100644
--- a/internal/test/admin_user_resource_test.go
+++ b/internal/test/admin_user_resource_test.go
@@ -47,7 +47,16 @@ func TestAdminUserResource(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildAdminUserResource(t, adminUserTestResource),
+ Config: composeTestResourceTf(
+ BuildAdminUserResource(t, adminUserTestResource),
+ BuildAdminScopeResource(t, adminScopeTestResource),
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources),
+ BuildPolicySetResourceWithoutDeliveryGroup(t),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify the name of the admin user
resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "name", userName),
@@ -60,7 +69,7 @@ func TestAdminUserResource(t *testing.T) {
// Verify the is_enabled flag
resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "is_enabled", "true"),
),
- SkipFunc: getSkipFunc(isOnPremises),
+ SkipFunc: skipForCloud(isOnPremises),
},
// ImportState testing
{
@@ -73,7 +82,16 @@ func TestAdminUserResource(t *testing.T) {
},
// Update and Read testing
{
- Config: BuildAdminUserResource(t, adminUserTestResource_updated),
+ Config: composeTestResourceTf(
+ BuildAdminUserResource(t, adminUserTestResource_updated),
+ BuildAdminScopeResource(t, adminScopeTestResource),
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources),
+ BuildPolicySetResourceWithoutDeliveryGroup(t),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify the name of the admin user
resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "name", userName),
@@ -88,7 +106,7 @@ func TestAdminUserResource(t *testing.T) {
// Verify the is_enabled flag
resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "is_enabled", "true"),
),
- SkipFunc: getSkipFunc(isOnPremises),
+ SkipFunc: skipForCloud(isOnPremises),
},
// Delete testing automatically occurs in TestCase
},
@@ -131,5 +149,5 @@ var (
func BuildAdminUserResource(t *testing.T, adminUser string) string {
adminName := os.Getenv("TEST_ADMIN_USER_NAME")
adminDomain := os.Getenv("TEST_ADMIN_USER_DOMAIN")
- return BuildAdminScopeResource(t, adminScopeTestResource) + BuildAdminRoleResource(t, adminRoleTestResource) + fmt.Sprintf(adminUser, adminName, adminDomain)
+ return fmt.Sprintf(adminUser, adminName, adminDomain)
}
diff --git a/internal/test/application_resource_test.go b/internal/test/application_resource_test.go
index c130bc3..6a06df5 100644
--- a/internal/test/application_resource_test.go
+++ b/internal/test/application_resource_test.go
@@ -33,7 +33,16 @@ func TestApplicationResource(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildApplicationResource(t, testApplicationResource),
+ Config: composeTestResourceTf(
+ BuildApplicationResource(t, testApplicationResource),
+ BuildApplicationFolderResource(t, testApplicationFolderResource_updated),
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources),
+ BuildPolicySetResourceWithoutDeliveryGroup(t),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of application
resource.TestCheckResourceAttr("citrix_application.testApplication", "name", name),
@@ -56,7 +65,16 @@ func TestApplicationResource(t *testing.T) {
},
// Update and Read testing
{
- Config: BuildApplicationResource(t, testApplicationResource_updated),
+ Config: composeTestResourceTf(
+ BuildApplicationResource(t, testApplicationResource_updated),
+ BuildApplicationFolderResource(t, testApplicationFolderResource_updated),
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources),
+ BuildPolicySetResourceWithoutDeliveryGroup(t),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of application
resource.TestCheckResourceAttr("citrix_application.testApplication", "name", fmt.Sprintf("%s-updated", name)),
@@ -104,5 +122,5 @@ resource "citrix_application" "testApplication" {
func BuildApplicationResource(t *testing.T, applicationResource string) string {
name := os.Getenv("TEST_APP_NAME")
- return BuildDeliveryGroupResource(t, testDeliveryGroupResources_updated) + BuildApplicationFolderResource(t, testApplicationFolderResource_updated) + fmt.Sprintf(applicationResource, name)
+ return fmt.Sprintf(applicationResource, name)
}
diff --git a/internal/test/azure_mcs_suite_test.go b/internal/test/azure_mcs_suite_test.go
new file mode 100644
index 0000000..8e63db3
--- /dev/null
+++ b/internal/test/azure_mcs_suite_test.go
@@ -0,0 +1,757 @@
+// Copyright © 2023. Citrix Systems, Inc.
+
+package test
+
+import (
+ "fmt"
+ "os"
+ "strconv"
+ "strings"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+// testHypervisorPreCheck validates the necessary env variable exist
+// in the testing environment
+func TestAzureMcsSuitePreCheck(t *testing.T) {
+ customerId := os.Getenv("CITRIX_CUSTOMER_ID")
+ isOnPremises := true
+ if customerId != "" && customerId != "CitrixOnPremises" {
+ // Tests being run in cloud env
+ isOnPremises = false
+ }
+
+ TestProviderPreCheck(t)
+ TestHypervisorPreCheck_Azure(t)
+ TestHypervisorResourcePoolPreCheck_Azure(t)
+ TestMachineCatalogPreCheck_Azure(t)
+ TestMachineCatalogPreCheck_Manual_Power_Managed_Azure(t)
+ TestDeliveryGroupPreCheck(t)
+ TestApplicationFolderPreCheck(t)
+ TestApplicationResourcePreCheck(t)
+ TestAdminScopeResourcePreCheck(t)
+ TestAdminRolePreCheck(t)
+ TestPolicySetResourcePreCheck(t)
+
+ if !isOnPremises {
+ TestMachineCatalogPreCheck_AzureAd(t)
+ TestMachineCatalogPreCheck_Workgroup(t)
+ } else {
+ TestAdminUserPreCheck(t)
+ }
+}
+
+func TestAzureMcs(t *testing.T) {
+ customerId := os.Getenv("CITRIX_CUSTOMER_ID")
+ isOnPremises := true
+ if customerId != "" && customerId != "CitrixOnPremises" {
+ // Tests being run in cloud env
+ isOnPremises = false
+ }
+
+ zoneName := os.Getenv("TEST_ZONE_NAME")
+ zoneDescription := os.Getenv("TEST_ZONE_DESCRIPTION")
+ if zoneName == "" {
+ zoneName = "second zone"
+ zoneDescription = "description for go test zone"
+ }
+
+ hypervName := os.Getenv("TEST_HYPERV_NAME_AZURE")
+ resourcePoolName := os.Getenv("TEST_HYPERV_RP_NAME")
+ machineCatalogName := os.Getenv("TEST_MC_NAME")
+ deliveryGroupName := os.Getenv("TEST_DG_NAME")
+ hybridCatalogName := machineCatalogName + "-HybAAD"
+ aadCatalogName := machineCatalogName + "-AAD"
+ workgroupCatalogName := machineCatalogName + "-WRKGRP"
+ manualPmCatalogName := os.Getenv("TEST_MC_NAME_MANUAL")
+ applicationName := os.Getenv("TEST_APP_NAME")
+ appFolderName := os.Getenv("TEST_APP_FOLDER_NAME")
+ folder_name_1 := fmt.Sprintf("%s-1", appFolderName)
+ folder_name_2 := fmt.Sprintf("%s-2", appFolderName)
+ adminScopeName := os.Getenv("TEST_ADMIN_SCOPE_NAME")
+ adminRoleName := os.Getenv("TEST_ROLE_NAME")
+ userName := os.Getenv("TEST_ADMIN_USER_NAME")
+ userDomainName := os.Getenv("TEST_ADMIN_USER_DOMAIN")
+
+ zoneResourceUpdated := zone_testResource
+
+ if isOnPremises {
+ zoneResourceUpdated = zone_testResource_updated
+ }
+
+ resource.Test(t, resource.TestCase{
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ PreCheck: func() {
+ TestProviderPreCheck(t)
+ TestHypervisorPreCheck_Azure(t)
+ TestHypervisorResourcePoolPreCheck_Azure(t)
+ TestMachineCatalogPreCheck_Azure(t)
+ TestMachineCatalogPreCheck_Manual_Power_Managed_Azure(t)
+ TestDeliveryGroupPreCheck(t)
+ TestApplicationFolderPreCheck(t)
+ TestApplicationResourcePreCheck(t)
+ },
+ Steps: []resource.TestStep{
+ /****************** Zone Test ******************/
+ // Zone - Create and Read testing
+ {
+ Config: BuildZoneResource(t, zone_testResource, zoneName),
+ Check: getAggregateTestFunc(isOnPremises, zoneName, zoneDescription),
+ },
+ // ImportState testing
+ {
+ ResourceName: "citrix_zone.test",
+ ImportState: true,
+ ImportStateVerify: true,
+ // The last_updated attribute does not exist in the Orchestration
+ // API, therefore there is no value for it during import.
+ ImportStateVerifyIgnore: []string{"last_updated", "metadata"},
+ },
+ // Update and Read testing
+ {
+ Config: BuildZoneResource(t, zoneResourceUpdated, zoneName),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify name of zone
+ resource.TestCheckResourceAttr("citrix_zone.test", "name", fmt.Sprintf("%s-updated", zoneName)),
+ // Verify description of zone
+ resource.TestCheckResourceAttr("citrix_zone.test", "description", fmt.Sprintf("updated %s", zoneDescription)),
+ // Verify number of meta data of zone
+ resource.TestCheckResourceAttr("citrix_zone.test", "metadata.#", "4"),
+ // Verify first meta data value
+ resource.TestCheckResourceAttr("citrix_zone.test", "metadata.3.name", "key4"),
+ resource.TestCheckResourceAttr("citrix_zone.test", "metadata.3.value", "value4"),
+ ),
+ SkipFunc: skipForCloud(isOnPremises),
+ },
+
+ /****************** Hypervisor Test ******************/
+ // Create and Read testing
+ {
+ Config: composeTestResourceTf(
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zoneResourceUpdated, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
+
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify name of hypervisor
+ resource.TestCheckResourceAttr("citrix_azure_hypervisor.testHypervisor", "name", hypervName),
+ ),
+ },
+
+ // ImportState testing
+ {
+ ResourceName: "citrix_azure_hypervisor.testHypervisor",
+ ImportState: true,
+ ImportStateVerify: true,
+ // The last_updated attribute does not exist in the Orchestration
+ // API, therefore there is no value for it during import.
+ ImportStateVerifyIgnore: []string{"last_updated", "application_secret"},
+ },
+ // Update and Read testing
+ {
+ Config: composeTestResourceTf(
+ BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
+ BuildZoneResource(t, zoneResourceUpdated, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify name of hypervisor
+ resource.TestCheckResourceAttr("citrix_azure_hypervisor.testHypervisor", "name", fmt.Sprintf("%s-updated", hypervName)),
+ ),
+ },
+
+ /****************** Resource Pool Test ******************/
+ // Create and Read testing
+ {
+ Config: composeTestResourceTf(
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
+ BuildZoneResource(t, zoneResourceUpdated, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
+
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr("citrix_azure_hypervisor_resource_pool.testHypervisorResourcePool", "name", resourcePoolName),
+ // Verify name of virtual network resource group name
+ resource.TestCheckResourceAttr("citrix_azure_hypervisor_resource_pool.testHypervisorResourcePool", "virtual_network_resource_group", os.Getenv("TEST_HYPERV_RP_VIRTUAL_NETWORK_RESOURCE_GROUP")),
+ // Verify name of virtual network
+ resource.TestCheckResourceAttr("citrix_azure_hypervisor_resource_pool.testHypervisorResourcePool", "virtual_network", os.Getenv("TEST_HYPERV_RP_VIRTUAL_NETWORK")),
+ // Verify name of the region
+ resource.TestCheckResourceAttr("citrix_azure_hypervisor_resource_pool.testHypervisorResourcePool", "region", os.Getenv("TEST_HYPERV_RP_REGION")),
+ // Verify subnets
+ resource.TestCheckResourceAttr("citrix_azure_hypervisor_resource_pool.testHypervisorResourcePool", "subnets.#", strconv.Itoa(len(strings.Split(os.Getenv("Test_HYPERV_RP_SUBNETS"), ",")))),
+ ),
+ },
+ // ImportState testing
+ {
+ ResourceName: "citrix_azure_hypervisor_resource_pool.testHypervisorResourcePool",
+ ImportState: true,
+ ImportStateIdFunc: generateImportStateId,
+ ImportStateVerify: true,
+ },
+ // Update and Read
+ {
+ Config: composeTestResourceTf(
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
+ BuildZoneResource(t, zoneResourceUpdated, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr("citrix_azure_hypervisor_resource_pool.testHypervisorResourcePool", "name", fmt.Sprintf("%s-updated", resourcePoolName)),
+ ),
+ },
+
+ /****************** Machine Catalog Test - MCS AD / AAD / HybridAAD - Manual Power Managed ******************/
+ // Create and Read testing
+ {
+ Config: composeAzureMachineCatalogTestResourceTf(t, isOnPremises),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ /*** Verify MCS AD Machine Catalog ***/
+ // Verify name of catalog
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", machineCatalogName),
+ // Verify domain FQDN
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "session_support", "MultiSession"),
+ // Verify domain admin username
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.machine_domain_identity.service_account", os.Getenv("TEST_MC_SERVICE_ACCOUNT")),
+ // Verify machine catalog identity type
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.identity_type", "ActiveDirectory"),
+ // Verify nic network
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.network_mapping.0.network", os.Getenv("TEST_MC_SUBNET")),
+
+ /*** Verify MCS Hybrid AAD Machine Catalog ***/
+ // Verify name of catalog
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-HybAAD", "name", hybridCatalogName),
+ // Verify domain FQDN
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-HybAAD", "session_support", "MultiSession"),
+ // Verify machine catalog identity type
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-HybAAD", "provisioning_scheme.identity_type", "HybridAzureAD"),
+ // Verify domain admin username
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-HybAAD", "provisioning_scheme.machine_domain_identity.service_account", os.Getenv("TEST_MC_SERVICE_ACCOUNT")),
+ // Verify nic network
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-HybAAD", "provisioning_scheme.network_mapping.0.network", os.Getenv("TEST_MC_SUBNET")),
+
+ /*** Optional - Verify MCS AAD / WorkGroup Machine Catalog ***/
+ composeCloudMachineCatalogTestVerification(isOnPremises, aadCatalogName, workgroupCatalogName),
+
+ /*** Verify Manual Power Managed Machine Catalog ***/
+ // Verify name of catalog
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalogManualPowerManaged", "name", manualPmCatalogName),
+ // Verify session support
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalogManualPowerManaged", "session_support", os.Getenv("TEST_MC_SESSION_SUPPORT_MANUAL_POWER_MANAGED")),
+ // Verify total number of machines
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalogManualPowerManaged", "machine_accounts.#", "1"),
+ ),
+ },
+ // ImportState testing - MCS AD
+ {
+ ResourceName: "citrix_machine_catalog.testMachineCatalog",
+ ImportState: true,
+ ImportStateVerify: true,
+ // The last_updated attribute does not exist in the Orchestration
+ // API, therefore there is no value for it during import.
+ ImportStateVerifyIgnore: []string{"provisioning_scheme.network_mapping", "provisioning_scheme.azure_machine_config.writeback_cache", "provisioning_scheme.machine_domain_identity.service_account", "provisioning_scheme.machine_config.service_account_password"},
+ },
+ // ImportState testing - MCS HybridAAD
+ {
+ ResourceName: "citrix_machine_catalog.testMachineCatalog-HybAAD",
+ ImportState: true,
+ ImportStateVerify: true,
+ // The last_updated attribute does not exist in the Orchestration
+ // API, therefore there is no value for it during import.
+ ImportStateVerifyIgnore: []string{"provisioning_scheme.network_mapping", "provisioning_scheme.azure_machine_config.writeback_cache", "provisioning_scheme.machine_domain_identity.service_account", "provisioning_scheme.machine_config.service_account_password"},
+ },
+ // ImportState testing - MCS AAD
+ {
+ ResourceName: "citrix_machine_catalog.testMachineCatalog-AAD",
+ ImportState: true,
+ ImportStateVerify: true,
+ // The last_updated attribute does not exist in the Orchestration
+ // API, therefore there is no value for it during import.
+ ImportStateVerifyIgnore: []string{"provisioning_scheme.network_mapping", "provisioning_scheme.azure_machine_config.writeback_cache"},
+ SkipFunc: skipForOnPrem(isOnPremises),
+ },
+ // ImportState testing
+ {
+ ResourceName: "citrix_machine_catalog.testMachineCatalog-WG",
+ ImportState: true,
+ ImportStateVerify: true,
+ // The last_updated attribute does not exist in the Orchestration
+ // API, therefore there is no value for it during import.
+ ImportStateVerifyIgnore: []string{"provisioning_scheme.network_mapping", "provisioning_scheme.azure_machine_config.writeback_cache"},
+ SkipFunc: skipForOnPrem(isOnPremises),
+ },
+ // ImportState testing - Manual Power Managed
+ {
+ ResourceName: "citrix_machine_catalog.testMachineCatalogManualPowerManaged",
+ ImportState: true,
+ ImportStateVerify: true,
+ ImportStateVerifyIgnore: []string{"machine_accounts", "is_remote_pc", "is_power_managed"},
+ },
+
+ /****************** Delivery Group Test - Create ******************/
+ // Create and Read testing
+ {
+ Config: composeTestResourceTf(
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
+ BuildZoneResource(t, zoneResourceUpdated, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
+
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify name of delivery group
+ resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "name", deliveryGroupName),
+ // Verify description of delivery group
+ resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "description", "Delivery Group for testing"),
+ // Verify number of desktops
+ resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "desktops.#", "2"),
+ // Verify number of reboot schedules
+ resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "reboot_schedules.#", "2"),
+ // Verify total number of machines in delivery group
+ resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "total_machines", "1"),
+ // Verify the policy set id assigned to the delivery group
+ resource.TestCheckNoResourceAttr("citrix_delivery_group.testDeliveryGroup", "policy_set_id"),
+ ),
+ },
+ // ImportState testing
+ {
+ ResourceName: "citrix_delivery_group.testDeliveryGroup",
+ ImportState: true,
+ ImportStateVerify: true,
+ // The last_updated attribute does not exist in the Orchestration
+ // API, therefore there is no value for it during import.
+ ImportStateVerifyIgnore: []string{"last_updated", "autoscale_settings", "associated_machine_catalogs", "reboot_schedules"},
+ },
+
+ /****************** Delivery Group Test - MCS AD - Update ******************/
+ // Machine Catalog: Update description, master image and add machine test
+ // Delivery Group: Update name, description and add machine testing
+ {
+ Config: composeTestResourceTf(
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources_updated),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
+ BuildZoneResource(t, zoneResourceUpdated, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ /*** Verify Machine Catalog ***/
+ // Verify updated name of catalog
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", machineCatalogName),
+ // Verify updated description
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "description", "updatedCatalog"),
+ // Verify updated image
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.azure_machine_config.azure_master_image.master_image", os.Getenv("TEST_MC_MASTER_IMAGE_UPDATED")),
+ // Verify machine catalog identity type
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.identity_type", "ActiveDirectory"),
+ // Verify total number of machines
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.number_of_total_machines", "2"),
+
+ /*** Verify Delivery Group ***/
+ // Verify name of delivery group
+ resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "name", fmt.Sprintf("%s-updated", deliveryGroupName)),
+ // Verify description of delivery group
+ resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "description", "Delivery Group for testing updated"),
+ // Verify number of desktops
+ resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "desktops.#", "1"),
+ // Verify number of reboot schedules
+ resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "reboot_schedules.#", "1"),
+ // Verify total number of machines in delivery group
+ resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "total_machines", "2"),
+ // Verify the policy set id assigned to the delivery group
+ resource.TestCheckNoResourceAttr("citrix_delivery_group.testDeliveryGroup", "policy_set_id"),
+ ),
+ },
+
+ /****************** Delivery Group Test - Policy Update ******************/
+ // Create Policy and assign to delivery group
+ {
+ Config: composeTestResourceTf(
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources_updatedWithPolicySetId),
+ BuildPolicySetResourceWithoutDeliveryGroup(t),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
+ BuildZoneResource(t, zoneResourceUpdated, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify the policy set id assigned to the delivery group
+ resource.TestCheckResourceAttrSet("citrix_delivery_group.testDeliveryGroup", "policy_set_id"),
+ ),
+ },
+
+ /****************** Machine Catalog & Delivery Group Test - MCS AD - Delete Machine ******************/
+ // Delivery Group: Remove machine test
+ // Machine Catalog: Delete machine test
+ {
+ Config: composeTestResourceTf(
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_delete_machine, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
+ BuildZoneResource(t, zoneResourceUpdated, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify total number of machines in delivery group
+ resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "total_machines", "1"),
+ // Verify the policy set id assigned to the delivery group
+ resource.TestCheckNoResourceAttr("citrix_delivery_group.testDeliveryGroup", "policy_set_id"),
+ // Verify updated name of catalog
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", machineCatalogName),
+ // Verify total number of machines
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.number_of_total_machines", "1"),
+ // Verify machine catalog identity type
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.identity_type", "ActiveDirectory"),
+ ),
+ },
+
+ /****************** Application Folder Test ******************/
+ // Create and Read testing
+ {
+ Config: composeTestResourceTf(
+ BuildApplicationFolderResource(t, testApplicationFolderResource),
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_delete_machine, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
+ BuildZoneResource(t, zoneResourceUpdated, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify name of application
+ resource.TestCheckResourceAttr("citrix_application_folder.testApplicationFolder1", "name", folder_name_1),
+ // Verify name of application
+ resource.TestCheckResourceAttr("citrix_application_folder.testApplicationFolder2", "name", folder_name_2),
+ // Verify parent path of application
+ resource.TestCheckResourceAttr("citrix_application_folder.testApplicationFolder2", "parent_path", fmt.Sprintf("%s\\", folder_name_1)),
+ // Verify path of application
+ resource.TestCheckResourceAttr("citrix_application_folder.testApplicationFolder2", "path", fmt.Sprintf("%s\\%s\\", folder_name_1, folder_name_2)),
+ ),
+ },
+ // ImportState testing
+ {
+ ResourceName: "citrix_application_folder.testApplicationFolder2",
+ ImportState: true,
+ ImportStateVerify: true,
+ },
+ // Update and Read testing
+ {
+ Config: composeTestResourceTf(
+ BuildApplicationFolderResource(t, testApplicationFolderResource_updated),
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_delete_machine, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
+ BuildZoneResource(t, zoneResourceUpdated, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify name of application
+ resource.TestCheckResourceAttr("citrix_application_folder.testApplicationFolder1", "name", fmt.Sprintf("%s-updated", folder_name_1)),
+ // Verify parent path of application
+ resource.TestCheckResourceAttr("citrix_application_folder.testApplicationFolder2", "path", fmt.Sprintf("%s\\", folder_name_2)),
+ ),
+ },
+
+ /****************** Application Test / Policy Test / Admin Scope / Admin Role Test - In Parallel ******************/
+ // Create and Read testing
+ {
+ Config: composeTestResourceTf(
+ BuildAdminRoleResource(t, adminRoleTestResource),
+ BuildAdminScopeResource(t, adminScopeTestResource),
+ BuildPolicySetResource(t, policy_set_testResource),
+ BuildApplicationResource(t, testApplicationResource),
+ BuildApplicationFolderResource(t, testApplicationFolderResource_updated),
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_delete_machine, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
+ BuildZoneResource(t, zoneResourceUpdated, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ /*** Verify Application ***/
+ // Verify name of application
+ resource.TestCheckResourceAttr("citrix_application.testApplication", "name", applicationName),
+ // Verify description of application
+ resource.TestCheckResourceAttr("citrix_application.testApplication", "description", "Application for testing"),
+ // Verify the number of delivery groups
+ resource.TestCheckResourceAttr("citrix_application.testApplication", "delivery_groups.#", "1"),
+ // Verify the command line executable
+ resource.TestCheckResourceAttr("citrix_application.testApplication", "installed_app_properties.command_line_executable", "test.exe"),
+
+ /*** Verify Policy Set ***/
+ // Verify name of the policy set
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "name", os.Getenv("TEST_POLICY_SET_NAME")+"-1"),
+ // Verify description of the policy set
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "description", "Test policy set description"),
+ // Verify type of the policy set
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "type", "DeliveryGroupPolicies"),
+ // Verify the number of scopes of the policy set
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "scopes.#", "1"),
+ // Verify the scopes of the policy set
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "scopes.0", "All"),
+ // Verify the number of policies in the policy set
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "policies.#", "2"),
+ // Verify name of the first policy in the policy set
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "policies.0.name", "first-test-policy"),
+ // Verify policy settings of the first policy in the policy set
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "policies.0.policy_settings.#", "2"),
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "policies.0.policy_settings.0.name", "AdvanceWarningPeriod"),
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "policies.0.policy_settings.0.value", "13:00:00"),
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "policies.0.policy_settings.1.name", "AllowFileDownload"),
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "policies.0.policy_settings.1.enabled", "true"),
+ // Verify name of the second policy in the policy set
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "policies.1.name", "second-test-policy"),
+
+ /*** Verify Admin Scope ***/
+ // Verify the name of the admin scope
+ resource.TestCheckResourceAttr("citrix_admin_scope.test_scope", "name", adminScopeName),
+ // Verify the description of the admin scope
+ resource.TestCheckResourceAttr("citrix_admin_scope.test_scope", "description", "test scope created via terraform"),
+ // Verify number of scoped objects
+ resource.TestCheckResourceAttr("citrix_admin_scope.test_scope", "scoped_objects.#", "1"),
+ // Verify the scoped objects data
+ resource.TestCheckResourceAttr("citrix_admin_scope.test_scope", "scoped_objects.0.object_type", "DeliveryGroup"),
+ resource.TestCheckResourceAttr("citrix_admin_scope.test_scope", "scoped_objects.0.object", deliveryGroupName),
+
+ /*** Verify Admin Role ***/
+ // Verify the name of the admin role
+ resource.TestCheckResourceAttr("citrix_admin_role.test_role", "name", adminRoleName),
+ // Verify the description of the admin role
+ resource.TestCheckResourceAttr("citrix_admin_role.test_role", "description", "Test role created via terraform"),
+ // Verify the value of the can_launch_manage flag (Set to true by default)
+ resource.TestCheckResourceAttr("citrix_admin_role.test_role", "can_launch_manage", "true"),
+ // Verify the value of the can_launch_monitor flag (Set to true by default)
+ resource.TestCheckResourceAttr("citrix_admin_role.test_role", "can_launch_monitor", "true"),
+ // Verify the permissions list
+ resource.TestCheckResourceAttr("citrix_admin_role.test_role", "permissions.#", "2"),
+ resource.TestCheckResourceAttr("citrix_admin_role.test_role", "permissions.0", "Director_DismissAlerts"),
+ resource.TestCheckResourceAttr("citrix_admin_role.test_role", "permissions.1", "DesktopGroup_AddApplicationGroup"),
+ ),
+ },
+
+ // ImportState testing - Application
+ {
+ ResourceName: "citrix_application.testApplication",
+ ImportState: true,
+ ImportStateVerify: true,
+ // The last_updated attribute does not exist in the Orchestration
+ // API, therefore there is no value for it during import.
+ ImportStateVerifyIgnore: []string{"delivery_groups", "installed_app_properties"},
+ },
+ // ImportState testing - Policy Set
+ {
+ ResourceName: "citrix_policy_set.testPolicySet",
+ ImportState: true,
+ ImportStateVerify: true,
+ // The last_updated attribute does not exist in the Orchestration
+ // API, therefore there is no value for it during import.
+ ImportStateVerifyIgnore: []string{"last_updated"},
+ },
+ // ImportState testing - Admin Scope
+ {
+ ResourceName: "citrix_admin_scope.test_scope",
+ ImportState: true,
+ ImportStateVerify: true,
+ // The last_updated attribute does not exist in the Orchestration
+ // API, therefore there is no value for it during import.
+ ImportStateVerifyIgnore: []string{"last_updated"},
+ },
+ // ImportState testing - Admin Role
+ {
+ ResourceName: "citrix_admin_role.test_role",
+ ImportState: true,
+ ImportStateVerify: true,
+ // The last_updated attribute does not exist in the Orchestration
+ // API, therefore there is no value for it during import.
+ ImportStateVerifyIgnore: []string{"last_updated", "permissions"},
+ },
+
+ // Update and Read testing
+ {
+ Config: composeTestResourceTf(
+ BuildAdminRoleResource(t, adminRoleTestResource_updated),
+ BuildAdminScopeResource(t, adminScopeTestResource_updated),
+ BuildPolicySetResource(t, policy_set_updated_testResource),
+ BuildApplicationResource(t, testApplicationResource_updated),
+ BuildApplicationFolderResource(t, testApplicationFolderResource_updated),
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_delete_machine, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
+ BuildZoneResource(t, zoneResourceUpdated, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ /*** Verify Application ***/
+ // Verify name of application
+ resource.TestCheckResourceAttr("citrix_application.testApplication", "name", fmt.Sprintf("%s-updated", applicationName)),
+ // Verify description of application
+ resource.TestCheckResourceAttr("citrix_application.testApplication", "description", "Application for testing updated"),
+ // Verify the command line arguments
+ resource.TestCheckResourceAttr("citrix_application.testApplication", "installed_app_properties.command_line_arguments", "update test arguments"),
+ // Verify the command line executable
+ resource.TestCheckResourceAttr("citrix_application.testApplication", "installed_app_properties.command_line_executable", "updated_test.exe"),
+ // Verify the application folder path
+ resource.TestCheckResourceAttr("citrix_application.testApplication", "application_folder_path", fmt.Sprintf("%s\\", folder_name_2)),
+
+ /*** Verify Policy Set ***/
+ // Verify name of the policy set
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "name", os.Getenv("TEST_POLICY_SET_NAME")+"-3"),
+ // Verify description of the policy set
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "description", "Test policy set description updated"),
+ // Verify type of the policy set
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "type", "DeliveryGroupPolicies"),
+ // Verify the number of scopes of the policy set
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "scopes.#", "1"),
+ // Verify the scopes of the policy set
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "scopes.0", "All"),
+ // Verify the number of policies in the policy set
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "policies.#", "1"),
+ // Verify name of the second policy in the policy set
+ resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "policies.0.name", "first-test-policy"),
+
+ /*** Verify Admin Scope ***/
+ // Verify the name of the admin scope
+ resource.TestCheckResourceAttr("citrix_admin_scope.test_scope", "name", fmt.Sprintf("%s-updated", adminScopeName)),
+ // Verify the description of the admin scope
+ resource.TestCheckResourceAttr("citrix_admin_scope.test_scope", "description", "Updated description for test scope"),
+ // Verify number of scoped objects
+ resource.TestCheckResourceAttr("citrix_admin_scope.test_scope", "scoped_objects.#", "2"),
+ // Verify the scoped objects data
+ resource.TestCheckResourceAttr("citrix_admin_scope.test_scope", "scoped_objects.0.object_type", "DeliveryGroup"),
+ resource.TestCheckResourceAttr("citrix_admin_scope.test_scope", "scoped_objects.0.object", deliveryGroupName),
+ resource.TestCheckResourceAttr("citrix_admin_scope.test_scope", "scoped_objects.1.object_type", "MachineCatalog"),
+ resource.TestCheckResourceAttr("citrix_admin_scope.test_scope", "scoped_objects.1.object", machineCatalogName),
+
+ /*** Verify Admin Role ***/
+ // Verify the name of the admin role
+ resource.TestCheckResourceAttr("citrix_admin_role.test_role", "name", fmt.Sprintf("%s-updated", adminRoleName)),
+ // Verify the description of the admin role
+ resource.TestCheckResourceAttr("citrix_admin_role.test_role", "description", "Updated description for test role"),
+ // Verify the value of the can_launch_manage flag
+ resource.TestCheckResourceAttr("citrix_admin_role.test_role", "can_launch_manage", "true"),
+ // Verify the value of the can_launch_monitor flag
+ resource.TestCheckResourceAttr("citrix_admin_role.test_role", "can_launch_monitor", "true"),
+ // Verify the permissions list
+ resource.TestCheckResourceAttr("citrix_admin_role.test_role", "permissions.#", "3"),
+ resource.TestCheckResourceAttr("citrix_admin_role.test_role", "permissions.0", "Director_DismissAlerts"),
+ resource.TestCheckResourceAttr("citrix_admin_role.test_role", "permissions.1", "ApplicationGroup_AddScope"),
+ resource.TestCheckResourceAttr("citrix_admin_role.test_role", "permissions.2", "AppLib_AddPackage"),
+ ),
+ },
+
+ /****************** Admin User Test - On-Premises test only ******************/
+ // Create and Read testing
+ {
+ Config: composeTestResourceTf(
+ BuildAdminUserResource(t, adminUserTestResource),
+ BuildAdminRoleResource(t, adminRoleTestResource_updated),
+ BuildAdminScopeResource(t, adminScopeTestResource_updated),
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_delete_machine, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
+ BuildZoneResource(t, zoneResourceUpdated, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify the name of the admin user
+ resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "name", userName),
+ // Verify the domain of the admin use
+ resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "domain_name", userDomainName),
+ // Verify the rights object
+ resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "rights.#", "1"),
+ resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "rights.0.role", fmt.Sprintf("%s-updated", adminRoleName)),
+ resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "rights.0.scope", fmt.Sprintf("%s-updated", adminScopeName)),
+ // Verify the is_enabled flag
+ resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "is_enabled", "true"),
+ ),
+ SkipFunc: skipForCloud(isOnPremises),
+ },
+ // ImportState testing
+ {
+ ResourceName: "citrix_admin_user.test_admin_user",
+ ImportState: true,
+ ImportStateVerify: true,
+ // The last_updated attribute does not exist in the Orchestration
+ // API, therefore there is no value for it during import.
+ ImportStateVerifyIgnore: []string{"last_updated"},
+ },
+ // Update and Read testing
+ {
+ Config: composeTestResourceTf(
+ BuildAdminUserResource(t, adminUserTestResource_updated),
+ BuildAdminRoleResource(t, adminRoleTestResource_updated),
+ BuildAdminScopeResource(t, adminScopeTestResource_updated),
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources),
+ BuildPolicySetResourceWithoutDeliveryGroup(t),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_delete_machine, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
+ BuildZoneResource(t, zoneResourceUpdated, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify the name of the admin user
+ resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "name", userName),
+ // Verify the domain of the admin user
+ resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "domain_name", userDomainName),
+ // Verify the updated rights object
+ resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "rights.#", "2"),
+ resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "rights.0.role", fmt.Sprintf("%s-updated", adminRoleName)),
+ resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "rights.0.scope", fmt.Sprintf("%s-updated", adminScopeName)),
+ resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "rights.1.role", "Delivery Group Administrator"),
+ resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "rights.1.scope", fmt.Sprintf("%s-updated", adminScopeName)),
+ // Verify the is_enabled flag
+ resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "is_enabled", "true"),
+ ),
+ SkipFunc: skipForCloud(isOnPremises),
+ },
+ },
+ })
+}
+
+func composeAzureMachineCatalogTestResourceTf(t *testing.T, isOnPremises bool) string {
+ if isOnPremises {
+ return composeTestResourceTf(
+ BuildMachineCatalogResourceManualPowerManagedAzure(t, machinecatalog_testResources_manual_power_managed_azure),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure, "-HybAAD", "HybridAzureAD"),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
+ BuildZoneResource(t, zone_testResource_updated, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ )
+ }
+ return composeTestResourceTf(
+ BuildMachineCatalogResourceManualPowerManagedAzure(t, machinecatalog_testResources_manual_power_managed_azure),
+ BuildMachineCatalogResourceWorkgroup(t, machinecatalog_testResources_workgroup),
+ BuildMachineCatalogResourceAzureAd(t, machinecatalog_testResources_azure_ad),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure, "-HybAAD", "HybridAzureAD"),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ )
+}
+
+func composeCloudMachineCatalogTestVerification(isOnPremises bool, aadCatalogName, workgroupCatalogName string) resource.TestCheckFunc {
+ if isOnPremises {
+ // For OnPremises, do not return any cloud related test verification
+ return resource.ComposeAggregateTestCheckFunc()
+ }
+ return resource.ComposeAggregateTestCheckFunc(
+ /*** Verify MCS AAD Machine Catalog ***/
+ // Verify name of catalog
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AAD", "name", aadCatalogName),
+ // Verify domain FQDN
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AAD", "session_support", "MultiSession"),
+ // Verify machine catalog identity type
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AAD", "provisioning_scheme.identity_type", "AzureAD"),
+ // Verify nic network
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AAD", "provisioning_scheme.network_mapping.0.network", os.Getenv("TEST_MC_SUBNET")),
+
+ /*** Verify MCS Workgroup Machine Catalog ***/
+ // Verify name of catalog
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-WG", "name", workgroupCatalogName),
+ // Verify domain FQDN
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-WG", "session_support", "MultiSession"),
+ // Verify machine catalog identity type
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-WG", "provisioning_scheme.identity_type", "Workgroup"),
+ )
+}
diff --git a/internal/test/common.go b/internal/test/common.go
index 05c4e2d..2682d01 100644
--- a/internal/test/common.go
+++ b/internal/test/common.go
@@ -3,7 +3,7 @@
package test
// Used to skip a test case if environment is cloud
-func getSkipFunc(isOnPremises bool) func() (bool, error) {
+func skipForCloud(isOnPremises bool) func() (bool, error) {
return func() (bool, error) {
if isOnPremises {
return false, nil
@@ -12,3 +12,23 @@ func getSkipFunc(isOnPremises bool) func() (bool, error) {
return true, nil
}
}
+
+// Used to skip a test case if environment is cloud
+func skipForOnPrem(isOnPremises bool) func() (bool, error) {
+ return func() (bool, error) {
+ if isOnPremises {
+ return true, nil
+ }
+
+ return false, nil
+ }
+}
+
+// Used to aggregate arbitrary number of terraform resource blocks
+func composeTestResourceTf(resources ...string) string {
+ var result = ""
+ for _, resource := range resources {
+ result += resource
+ }
+ return result
+}
diff --git a/internal/test/delivery_group_test.go b/internal/test/delivery_group_test.go
index d3a80f8..ebd4aad 100644
--- a/internal/test/delivery_group_test.go
+++ b/internal/test/delivery_group_test.go
@@ -37,7 +37,14 @@ func TestDeliveryGroupResourceAzureRM(t *testing.T) {
// Create and Read testing
{
- Config: BuildDeliveryGroupResource(t, testDeliveryGroupResources),
+ Config: composeTestResourceTf(
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources),
+ BuildPolicySetResourceWithoutDeliveryGroup(t),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of delivery group
@@ -67,7 +74,14 @@ func TestDeliveryGroupResourceAzureRM(t *testing.T) {
// Update name, description and add machine testing
{
- Config: BuildDeliveryGroupResource(t, testDeliveryGroupResources_updated),
+ Config: composeTestResourceTf(
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources_updated),
+ BuildPolicySetResourceWithoutDeliveryGroup(t),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of delivery group
@@ -87,7 +101,14 @@ func TestDeliveryGroupResourceAzureRM(t *testing.T) {
// Remove machine testing
{
- Config: BuildDeliveryGroupResource(t, testDeliveryGroupResources),
+ Config: composeTestResourceTf(
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources),
+ BuildPolicySetResourceWithoutDeliveryGroup(t),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify total number of machines in delivery group
@@ -98,7 +119,14 @@ func TestDeliveryGroupResourceAzureRM(t *testing.T) {
},
// Update policy set testing
{
- Config: BuildDeliveryGroupResource(t, testDeliveryGroupResources_updatedWithPolicySetId),
+ Config: composeTestResourceTf(
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources_updatedWithPolicySetId),
+ BuildPolicySetResourceWithoutDeliveryGroup(t),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify the policy set id assigned to the delivery group
@@ -363,7 +391,7 @@ resource "citrix_policy_set" "testPolicySetWithoutDG" {
func BuildDeliveryGroupResource(t *testing.T, deliveryGroup string) string {
name := os.Getenv("TEST_DG_NAME")
- return BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "ActiveDirectory") + BuildPolicySetResourceWithoutDeliveryGroup(t) + fmt.Sprintf(deliveryGroup, name)
+ return fmt.Sprintf(deliveryGroup, name)
}
func BuildPolicySetResourceWithoutDeliveryGroup(t *testing.T) string {
diff --git a/internal/test/gac_settings_resource_test.go b/internal/test/gac_settings_resource_test.go
new file mode 100644
index 0000000..6e74ebf
--- /dev/null
+++ b/internal/test/gac_settings_resource_test.go
@@ -0,0 +1,277 @@
+// Copyright © 2023. Citrix Systems, Inc.
+
+package test
+
+import (
+ "fmt"
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+func TestGacSettingsPreCheck(t *testing.T) {
+ if service_url := os.Getenv("TEST_SETTINGS_CONFIG_SERVICE_URL"); service_url == "" {
+ t.Fatal("TEST_SETTINGS_CONFIG_SERVICE_URL must be set for acceptance tests")
+ }
+ if name := os.Getenv("TEST_SETTINGS_CONFIG_NAME"); name == "" {
+ t.Fatal("TEST_SETTINGS_CONFIG_NAME must be set for acceptance tests")
+ }
+}
+
+func TestGacSettingsResource(t *testing.T) {
+ name := os.Getenv("TEST_SETTINGS_CONFIG_NAME")
+ service_url := os.Getenv("TEST_SETTINGS_CONFIG_SERVICE_URL")
+
+ resource.Test(t, resource.TestCase{
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ PreCheck: func() {
+ TestProviderPreCheck(t)
+ TestGacSettingsPreCheck(t)
+ },
+ Steps: []resource.TestStep{
+ // Create and Read testing
+ {
+ Config: BuildGacSettingsResource(t, gacSettingsTestResource),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify the service url
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "service_url", service_url),
+ // Verify the name
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "name", name),
+ // Verify the description
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "description", "This is a test resource"),
+ // Check permissions for Windows
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.#", "1"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.0.category", "ICA Client"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.0.user_override", "false"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.0.settings.#", "1"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.0.settings.0.name", "Allow Client Clipboard Redirection"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.0.settings.0.value_string", "true"),
+ // Check permissions for HTML5
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.html5.#", "1"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.html5.0.category", "Virtual Channel"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.html5.0.user_override", "false"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.html5.0.settings.#", "1"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.html5.0.settings.0.name", "Clipboard Operations Between VDA And Local Device"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.html5.0.settings.0.value_string", "true"),
+ // Check permissions for ChromeOS
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.chromeos.#", "1"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.chromeos.0.category", "Virtual Channel"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.chromeos.0.user_override", "false"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.chromeos.0.settings.#", "1"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.chromeos.0.settings.0.name", "Clipboard Operations Between VDA And Local Device"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.chromeos.0.settings.0.value_string", "true"),
+ // Check permissions for Android
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.android.#", "1"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.android.0.category", "advanced"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.android.0.user_override", "false"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.android.0.settings.#", "1"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.android.0.settings.0.name", "enable clipboard"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.android.0.settings.0.value_string", "true"),
+ ),
+ },
+ // ImportState testing
+ {
+ ResourceName: "citrix_gac_settings.test_settings_configuration",
+ ImportState: true,
+ ImportStateId: service_url,
+ ImportStateVerify: true,
+ ImportStateVerifyIdentifierAttribute: "service_url",
+ },
+ // Update and Read testing
+ {
+ Config: BuildGacSettingsResource(t, gacSettingsTestResource_updated),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify the service url
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "service_url", service_url),
+ // Verify the name
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "name", fmt.Sprintf("%s - Updated", name)),
+ // Verify the description
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "description", "Updated description for test resource"),
+ // Check permissions for Windows
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.#", "2"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.0.category", "ICA Client"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.0.user_override", "false"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.0.settings.#", "1"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.0.settings.0.name", "Allow Client Clipboard Redirection"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.0.settings.0.value_string", "true"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.1.category", "Browser"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.1.user_override", "false"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.1.settings.#", "2"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.1.settings.0.name", "delete browsing data on exit"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.1.settings.0.value_list.#", "2"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.1.settings.0.value_list.0", "browsing_history"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.1.settings.0.value_list.1", "download_history"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.1.settings.1.name", "relaunch notification period"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.windows.1.settings.1.value_string", "3600000"),
+ // Check permissions for HTML5
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.html5.#", "1"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.html5.0.category", "Virtual Channel"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.html5.0.user_override", "false"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.html5.0.settings.#", "1"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.html5.0.settings.0.name", "Clipboard Operations Between VDA And Local Device"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.html5.0.settings.0.value_string", "true"),
+ // Check permissions for iOS
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.ios.#", "1"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.ios.0.category", "Audio"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.ios.0.user_override", "false"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.ios.0.settings.#", "1"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.ios.0.settings.0.name", "audio"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.ios.0.settings.0.value_string", "true"),
+ // Check permissions for MacOS
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.macos.#", "1"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.macos.0.category", "ica client"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.macos.0.user_override", "false"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.macos.0.settings.#", "1"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.macos.0.settings.0.name", "Reconnect Apps and Desktops"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.macos.0.settings.0.value_list.#", "2"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.macos.0.settings.0.value_list.0", "startWorkspace"),
+ resource.TestCheckResourceAttr("citrix_gac_settings.test_settings_configuration", "app_settings.macos.0.settings.0.value_list.1", "refreshApps"),
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ },
+ })
+}
+
+var (
+ gacSettingsTestResource = `
+ resource "citrix_gac_settings" "test_settings_configuration" {
+ service_url = "%s"
+ name = "%s"
+ description = "This is a test resource"
+ app_settings = {
+ windows = [
+ {
+ category = "ICA Client",
+ user_override = false,
+ settings = [
+ {
+ name = "Allow Client Clipboard Redirection",
+ value_string = "true"
+ }
+ ]
+ },
+ ],
+ html5 = [
+ {
+ category = "Virtual Channel",
+ user_override = false,
+ settings = [
+ {
+ name = "Clipboard Operations Between VDA And Local Device",
+ value_string = "true"
+ }
+ ]
+ }
+ ],
+ chromeos = [
+ {
+ category = "Virtual Channel",
+ user_override = false,
+ settings = [
+ {
+ name = "Clipboard Operations Between VDA And Local Device",
+ value_string = "true"
+ }
+ ]
+ }
+ ],
+ android = [
+ {
+ category = "advanced",
+ user_override = false,
+ settings = [
+ {
+ name = "enable clipboard",
+ value_string = "true"
+ }
+ ]
+ }
+ ]
+ }
+ }
+ `
+ gacSettingsTestResource_updated = `
+ resource "citrix_gac_settings" "test_settings_configuration" {
+ service_url = "%s"
+ name = "%s - Updated"
+ description = "Updated description for test resource"
+ app_settings = {
+ windows = [
+ {
+ user_override = false,
+ category = "ICA Client",
+ settings = [
+ {
+ name = "Allow Client Clipboard Redirection",
+ value_string = "true"
+ }
+ ]
+ },
+ {
+ user_override = false,
+ category = "Browser",
+ settings = [
+ {
+ name = "delete browsing data on exit",
+ value_list = [
+ "browsing_history",
+ "download_history"
+ ]
+ },
+ {
+ name = "relaunch notification period",
+ value_string = "3600000"
+ }
+ ]
+ }
+ ],
+ html5 = [
+ {
+ category = "Virtual Channel",
+ user_override = false,
+ settings = [
+ {
+ name = "Clipboard Operations Between VDA And Local Device",
+ value_string = "true"
+ }
+ ]
+ }
+ ],
+ ios = [
+ {
+ category = "Audio",
+ user_override = false,
+ settings = [
+ {
+ name = "audio",
+ value_string = "true"
+ }
+ ]
+ }
+ ],
+ macos = [
+ {
+ category = "ica client",
+ user_override = false,
+ settings = [
+ {
+ name = "Reconnect Apps and Desktops",
+ value_list = [
+ "startWorkspace",
+ "refreshApps"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ }
+ `
+)
+
+func BuildGacSettingsResource(t *testing.T, settings string) string {
+ val := fmt.Sprintf(settings, os.Getenv("TEST_SETTINGS_CONFIG_SERVICE_URL"), os.Getenv("TEST_SETTINGS_CONFIG_NAME"))
+ return val
+}
diff --git a/internal/test/hypervisor_resource_pool_test.go b/internal/test/hypervisor_resource_pool_test.go
index f556d54..bfabd9f 100644
--- a/internal/test/hypervisor_resource_pool_test.go
+++ b/internal/test/hypervisor_resource_pool_test.go
@@ -44,7 +44,11 @@ func TestHypervisorResourcePoolAzureRM(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ Config: composeTestResourceTf(
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("citrix_azure_hypervisor_resource_pool.testHypervisorResourcePool", "name", name),
@@ -68,7 +72,11 @@ func TestHypervisorResourcePoolAzureRM(t *testing.T) {
},
// Update and Read
{
- Config: BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
+ Config: composeTestResourceTf(
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("citrix_azure_hypervisor_resource_pool.testHypervisorResourcePool", "name", fmt.Sprintf("%s-updated", name)),
),
@@ -108,7 +116,11 @@ func TestHypervisorResourcePoolGCP(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildHypervisorResourcePoolResourceGCP(t, hypervisor_resource_pool_testResource_gcp),
+ Config: composeTestResourceTf(
+ BuildHypervisorResourcePoolResourceGCP(t, hypervisor_resource_pool_testResource_gcp),
+ BuildHypervisorResourceGCP(t, hypervisor_testResources_gcp),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_GCP")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("citrix_gcp_hypervisor_resource_pool.testHypervisorResourcePool", "name", name),
@@ -131,7 +143,11 @@ func TestHypervisorResourcePoolGCP(t *testing.T) {
},
// Update and Read
{
- Config: BuildHypervisorResourcePoolResourceGCP(t, hypervisor_resource_pool_updated_testResource_gcp),
+ Config: composeTestResourceTf(
+ BuildHypervisorResourcePoolResourceGCP(t, hypervisor_resource_pool_updated_testResource_gcp),
+ BuildHypervisorResourceGCP(t, hypervisor_testResources_gcp),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_GCP")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("citrix_gcp_hypervisor_resource_pool.testHypervisorResourcePool", "name", fmt.Sprintf("%s-updated", name)),
),
@@ -171,7 +187,11 @@ func TestHypervisorResourcePoolXenserver(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildHypervisorResourcePoolResourceXenServer(t),
+ Config: composeTestResourceTf(
+ BuildHypervisorResourcePoolResourceXenServer(t, hypervisor_resource_pool_testResource_xenserver),
+ BuildHypervisorResourceXenserver(t, hypervisor_testResources_xenserver),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_XENSERVER")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("citrix_xenserver_hypervisor_resource_pool.testHypervisorResourcePool", "name", name),
@@ -195,7 +215,11 @@ func TestHypervisorResourcePoolXenserver(t *testing.T) {
},
// Update and Read
{
- Config: BuildHypervisorResourcePoolResourceXenServerUpdated(t),
+ Config: composeTestResourceTf(
+ BuildHypervisorResourcePoolResourceXenServerUpdated(t, hypervisor_resource_pool_updated_testResource_xenserver),
+ BuildHypervisorResourceXenserver(t, hypervisor_testResources_xenserver),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_XENSERVER")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("citrix_xenserver_hypervisor_resource_pool.testHypervisorResourcePool", "name", fmt.Sprintf("%s-updated", name)),
resource.TestCheckResourceAttr("citrix_xenserver_hypervisor_resource_pool.testHypervisorResourcePool", "networks.#", "2"),
@@ -242,7 +266,11 @@ func TestHypervisorResourcePoolVsphere(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildHypervisorResourcePoolResourceVsphere(t),
+ Config: composeTestResourceTf(
+ BuildHypervisorResourcePoolResourceVsphere(t, hypervisor_resource_pool_testResource_vsphere),
+ BuildHypervisorResourceVsphere(t, hypervisor_testResources_vsphere),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_VSPHERE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("citrix_vsphere_hypervisor_resource_pool.testHypervisorResourcePool", "name", name),
@@ -267,7 +295,11 @@ func TestHypervisorResourcePoolVsphere(t *testing.T) {
},
// Update and Read
{
- Config: BuildHypervisorResourcePoolResourceVsphereUpdated(t),
+ Config: composeTestResourceTf(
+ BuildHypervisorResourcePoolResourceVsphereUpdated(t, hypervisor_resource_pool_updated_testResource_vsphere),
+ BuildHypervisorResourceVsphere(t, hypervisor_testResources_vsphere),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_VSPHERE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("citrix_vsphere_hypervisor_resource_pool.testHypervisorResourcePool", "name", fmt.Sprintf("%s-updated", name)),
resource.TestCheckResourceAttr("citrix_vsphere_hypervisor_resource_pool.testHypervisorResourcePool", "storage.#", "2"),
@@ -299,7 +331,11 @@ func TestHypervisorResourcePoolNutanix(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildHypervisorResourcePoolResourceNutanix(t, hypervisor_resource_pool_testResource_nutanix),
+ Config: composeTestResourceTf(
+ BuildHypervisorResourcePoolResourceNutanix(t, hypervisor_resource_pool_testResource_nutanix),
+ BuildHypervisorResourceNutanix(t, hypervisor_testResources_nutanix),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_NUTANIX")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("citrix_nutanix_hypervisor_resource_pool.testHypervisorResourcePool", "name", name),
@@ -317,7 +353,11 @@ func TestHypervisorResourcePoolNutanix(t *testing.T) {
},
// Update and Read
{
- Config: BuildHypervisorResourcePoolResourceNutanix(t, hypervisor_resource_pool_updated_testResource_nutanix),
+ Config: composeTestResourceTf(
+ BuildHypervisorResourcePoolResourceNutanix(t, hypervisor_resource_pool_updated_testResource_nutanix),
+ BuildHypervisorResourceNutanix(t, hypervisor_testResources_nutanix),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_NUTANIX")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("citrix_nutanix_hypervisor_resource_pool.testHypervisorResourcePool", "name", fmt.Sprintf("%s-updated", name)),
),
@@ -354,7 +394,11 @@ func TestHypervisorResourcePoolAwsEc2(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildHypervisorResourcePoolResourceAwsEc2(t, hypervisor_resource_pool_testResource_aws_ec2),
+ Config: composeTestResourceTf(
+ BuildHypervisorResourcePoolResourceAwsEc2(t, hypervisor_resource_pool_testResource_aws_ec2),
+ BuildHypervisorResourceAwsEc2(t, hypervisor_testResources_aws_ec2),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AWS_EC2")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("citrix_aws_hypervisor_resource_pool.testHypervisorResourcePool", "name", name),
@@ -373,7 +417,11 @@ func TestHypervisorResourcePoolAwsEc2(t *testing.T) {
},
// Update and Read
{
- Config: BuildHypervisorResourcePoolResourceAwsEc2(t, hypervisor_resource_pool_updated_testResource_aws_ec2),
+ Config: composeTestResourceTf(
+ BuildHypervisorResourcePoolResourceAwsEc2(t, hypervisor_resource_pool_updated_testResource_aws_ec2),
+ BuildHypervisorResourceAwsEc2(t, hypervisor_testResources_aws_ec2),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AWS_EC2")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("citrix_aws_hypervisor_resource_pool.testHypervisorResourcePool", "name", fmt.Sprintf("%s-updated", name)),
),
@@ -620,7 +668,7 @@ func BuildHypervisorResourcePoolResourceAzure(t *testing.T, hypervisorRP string)
virtualNetwork := os.Getenv("TEST_HYPERV_RP_VIRTUAL_NETWORK")
subnet := os.Getenv("Test_HYPERV_RP_SUBNETS")
- return BuildHypervisorResourceAzure(t, hypervisor_testResources) + fmt.Sprintf(hypervisorRP, name, region, virtualNetworkResourceGroup, virtualNetwork, subnet)
+ return fmt.Sprintf(hypervisorRP, name, region, virtualNetworkResourceGroup, virtualNetwork, subnet)
}
func BuildHypervisorResourcePoolResourceGCP(t *testing.T, hypervisorRP string) string {
@@ -630,29 +678,29 @@ func BuildHypervisorResourcePoolResourceGCP(t *testing.T, hypervisorRP string) s
projectName := os.Getenv("TEST_HYPERV_RP_PROJECT_NAME_GCP")
vpc := os.Getenv("TEST_HYPERV_RP_VPC_GCP")
- return BuildHypervisorResourceGCP(t, hypervisor_testResources_gcp) + fmt.Sprintf(hypervisorRP, name, projectName, region, subnet, vpc)
+ return fmt.Sprintf(hypervisorRP, name, projectName, region, subnet, vpc)
}
-func BuildHypervisorResourcePoolResourceXenServer(t *testing.T) string {
+func BuildHypervisorResourcePoolResourceXenServer(t *testing.T, hypervisorRP string) string {
name := os.Getenv("TEST_HYPERV_RP_NAME_XENSERVER")
network1 := os.Getenv("TEST_HYPERV_RP_NETWORK_1_XENSERVER")
storage := os.Getenv("TEST_HYPERV_RP_STORAGE_XENSERVER")
tempStorage := os.Getenv("TEST_HYPERV_RP_TEMP_STORAGE_XENSERVER")
- return BuildHypervisorResourceXenserver(t, hypervisor_testResources_xenserver) + fmt.Sprintf(hypervisor_resource_pool_testResource_xenserver, name, network1, storage, tempStorage)
+ return fmt.Sprintf(hypervisorRP, name, network1, storage, tempStorage)
}
-func BuildHypervisorResourcePoolResourceXenServerUpdated(t *testing.T) string {
+func BuildHypervisorResourcePoolResourceXenServerUpdated(t *testing.T, hypervisorRP string) string {
name := os.Getenv("TEST_HYPERV_RP_NAME_XENSERVER")
network1 := os.Getenv("TEST_HYPERV_RP_NETWORK_1_XENSERVER")
network2 := os.Getenv("TEST_HYPERV_RP_NETWORK_2_XENSERVER")
storage := os.Getenv("TEST_HYPERV_RP_STORAGE_XENSERVER")
tempStorage := os.Getenv("TEST_HYPERV_RP_TEMP_STORAGE_XENSERVER")
- return BuildHypervisorResourceXenserver(t, hypervisor_testResources_xenserver) + fmt.Sprintf(hypervisor_resource_pool_updated_testResource_xenserver, name, network1, network2, storage, tempStorage)
+ return fmt.Sprintf(hypervisorRP, name, network1, network2, storage, tempStorage)
}
-func BuildHypervisorResourcePoolResourceVsphere(t *testing.T) string {
+func BuildHypervisorResourcePoolResourceVsphere(t *testing.T, hypervisorRP string) string {
name := os.Getenv("TEST_HYPERV_RP_NAME_VSPHERE")
datacenter := os.Getenv("TEST_HYPERV_RP_DATACENTER_VSPHERE")
host := os.Getenv("TEST_HYPERV_RP_HOST_VSPHERE")
@@ -660,10 +708,10 @@ func BuildHypervisorResourcePoolResourceVsphere(t *testing.T) string {
storage_1 := os.Getenv("TEST_HYPERV_RP_STORAGE_1_VSPHERE")
tempStorage := os.Getenv("TEST_HYPERV_RP_TEMP_STORAGE_VSPHERE")
- return BuildHypervisorResourceVsphere(t, hypervisor_testResources_vsphere) + fmt.Sprintf(hypervisor_resource_pool_testResource_vsphere, name, datacenter, host, network, storage_1, tempStorage)
+ return fmt.Sprintf(hypervisorRP, name, datacenter, host, network, storage_1, tempStorage)
}
-func BuildHypervisorResourcePoolResourceVsphereUpdated(t *testing.T) string {
+func BuildHypervisorResourcePoolResourceVsphereUpdated(t *testing.T, hypervisorRP string) string {
name := os.Getenv("TEST_HYPERV_RP_NAME_VSPHERE")
datacenter := os.Getenv("TEST_HYPERV_RP_DATACENTER_VSPHERE")
host := os.Getenv("TEST_HYPERV_RP_HOST_VSPHERE")
@@ -672,21 +720,21 @@ func BuildHypervisorResourcePoolResourceVsphereUpdated(t *testing.T) string {
storage_2 := os.Getenv("TEST_HYPERV_RP_STORAGE_2_VSPHERE")
tempStorage := os.Getenv("TEST_HYPERV_RP_TEMP_STORAGE_VSPHERE")
- return BuildHypervisorResourceVsphere(t, hypervisor_testResources_vsphere) + fmt.Sprintf(hypervisor_resource_pool_updated_testResource_vsphere, name, datacenter, host, network, storage_1, storage_2, tempStorage)
+ return fmt.Sprintf(hypervisorRP, name, datacenter, host, network, storage_1, storage_2, tempStorage)
}
-func BuildHypervisorResourcePoolResourceNutanix(t *testing.T, hypervisorRp string) string {
+func BuildHypervisorResourcePoolResourceNutanix(t *testing.T, hypervisorRP string) string {
name := os.Getenv("TEST_HYPERV_RP_NAME_NUTANIX")
network := os.Getenv("TEST_HYPERV_RP_NETWORK_NUTANIX")
- return BuildHypervisorResourceNutanix(t, hypervisor_testResources_nutanix) + fmt.Sprintf(hypervisorRp, name, network)
+ return fmt.Sprintf(hypervisorRP, name, network)
}
-func BuildHypervisorResourcePoolResourceAwsEc2(t *testing.T, hypervisorRp string) string {
+func BuildHypervisorResourcePoolResourceAwsEc2(t *testing.T, hypervisorRP string) string {
name := os.Getenv("TEST_HYPERV_RP_NAME_AWS_EC2")
vpc := os.Getenv("TEST_HYPERV_RP_VPC_AWS_EC2")
availability_zone := os.Getenv("TEST_HYPERV_RP_AVAILABILITY_ZONE_AWS_EC2")
subnets := os.Getenv("Test_HYPERV_RP_SUBNETS_AWS_EC2")
- return BuildHypervisorResourceAwsEc2(t, hypervisor_testResources_aws_ec2) + fmt.Sprintf(hypervisorRp, name, vpc, availability_zone, subnets)
+ return fmt.Sprintf(hypervisorRP, name, vpc, availability_zone, subnets)
}
diff --git a/internal/test/hypervisor_resource_test.go b/internal/test/hypervisor_resource_test.go
index 1c9afbf..9cda420 100644
--- a/internal/test/hypervisor_resource_test.go
+++ b/internal/test/hypervisor_resource_test.go
@@ -46,7 +46,7 @@ func TestHypervisorResourceAzureRM(t *testing.T) {
// Create and Read testing
{
- Config: BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ Config: composeTestResourceTf(BuildHypervisorResourceAzure(t, hypervisor_testResources), BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE"))),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of hypervisor
@@ -65,7 +65,7 @@ func TestHypervisorResourceAzureRM(t *testing.T) {
},
// Update and Read testing
{
- Config: BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
+ Config: composeTestResourceTf(BuildHypervisorResourceAzure(t, hypervisor_testResources_updated), BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE"))),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of hypervisor
resource.TestCheckResourceAttr("citrix_azure_hypervisor.testHypervisor", "name", fmt.Sprintf("%s-updated", name)),
@@ -103,8 +103,7 @@ func TestHypervisorResourceGCP(t *testing.T) {
// Create and Read testing
{
- Config: BuildHypervisorResourceGCP(t, hypervisor_testResources_gcp),
-
+ Config: composeTestResourceTf(BuildHypervisorResourceGCP(t, hypervisor_testResources_gcp), BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_GCP"))),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of hypervisor
resource.TestCheckResourceAttr("citrix_gcp_hypervisor.testHypervisor", "name", name),
@@ -122,7 +121,7 @@ func TestHypervisorResourceGCP(t *testing.T) {
},
// Update and Read testing
{
- Config: BuildHypervisorResourceGCP(t, hypervisor_testResources_updated_gcp),
+ Config: composeTestResourceTf(BuildHypervisorResourceGCP(t, hypervisor_testResources_updated_gcp), BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_GCP"))),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of hypervisor
resource.TestCheckResourceAttr("citrix_gcp_hypervisor.testHypervisor", "name", fmt.Sprintf("%s-updated", name)),
@@ -167,7 +166,7 @@ func TestHypervisorResourceVsphere(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildHypervisorResourceVsphere(t, hypervisor_testResources_vsphere),
+ Config: composeTestResourceTf(BuildHypervisorResourceVsphere(t, hypervisor_testResources_vsphere), BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_VSPHERE"))),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of hypervisor
resource.TestCheckResourceAttr("citrix_vsphere_hypervisor.testHypervisor", "name", name),
@@ -188,7 +187,7 @@ func TestHypervisorResourceVsphere(t *testing.T) {
},
// Update and Read testing
{
- Config: BuildHypervisorResourceVsphere(t, hypervisor_testResources_updated_vsphere),
+ Config: composeTestResourceTf(BuildHypervisorResourceVsphere(t, hypervisor_testResources_updated_vsphere), BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_VSPHERE"))),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of hypervisor
resource.TestCheckResourceAttr("citrix_vsphere_hypervisor.testHypervisor", "name", fmt.Sprintf("%s-updated", name)),
@@ -232,7 +231,7 @@ func TestHypervisorResourceXenserver(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildHypervisorResourceXenserver(t, hypervisor_testResources_xenserver),
+ Config: composeTestResourceTf(BuildHypervisorResourceXenserver(t, hypervisor_testResources_xenserver), BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_XENSERVER"))),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of hypervisor
resource.TestCheckResourceAttr("citrix_xenserver_hypervisor.testHypervisor", "name", name),
@@ -253,7 +252,7 @@ func TestHypervisorResourceXenserver(t *testing.T) {
},
// Update and Read testing
{
- Config: BuildHypervisorResourceXenserver(t, hypervisor_testResources_updated_xenserver),
+ Config: composeTestResourceTf(BuildHypervisorResourceXenserver(t, hypervisor_testResources_updated_xenserver), BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_XENSERVER"))),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of hypervisor
resource.TestCheckResourceAttr("citrix_xenserver_hypervisor.testHypervisor", "name", fmt.Sprintf("%s-updated", name)),
@@ -294,7 +293,7 @@ func TestHypervisorResourceNutanix(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildHypervisorResourceNutanix(t, hypervisor_testResources_nutanix),
+ Config: composeTestResourceTf(BuildHypervisorResourceNutanix(t, hypervisor_testResources_nutanix), BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_NUTANIX"))),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of hypervisor
resource.TestCheckResourceAttr("citrix_nutanix_hypervisor.testHypervisor", "name", name),
@@ -313,7 +312,7 @@ func TestHypervisorResourceNutanix(t *testing.T) {
},
// Update and Read testing
{
- Config: BuildHypervisorResourceNutanix(t, hypervisor_testResources_updated_nutanix),
+ Config: composeTestResourceTf(BuildHypervisorResourceNutanix(t, hypervisor_testResources_updated_nutanix), BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_NUTANIX"))),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of hypervisor
resource.TestCheckResourceAttr("citrix_nutanix_hypervisor.testHypervisor", "name", fmt.Sprintf("%s-updated", name)),
@@ -353,7 +352,7 @@ func TestHypervisorResourceAwsEc2(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildHypervisorResourceAwsEc2(t, hypervisor_testResources_aws_ec2),
+ Config: composeTestResourceTf(BuildHypervisorResourceAwsEc2(t, hypervisor_testResources_aws_ec2), BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AWS_EC2"))),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of hypervisor
resource.TestCheckResourceAttr("citrix_aws_hypervisor.testHypervisor", "name", name),
@@ -370,7 +369,7 @@ func TestHypervisorResourceAwsEc2(t *testing.T) {
},
// Update and Read testing
{
- Config: BuildHypervisorResourceAwsEc2(t, hypervisor_testResources_updated_aws_ec2),
+ Config: composeTestResourceTf(BuildHypervisorResourceAwsEc2(t, hypervisor_testResources_updated_aws_ec2), BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AWS_EC2"))),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of hypervisor
resource.TestCheckResourceAttr("citrix_aws_hypervisor.testHypervisor", "name", fmt.Sprintf("%s-updated", name)),
@@ -558,8 +557,7 @@ func BuildHypervisorResourceAzure(t *testing.T, hypervisor string) string {
applicationId := os.Getenv("TEST_HYPERV_APPLICATION_ID")
zoneValueForHypervisor := "citrix_zone.test.id"
- zoneNameAzure := os.Getenv("TEST_ZONE_NAME_AZURE")
- return BuildZoneResource(t, zone_testResource, zoneNameAzure) + fmt.Sprintf(hypervisor, name, zoneValueForHypervisor, tenantId, subscriptionId, applicationSecret, applicationId)
+ return fmt.Sprintf(hypervisor, name, zoneValueForHypervisor, tenantId, subscriptionId, applicationSecret, applicationId)
}
func BuildHypervisorResourceGCP(t *testing.T, hypervisor string) string {
@@ -567,9 +565,7 @@ func BuildHypervisorResourceGCP(t *testing.T, hypervisor string) string {
serviceAccountId := os.Getenv("TEST_HYPERV_SERVICE_ACCOUNT_ID")
serviceAccountCredential := os.Getenv("TEST_HYPERV_SERVICE_ACCOUNT_CREDENTIAL")
zoneValueForHypervisor := "citrix_zone.test.id"
- zoneNameGCP := os.Getenv("TEST_ZONE_NAME_GCP")
- resource := BuildZoneResource(t, zone_testResource, zoneNameGCP) + fmt.Sprintf(hypervisor, name, zoneValueForHypervisor, serviceAccountId, serviceAccountCredential)
- return resource
+ return fmt.Sprintf(hypervisor, name, zoneValueForHypervisor, serviceAccountId, serviceAccountCredential)
}
func BuildHypervisorResourceVsphere(t *testing.T, hypervisor string) string {
@@ -579,8 +575,7 @@ func BuildHypervisorResourceVsphere(t *testing.T, hypervisor string) string {
address := os.Getenv("TEST_HYPERV_ADDRESS_VSPHERE")
ssl_thumbprint := os.Getenv("TEST_HYPERV_SSL_THUMBPRINT_VSPHERE")
zoneValueForHypervisor := "citrix_zone.test.id"
- zoneNameVsphere := os.Getenv("TEST_ZONE_NAME_VSPHERE")
- return BuildZoneResource(t, zone_testResource, zoneNameVsphere) + fmt.Sprintf(hypervisor, name, zoneValueForHypervisor, username, password, address, ssl_thumbprint)
+ return fmt.Sprintf(hypervisor, name, zoneValueForHypervisor, username, password, address, ssl_thumbprint)
}
func BuildHypervisorResourceXenserver(t *testing.T, hypervisor string) string {
@@ -590,8 +585,7 @@ func BuildHypervisorResourceXenserver(t *testing.T, hypervisor string) string {
address := os.Getenv("TEST_HYPERV_ADDRESS_XENSERVER")
ssl_thumbprint := os.Getenv("TEST_HYPERV_SSL_THUMBPRINT_XENSERVER")
zoneValueForHypervisor := "citrix_zone.test.id"
- zoneNameXenserver := os.Getenv("TEST_ZONE_NAME_XENSERVER")
- return BuildZoneResource(t, zone_testResource, zoneNameXenserver) + fmt.Sprintf(hypervisor, name, zoneValueForHypervisor, username, password, address, ssl_thumbprint)
+ return fmt.Sprintf(hypervisor, name, zoneValueForHypervisor, username, password, address, ssl_thumbprint)
}
func BuildHypervisorResourceNutanix(t *testing.T, hypervisor string) string {
@@ -600,8 +594,7 @@ func BuildHypervisorResourceNutanix(t *testing.T, hypervisor string) string {
password := os.Getenv("TEST_HYPERV_PASSWORD_PLAINTEXT_NUTANIX")
address := os.Getenv("TEST_HYPERV_ADDRESS_NUTANIX")
zoneValueForHypervisor := "citrix_zone.test.id"
- zoneNameNutanix := os.Getenv("TEST_ZONE_NAME_NUTANIX")
- return BuildZoneResource(t, zone_testResource, zoneNameNutanix) + fmt.Sprintf(hypervisor, name, zoneValueForHypervisor, username, password, address)
+ return fmt.Sprintf(hypervisor, name, zoneValueForHypervisor, username, password, address)
}
func BuildHypervisorResourceAwsEc2(t *testing.T, hypervisor string) string {
@@ -609,7 +602,6 @@ func BuildHypervisorResourceAwsEc2(t *testing.T, hypervisor string) string {
api_key := os.Getenv("TEST_HYPERV_API_KEY_AWS_EC2")
secret_key := os.Getenv("TEST_HYPERV_SECRET_KEY_AWS_EC2")
region := os.Getenv("TEST_HYPERV_REGION_AWS_EC2")
- zoneNameAwsEc2 := os.Getenv("TEST_ZONE_NAME_AWS_EC2")
zoneValueForHypervisor := "citrix_zone.test.id"
- return BuildZoneResource(t, zone_testResource, zoneNameAwsEc2) + fmt.Sprintf(hypervisor, name, zoneValueForHypervisor, api_key, secret_key, region)
+ return fmt.Sprintf(hypervisor, name, zoneValueForHypervisor, api_key, secret_key, region)
}
diff --git a/internal/test/machine_catalog_resource_test.go b/internal/test/machine_catalog_resource_test.go
index dc4bc78..f8c63ba 100644
--- a/internal/test/machine_catalog_resource_test.go
+++ b/internal/test/machine_catalog_resource_test.go
@@ -59,23 +59,28 @@ func TestActiveDirectoryMachineCatalogResourceAzure(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure, "ActiveDirectory"),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure, "-AD", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of catalog
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AD", "name", name),
// Verify domain FQDN
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "session_support", "MultiSession"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AD", "session_support", "MultiSession"),
// Verify domain admin username
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.machine_domain_identity.service_account", os.Getenv("TEST_MC_SERVICE_ACCOUNT")),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AD", "provisioning_scheme.machine_domain_identity.service_account", os.Getenv("TEST_MC_SERVICE_ACCOUNT")),
// Verify machine catalog identity type
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.identity_type", "ActiveDirectory"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AD", "provisioning_scheme.identity_type", "ActiveDirectory"),
// Verify nic network
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.network_mapping.network", os.Getenv("TEST_MC_SUBNET")),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AD", "provisioning_scheme.network_mapping.network", os.Getenv("TEST_MC_SUBNET")),
),
},
// ImportState testing
{
- ResourceName: "citrix_machine_catalog.testMachineCatalog",
+ ResourceName: "citrix_machine_catalog.testMachineCatalog-AD",
ImportState: true,
ImportStateVerify: true,
// The last_updated attribute does not exist in the Orchestration
@@ -84,30 +89,40 @@ func TestActiveDirectoryMachineCatalogResourceAzure(t *testing.T) {
},
//Update description, master image and add machine test
{
- Config: BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "ActiveDirectory"),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "-AD", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify updated name of catalog
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AD", "name", name),
// Verify updated description
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "description", "updatedCatalog"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AD", "description", "updatedCatalog"),
// Verify updated image
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.azure_machine_config.azure_master_image.master_image", os.Getenv("TEST_MC_MASTER_IMAGE_UPDATED")),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AD", "provisioning_scheme.azure_machine_config.azure_master_image.master_image", os.Getenv("TEST_MC_MASTER_IMAGE_UPDATED")),
// Verify machine catalog identity type
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.identity_type", "ActiveDirectory"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AD", "provisioning_scheme.identity_type", "ActiveDirectory"),
// Verify total number of machines
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.number_of_total_machines", "2"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AD", "provisioning_scheme.number_of_total_machines", "2"),
),
},
// Delete machine test
{
- Config: BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_delete_machine, "ActiveDirectory"),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_delete_machine, "-AD", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify updated name of catalog
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AD", "name", name),
// Verify total number of machines
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.number_of_total_machines", "1"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AD", "provisioning_scheme.number_of_total_machines", "1"),
// Verify machine catalog identity type
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.identity_type", "ActiveDirectory"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AD", "provisioning_scheme.identity_type", "ActiveDirectory"),
),
},
//Delete testing automatically occurs in TestCase
@@ -129,23 +144,28 @@ func TestHybridAzureADMachineCatalogResourceAzure(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure, "HybridAzureAD"),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure, "-HybAAD", "HybridAzureAD"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of catalog
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-HybAAD", "name", name),
// Verify domain FQDN
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "session_support", "MultiSession"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-HybAAD", "session_support", "MultiSession"),
// Verify machine catalog identity type
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.identity_type", "HybridAzureAD"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-HybAAD", "provisioning_scheme.identity_type", "HybridAzureAD"),
// Verify domain admin username
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.machine_domain_identity.service_account", os.Getenv("TEST_MC_SERVICE_ACCOUNT")),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-HybAAD", "provisioning_scheme.machine_domain_identity.service_account", os.Getenv("TEST_MC_SERVICE_ACCOUNT")),
// Verify nic network
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.network_mapping.network", os.Getenv("TEST_MC_SUBNET")),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-HybAAD", "provisioning_scheme.network_mapping.network", os.Getenv("TEST_MC_SUBNET")),
),
},
// ImportState testing
{
- ResourceName: "citrix_machine_catalog.testMachineCatalog",
+ ResourceName: "citrix_machine_catalog.testMachineCatalog-HybAAD",
ImportState: true,
ImportStateVerify: true,
// The last_updated attribute does not exist in the Orchestration
@@ -154,18 +174,23 @@ func TestHybridAzureADMachineCatalogResourceAzure(t *testing.T) {
},
// Update description, master image and add machine test
{
- Config: BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "HybridAzureAD"),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "-HybAAD", "HybridAzureAD"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify updated name of catalog
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-HybAAD", "name", name),
// Verify updated description
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "description", "updatedCatalog"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-HybAAD", "description", "updatedCatalog"),
// Verify updated image
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.azure_machine_config.azure_master_image.master_image", os.Getenv("TEST_MC_MASTER_IMAGE_UPDATED")),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-HybAAD", "provisioning_scheme.azure_machine_config.azure_master_image.master_image", os.Getenv("TEST_MC_MASTER_IMAGE_UPDATED")),
// Verify machine catalog identity type
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.identity_type", "HybridAzureAD"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-HybAAD", "provisioning_scheme.identity_type", "HybridAzureAD"),
// Verify total number of machines
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.number_of_total_machines", "2"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-HybAAD", "provisioning_scheme.number_of_total_machines", "2"),
),
},
//Delete testing automatically occurs in TestCase
@@ -220,21 +245,26 @@ func TestAzureADMachineCatalogResourceAzure(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildMachineCatalogResourceAzureAd(t, machinecatalog_testResources_azure_ad),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceAzureAd(t, machinecatalog_testResources_azure_ad),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of catalog
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AAD", "name", name),
// Verify domain FQDN
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "session_support", "MultiSession"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AAD", "session_support", "MultiSession"),
// Verify machine catalog identity type
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.identity_type", "AzureAD"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AAD", "provisioning_scheme.identity_type", "AzureAD"),
// Verify nic network
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.network_mapping.network", os.Getenv("TEST_MC_SUBNET")),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AAD", "provisioning_scheme.network_mapping.network", os.Getenv("TEST_MC_SUBNET")),
),
},
// ImportState testing
{
- ResourceName: "citrix_machine_catalog.testMachineCatalog",
+ ResourceName: "citrix_machine_catalog.testMachineCatalog-AAD",
ImportState: true,
ImportStateVerify: true,
// The last_updated attribute does not exist in the Orchestration
@@ -243,18 +273,23 @@ func TestAzureADMachineCatalogResourceAzure(t *testing.T) {
},
// Update description, master image and add machine test
{
- Config: BuildMachineCatalogResourceAzureAd(t, machinecatalog_testResources_azure_ad_updated),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceAzureAd(t, machinecatalog_testResources_azure_ad_updated),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify updated name of catalog
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AAD", "name", name),
// Verify updated description
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "description", "updatedCatalog"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AAD", "description", "updatedCatalog"),
// Verify updated image
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.azure_machine_config.azure_master_image.master_image", os.Getenv("TEST_MC_MASTER_IMAGE_UPDATED")),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AAD", "provisioning_scheme.azure_machine_config.azure_master_image.master_image", os.Getenv("TEST_MC_MASTER_IMAGE_UPDATED")),
// Verify machine catalog identity type
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.identity_type", "AzureAD"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AAD", "provisioning_scheme.identity_type", "AzureAD"),
// Verify total number of machines
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.number_of_total_machines", "2"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AAD", "provisioning_scheme.number_of_total_machines", "2"),
),
},
//Delete testing automatically occurs in TestCase
@@ -300,19 +335,24 @@ func TestWorkgroupMachineCatalogResourceAzure(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildMachineCatalogResourceWorkgroup(t, machinecatalog_testResources_workgroup),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceWorkgroup(t, machinecatalog_testResources_workgroup),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of catalog
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-WG", "name", name),
// Verify domain FQDN
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "session_support", "MultiSession"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-WG", "session_support", "MultiSession"),
// Verify machine catalog identity type
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.identity_type", "Workgroup"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-WG", "provisioning_scheme.identity_type", "Workgroup"),
),
},
// ImportState testing
{
- ResourceName: "citrix_machine_catalog.testMachineCatalog",
+ ResourceName: "citrix_machine_catalog.testMachineCatalog-WG",
ImportState: true,
ImportStateVerify: true,
// The last_updated attribute does not exist in the Orchestration
@@ -321,18 +361,23 @@ func TestWorkgroupMachineCatalogResourceAzure(t *testing.T) {
},
// Update description, master image and add machine test
{
- Config: BuildMachineCatalogResourceWorkgroup(t, machinecatalog_testResources_workgroup_updated),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceWorkgroup(t, machinecatalog_testResources_workgroup_updated),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify updated name of catalog
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-WG", "name", name),
// Verify updated description
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "description", "updatedCatalog"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-WG", "description", "updatedCatalog"),
// Verify updated image
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.azure_machine_config.azure_master_image.master_image", os.Getenv("TEST_MC_MASTER_IMAGE_UPDATED")),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-WG", "provisioning_scheme.azure_machine_config.azure_master_image.master_image", os.Getenv("TEST_MC_MASTER_IMAGE_UPDATED")),
// Verify machine catalog identity type
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.identity_type", "Workgroup"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-WG", "provisioning_scheme.identity_type", "Workgroup"),
// Verify total number of machines
- resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.number_of_total_machines", "2"),
+ resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-WG", "provisioning_scheme.number_of_total_machines", "2"),
),
},
//Delete testing automatically occurs in TestCase
@@ -388,7 +433,12 @@ func TestMachineCatalogResourceGCP(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildMachineCatalogResourceGCP(t, machinecatalog_testResources_gcp),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceGCP(t, machinecatalog_testResources_gcp),
+ BuildHypervisorResourcePoolResourceGCP(t, hypervisor_resource_pool_testResource_gcp),
+ BuildHypervisorResourceGCP(t, hypervisor_testResources_gcp),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_GCP")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of catalog
resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
@@ -411,7 +461,12 @@ func TestMachineCatalogResourceGCP(t *testing.T) {
},
//Update description, master image and add machine test
{
- Config: BuildMachineCatalogResourceGCP(t, machinecatalog_testResources_gcp_updated),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceGCP(t, machinecatalog_testResources_gcp_updated),
+ BuildHypervisorResourcePoolResourceGCP(t, hypervisor_resource_pool_testResource_gcp),
+ BuildHypervisorResourceGCP(t, hypervisor_testResources_gcp),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_GCP")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify updated name of catalog
resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
@@ -464,7 +519,12 @@ func TestMachineCatalogResourceVsphere(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildMachineCatalogResourceVsphere(t, machine_catalog_testResources_vsphere),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceVsphere(t, machine_catalog_testResources_vsphere),
+ BuildHypervisorResourcePoolResourceVsphere(t, hypervisor_resource_pool_testResource_vsphere),
+ BuildHypervisorResourceVsphere(t, hypervisor_testResources_vsphere),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_VSPHERE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of catalog
resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
@@ -487,7 +547,12 @@ func TestMachineCatalogResourceVsphere(t *testing.T) {
},
//Update description, master image and add machine test
{
- Config: BuildMachineCatalogResourceVsphere(t, machine_catalog_testResources_vsphere_updated),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceVsphere(t, machine_catalog_testResources_vsphere_updated),
+ BuildHypervisorResourcePoolResourceVsphere(t, hypervisor_resource_pool_testResource_vsphere),
+ BuildHypervisorResourceVsphere(t, hypervisor_testResources_vsphere),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_VSPHERE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify updated name of catalog
resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
@@ -540,7 +605,12 @@ func TestMachineCatalogResourceXenserver(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildMachineCatalogResourceXenserver(t, machine_catalog_testResources_xenserver),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceXenserver(t, machine_catalog_testResources_xenserver),
+ BuildHypervisorResourcePoolResourceXenServer(t, hypervisor_resource_pool_testResource_xenserver),
+ BuildHypervisorResourceXenserver(t, hypervisor_testResources_xenserver),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_XENSERVER")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of catalog
resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
@@ -563,7 +633,12 @@ func TestMachineCatalogResourceXenserver(t *testing.T) {
},
//Update description, master image and add machine test
{
- Config: BuildMachineCatalogResourceXenserver(t, machine_catalog_testResources_xenserver_updated),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceXenserver(t, machine_catalog_testResources_xenserver_updated),
+ BuildHypervisorResourcePoolResourceXenServer(t, hypervisor_resource_pool_testResource_xenserver),
+ BuildHypervisorResourceXenserver(t, hypervisor_testResources_xenserver),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_XENSERVER")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify updated name of catalog
resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
@@ -622,7 +697,12 @@ func TestMachineCatalogResourceNutanix(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildMachineCatalogResourceNutanix(t, machine_catalog_testResources_nutanix),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceNutanix(t, machine_catalog_testResources_nutanix),
+ BuildHypervisorResourcePoolResourceNutanix(t, hypervisor_resource_pool_testResource_nutanix),
+ BuildHypervisorResourceNutanix(t, hypervisor_testResources_nutanix),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_NUTANIX")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of catalog
resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
@@ -645,7 +725,12 @@ func TestMachineCatalogResourceNutanix(t *testing.T) {
},
//Update description, master image and add machine test
{
- Config: BuildMachineCatalogResourceNutanix(t, machine_catalog_testResources_nutanix_updated),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceNutanix(t, machine_catalog_testResources_nutanix_updated),
+ BuildHypervisorResourcePoolResourceNutanix(t, hypervisor_resource_pool_testResource_nutanix),
+ BuildHypervisorResourceNutanix(t, hypervisor_testResources_nutanix),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_NUTANIX")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify updated name of catalog
resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
@@ -701,7 +786,12 @@ func TestMachineCatalogResourceAwsEc2(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildMachineCatalogResourceAwsEc2(t, machinecatalog_testResources_aws_ec2),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceAwsEc2(t, machinecatalog_testResources_aws_ec2),
+ BuildHypervisorResourcePoolResourceAwsEc2(t, hypervisor_resource_pool_testResource_aws_ec2),
+ BuildHypervisorResourceAwsEc2(t, hypervisor_testResources_aws_ec2),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AWS_EC2")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of catalog
resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
@@ -726,7 +816,12 @@ func TestMachineCatalogResourceAwsEc2(t *testing.T) {
},
//Update description, master image and add machine test
{
- Config: BuildMachineCatalogResourceAwsEc2(t, machinecatalog_testResources_aws_ec2_updated),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceAwsEc2(t, machinecatalog_testResources_aws_ec2_updated),
+ BuildHypervisorResourcePoolResourceAwsEc2(t, hypervisor_resource_pool_testResource_aws_ec2),
+ BuildHypervisorResourceAwsEc2(t, hypervisor_testResources_aws_ec2),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AWS_EC2")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify updated name of catalog
resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
@@ -778,7 +873,11 @@ func TestMachineCatalogResource_Manual_Power_Managed_Azure(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildMachineCatalogResourceManualPowerManagedAzure(t, machinecatalog_testResources_manual_power_managed_azure),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceManualPowerManagedAzure(t, machinecatalog_testResources_manual_power_managed_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of catalog
resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalogManualPowerManaged", "name", name),
@@ -837,7 +936,11 @@ func TestMachineCatalogResource_Manual_Power_Managed_GCP(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildMachineCatalogResourceManualPowerManagedGCP(t, machinecatalog_testResources_manual_power_managed_gcp),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceManualPowerManagedGCP(t, machinecatalog_testResources_manual_power_managed_gcp),
+ BuildHypervisorResourceGCP(t, hypervisor_testResources_gcp),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_GCP")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of catalog
resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalogManualPowerManaged", "name", name),
@@ -896,7 +999,11 @@ func TestMachineCatalogResource_Manual_Power_Managed_Vsphere(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildMachineCatalogResourceManualPowerManagedVsphere(t, machinecatalog_testResources_manual_power_managed_vsphere),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceManualPowerManagedVsphere(t, machinecatalog_testResources_manual_power_managed_vsphere),
+ BuildHypervisorResourceVsphere(t, hypervisor_testResources_vsphere),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_VSPHERE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of catalog
resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalogManualPowerManaged", "name", name),
@@ -949,7 +1056,11 @@ func TestMachineCatalogResource_Manual_Power_Managed_Xenserver(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildMachineCatalogResourceManualPowerManagedXenserver(t, machinecatalog_testResources_manual_power_managed_xenserver),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceManualPowerManagedXenserver(t, machinecatalog_testResources_manual_power_managed_xenserver),
+ BuildHypervisorResourceXenserver(t, hypervisor_testResources_xenserver),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_XENSERVER")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of catalog
resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalogManualPowerManaged", "name", name),
@@ -1002,7 +1113,11 @@ func TestMachineCatalogResource_Manual_Power_Managed_Nutanix(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildMachineCatalogResourceManualPowerManagedNutanix(t, machinecatalog_testResources_manual_power_managed_nutanix),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceManualPowerManagedNutanix(t, machinecatalog_testResources_manual_power_managed_nutanix),
+ BuildHypervisorResourceNutanix(t, hypervisor_testResources_nutanix),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_NUTANIX")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of catalog
resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalogManualPowerManaged", "name", name),
@@ -1025,7 +1140,7 @@ func TestMachineCatalogResource_Manual_Power_Managed_Nutanix(t *testing.T) {
}
func TestMachineCatalogPreCheck_Manual_Power_Managed_AWS_EC2(t *testing.T) {
- if v := os.Getenv("TEST_MC_NAME_MANUAL"); v == "" {
+ if v := os.Getenv("TEST_MC_NAME_MANUAL_AWS_EC2"); v == "" {
t.Fatal("TEST_MC_NAME_MANUAL must be set for acceptance tests")
}
if v := os.Getenv("TEST_MC_ALLOCATION_TYPE_MANUAL_POWER_MANAGED"); v == "" {
@@ -1058,7 +1173,11 @@ func TestMachineCatalogResource_Manual_Power_Managed_Aws_Ec2(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildMachineCatalogResourceManualPowerManagedAwsEc2(t, machinecatalog_testResources_manual_power_managed_aws_ec2),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceManualPowerManagedAwsEc2(t, machinecatalog_testResources_manual_power_managed_aws_ec2),
+ BuildHypervisorResourceAwsEc2(t, hypervisor_testResources_aws_ec2),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AWS_EC2")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of catalog
resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalogManualPowerManaged", "name", name),
@@ -1108,7 +1227,10 @@ func TestMachineCatalogResource_Manual_Non_Power_Managed(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildMachineCatalogResourceManualNonPowerManaged(t, machinecatalog_testResources_manual_non_power_managed),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceManualNonPowerManaged(t, machinecatalog_testResources_manual_non_power_managed),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of catalog
resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalogNonManualPowerManaged", "name", name),
@@ -1163,7 +1285,10 @@ func TestMachineCatalogResource_RemotePC(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildMachineCatalogResourceRemotePC(t, machinecatalog_testResources_remote_pc),
+ Config: composeTestResourceTf(
+ BuildMachineCatalogResourceRemotePC(t, machinecatalog_testResources_remote_pc),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of catalog
resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", name),
@@ -1185,7 +1310,7 @@ func TestMachineCatalogResource_RemotePC(t *testing.T) {
var (
machinecatalog_testResources_azure = `
-resource "citrix_machine_catalog" "testMachineCatalog" {
+resource "citrix_machine_catalog" "testMachineCatalog%s" {
name = "%s"
description = "on prem catalog for import testing"
allocation_type = "Random"
@@ -1221,10 +1346,12 @@ resource "citrix_machine_catalog" "testMachineCatalog" {
storage_cost_saving = true
}
}
- network_mapping = {
- network_device = "0"
- network = "%s"
- }
+ network_mapping = [
+ {
+ network_device = "0"
+ network = "%s"
+ }
+ ]
number_of_total_machines = 1
machine_account_creation_rules ={
naming_scheme = "test-machine-##"
@@ -1236,7 +1363,7 @@ resource "citrix_machine_catalog" "testMachineCatalog" {
}
`
machinecatalog_testResources_azure_updated = `
- resource "citrix_machine_catalog" "testMachineCatalog" {
+ resource "citrix_machine_catalog" "testMachineCatalog%s" {
name = "%s"
description = "updatedCatalog"
allocation_type = "Random"
@@ -1272,10 +1399,12 @@ resource "citrix_machine_catalog" "testMachineCatalog" {
storage_cost_saving = true
}
}
- network_mapping = {
- network_device = "0"
- network = "%s"
- }
+ network_mapping = [
+ {
+ network_device = "0"
+ network = "%s"
+ }
+ ]
availability_zones = "1,3"
number_of_total_machines = 2
machine_account_creation_rules ={
@@ -1288,7 +1417,7 @@ resource "citrix_machine_catalog" "testMachineCatalog" {
`
machinecatalog_testResources_azure_delete_machine = `
- resource "citrix_machine_catalog" "testMachineCatalog" {
+ resource "citrix_machine_catalog" "testMachineCatalog%s" {
name = "%s"
description = "updatedCatalog"
allocation_type = "Random"
@@ -1324,10 +1453,12 @@ resource "citrix_machine_catalog" "testMachineCatalog" {
storage_cost_saving = true
}
}
- network_mapping = {
- network_device = "0"
- network = "%s"
- }
+ network_mapping = [
+ {
+ network_device = "0"
+ network = "%s"
+ }
+ ]
availability_zones = "1,3"
number_of_total_machines = 1
machine_account_creation_rules ={
@@ -1339,7 +1470,7 @@ resource "citrix_machine_catalog" "testMachineCatalog" {
}
`
machinecatalog_testResources_azure_ad = `
- resource "citrix_machine_catalog" "testMachineCatalog" {
+ resource "citrix_machine_catalog" "testMachineCatalog%s" {
name = "%s"
description = "on prem catalog for import testing"
allocation_type = "Random"
@@ -1373,10 +1504,12 @@ resource "citrix_machine_catalog" "testMachineCatalog" {
storage_cost_saving = true
}
}
- network_mapping = {
- network_device = "0"
- network = "%s"
- }
+ network_mapping = [
+ {
+ network_device = "0"
+ network = "%s"
+ }
+ ]
number_of_total_machines = 1
machine_account_creation_rules ={
naming_scheme = "test-machine-##"
@@ -1388,7 +1521,7 @@ resource "citrix_machine_catalog" "testMachineCatalog" {
}
`
machinecatalog_testResources_azure_ad_updated = `
- resource "citrix_machine_catalog" "testMachineCatalog" {
+ resource "citrix_machine_catalog" "testMachineCatalog%s" {
name = "%s"
description = "updatedCatalog"
allocation_type = "Random"
@@ -1422,10 +1555,12 @@ resource "citrix_machine_catalog" "testMachineCatalog" {
storage_cost_saving = true
}
}
- network_mapping = {
- network_device = "0"
- network = "%s"
- }
+ network_mapping = [
+ {
+ network_device = "0"
+ network = "%s"
+ }
+ ]
availability_zones = "1,3"
number_of_total_machines = 2
machine_account_creation_rules ={
@@ -1438,7 +1573,7 @@ resource "citrix_machine_catalog" "testMachineCatalog" {
`
machinecatalog_testResources_workgroup = `
- resource "citrix_machine_catalog" "testMachineCatalog" {
+ resource "citrix_machine_catalog" "testMachineCatalog%s" {
name = "%s"
description = "on prem catalog for import testing"
allocation_type = "Random"
@@ -1479,7 +1614,7 @@ resource "citrix_machine_catalog" "testMachineCatalog" {
}
`
machinecatalog_testResources_workgroup_updated = `
- resource "citrix_machine_catalog" "testMachineCatalog" {
+ resource "citrix_machine_catalog" "testMachineCatalog%s" {
name = "%s"
description = "updatedCatalog"
allocation_type = "Random"
@@ -1803,10 +1938,12 @@ resource "citrix_machine_catalog" "testMachineCatalog" {
]
tenancy_type = "Shared"
}
- network_mapping = {
- network_device = "0"
- network = "%s"
- }
+ network_mapping = [
+ {
+ network_device = "0"
+ network = "%s"
+ }
+ ]
number_of_total_machines = 1
machine_account_creation_rules ={
naming_scheme = "test-machine-##"
@@ -1842,10 +1979,12 @@ resource "citrix_machine_catalog" "testMachineCatalog" {
]
tenancy_type = "Shared"
}
- network_mapping = {
- network_device = "0"
- network = "%s"
- }
+ network_mapping = [
+ {
+ network_device = "0"
+ network = "%s"
+ }
+ ]
number_of_total_machines = 2
machine_account_creation_rules ={
naming_scheme = "test-machine-##"
@@ -2056,7 +2195,7 @@ resource "citrix_machine_catalog" "testMachineCatalog" {
`
)
-func BuildMachineCatalogResourceAzure(t *testing.T, machineResource string, identityType string) string {
+func BuildMachineCatalogResourceAzure(t *testing.T, machineResource, catalogNameSuffix, identityType string) string {
name := os.Getenv("TEST_MC_NAME")
if identityType == "HybridAzureAD" {
name += "-HybAAD"
@@ -2079,7 +2218,7 @@ func BuildMachineCatalogResourceAzure(t *testing.T, machineResource string, iden
//machine account
domain := os.Getenv("TEST_MC_DOMAIN")
- return BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure) + fmt.Sprintf(machineResource, name, identityType, domain, service_account, service_account_pass, service_offering, resource_group, storage_account, container, master_image, subnet)
+ return fmt.Sprintf(machineResource, catalogNameSuffix, name, identityType, domain, service_account, service_account_pass, service_offering, resource_group, storage_account, container, master_image, subnet)
}
func BuildMachineCatalogResourceAzureAd(t *testing.T, machineResource string) string {
@@ -2097,7 +2236,7 @@ func BuildMachineCatalogResourceAzureAd(t *testing.T, machineResource string) st
master_image = os.Getenv("TEST_MC_MASTER_IMAGE_UPDATED")
}
- return BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure) + fmt.Sprintf(machineResource, name, service_offering, resource_group, storage_account, container, master_image, machine_profile_vm_name, machine_profile_resource_group, subnet)
+ return fmt.Sprintf(machineResource, "-AAD", name, service_offering, resource_group, storage_account, container, master_image, machine_profile_vm_name, machine_profile_resource_group, subnet)
}
func BuildMachineCatalogResourceWorkgroup(t *testing.T, machineResource string) string {
@@ -2112,7 +2251,7 @@ func BuildMachineCatalogResourceWorkgroup(t *testing.T, machineResource string)
master_image = os.Getenv("TEST_MC_MASTER_IMAGE_UPDATED")
}
- return BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure) + fmt.Sprintf(machineResource, name, service_offering, resource_group, storage_account, container, master_image)
+ return fmt.Sprintf(machineResource, "-WG", name, service_offering, resource_group, storage_account, container, master_image)
}
func BuildMachineCatalogResourceGCP(t *testing.T, machineResource string) string {
@@ -2129,7 +2268,7 @@ func BuildMachineCatalogResourceGCP(t *testing.T, machineResource string) string
//machine account
domain := os.Getenv("TEST_MC_DOMAIN_GCP")
- return BuildHypervisorResourcePoolResourceGCP(t, hypervisor_resource_pool_testResource_gcp) + fmt.Sprintf(machineResource, name, identityType, domain, service_account, service_account_pass, storage_type, machine_profile, master_image, machine_snapshot, availability_zones)
+ return fmt.Sprintf(machineResource, name, identityType, domain, service_account, service_account_pass, storage_type, machine_profile, master_image, machine_snapshot, availability_zones)
}
func BuildMachineCatalogResourceVsphere(t *testing.T, machineResource string) string {
@@ -2141,7 +2280,7 @@ func BuildMachineCatalogResourceVsphere(t *testing.T, machineResource string) st
service_account := os.Getenv("TEST_MC_SERVICE_ACCOUNT_VSPHERE")
service_account_pass := os.Getenv("TEST_MC_SERVICE_ACCOUNT_PASS_VSPHERE")
- return BuildHypervisorResourcePoolResourceVsphere(t) + fmt.Sprintf(machineResource, name, master_image, memory_mb, cpu_count, service_account, domain, service_account_pass)
+ return fmt.Sprintf(machineResource, name, master_image, memory_mb, cpu_count, service_account, domain, service_account_pass)
}
func BuildMachineCatalogResourceXenserver(t *testing.T, machineResource string) string {
@@ -2153,7 +2292,7 @@ func BuildMachineCatalogResourceXenserver(t *testing.T, machineResource string)
service_account := os.Getenv("TEST_MC_SERVICE_ACCOUNT_XENSERVER")
service_account_pass := os.Getenv("TEST_MC_SERVICE_ACCOUNT_PASS_XENSERVER")
- return BuildHypervisorResourcePoolResourceXenServer(t) + fmt.Sprintf(machineResource, name, master_image, memory_mb, cpu_count, service_account, domain, service_account_pass)
+ return fmt.Sprintf(machineResource, name, master_image, memory_mb, cpu_count, service_account, domain, service_account_pass)
}
func BuildMachineCatalogResourceNutanix(t *testing.T, machineResource string) string {
@@ -2167,7 +2306,7 @@ func BuildMachineCatalogResourceNutanix(t *testing.T, machineResource string) st
service_account := os.Getenv("TEST_MC_SERVICE_ACCOUNT_NUTANIX")
service_account_pass := os.Getenv("TEST_MC_SERVICE_ACCOUNT_PASS_NUTANIX")
- return BuildHypervisorResourcePoolResourceNutanix(t, hypervisor_resource_pool_testResource_nutanix) + fmt.Sprintf(machineResource, name, container, master_image, memory_mb, cpu_count, cores_per_cpu_count, service_account, domain, service_account_pass)
+ return fmt.Sprintf(machineResource, name, container, master_image, memory_mb, cpu_count, cores_per_cpu_count, service_account, domain, service_account_pass)
}
func BuildMachineCatalogResourceAwsEc2(t *testing.T, machineResource string) string {
@@ -2180,7 +2319,7 @@ func BuildMachineCatalogResourceAwsEc2(t *testing.T, machineResource string) str
service_offering := os.Getenv("TEST_MC_SERVICE_OFFERING_AWS_EC2")
network := os.Getenv("TEST_MC_NETWORK_AWS_EC2")
- return BuildHypervisorResourcePoolResourceAwsEc2(t, hypervisor_resource_pool_testResource_aws_ec2) + fmt.Sprintf(machineResource, name, service_account, domain, service_account_pass, image_ami, master_image, service_offering, network)
+ return fmt.Sprintf(machineResource, name, service_account, domain, service_account_pass, image_ami, master_image, service_offering, network)
}
func BuildMachineCatalogResourceManualPowerManagedAzure(t *testing.T, machineResource string) string {
@@ -2192,7 +2331,7 @@ func BuildMachineCatalogResourceManualPowerManagedAzure(t *testing.T, machineRes
allocation_type := os.Getenv("TEST_MC_ALLOCATION_TYPE_MANUAL_POWER_MANAGED")
session_support := os.Getenv("TEST_MC_SESSION_SUPPORT_MANUAL_POWER_MANAGED")
- return BuildHypervisorResourceAzure(t, hypervisor_testResources) + fmt.Sprintf(machineResource, name, allocation_type, session_support, region, resource_group, machine_name, machine_account)
+ return fmt.Sprintf(machineResource, name, allocation_type, session_support, region, resource_group, machine_name, machine_account)
}
func BuildMachineCatalogResourceManualPowerManagedGCP(t *testing.T, machineResource string) string {
@@ -2204,7 +2343,7 @@ func BuildMachineCatalogResourceManualPowerManagedGCP(t *testing.T, machineResou
allocation_type := os.Getenv("TEST_MC_ALLOCATION_TYPE_MANUAL_POWER_MANAGED")
session_support := os.Getenv("TEST_MC_SESSION_SUPPORT_MANUAL_POWER_MANAGED")
- return BuildHypervisorResourceGCP(t, hypervisor_testResources_gcp) + fmt.Sprintf(machineResource, name, allocation_type, session_support, region, project_name, machine_name, machine_account)
+ return fmt.Sprintf(machineResource, name, allocation_type, session_support, region, project_name, machine_name, machine_account)
}
func BuildMachineCatalogResourceManualPowerManagedVsphere(t *testing.T, machineResource string) string {
@@ -2216,7 +2355,7 @@ func BuildMachineCatalogResourceManualPowerManagedVsphere(t *testing.T, machineR
allocation_type := os.Getenv("TEST_MC_ALLOCATION_TYPE_MANUAL_POWER_MANAGED")
session_support := os.Getenv("TEST_MC_SESSION_SUPPORT_MANUAL_POWER_MANAGED")
- return BuildHypervisorResourceVsphere(t, hypervisor_testResources_vsphere) + fmt.Sprintf(machineResource, name, allocation_type, session_support, datacenter, host, machine_name, machine_account)
+ return fmt.Sprintf(machineResource, name, allocation_type, session_support, datacenter, host, machine_name, machine_account)
}
func BuildMachineCatalogResourceManualPowerManagedXenserver(t *testing.T, machineResource string) string {
@@ -2226,7 +2365,7 @@ func BuildMachineCatalogResourceManualPowerManagedXenserver(t *testing.T, machin
allocation_type := os.Getenv("TEST_MC_ALLOCATION_TYPE_MANUAL_POWER_MANAGED")
session_support := os.Getenv("TEST_MC_SESSION_SUPPORT_MANUAL_POWER_MANAGED")
- return BuildHypervisorResourceXenserver(t, hypervisor_testResources_xenserver) + fmt.Sprintf(machineResource, name, allocation_type, session_support, machine_name, machine_account)
+ return fmt.Sprintf(machineResource, name, allocation_type, session_support, machine_name, machine_account)
}
func BuildMachineCatalogResourceManualPowerManagedNutanix(t *testing.T, machineResource string) string {
@@ -2236,7 +2375,7 @@ func BuildMachineCatalogResourceManualPowerManagedNutanix(t *testing.T, machineR
allocation_type := os.Getenv("TEST_MC_ALLOCATION_TYPE_MANUAL_POWER_MANAGED")
session_support := os.Getenv("TEST_MC_SESSION_SUPPORT_MANUAL_POWER_MANAGED")
- return BuildHypervisorResourceNutanix(t, hypervisor_testResources_nutanix) + fmt.Sprintf(machineResource, name, allocation_type, session_support, machine_name, machine_account)
+ return fmt.Sprintf(machineResource, name, allocation_type, session_support, machine_name, machine_account)
}
func BuildMachineCatalogResourceManualPowerManagedAwsEc2(t *testing.T, machineResource string) string {
@@ -2247,8 +2386,7 @@ func BuildMachineCatalogResourceManualPowerManagedAwsEc2(t *testing.T, machineRe
machine_account := os.Getenv("TEST_MC_MACHINE_ACCOUNT_MANUAL_AWS_EC2")
availability_zone := os.Getenv("TEST_MC_AVAILABILITY_ZONE_MANUAL_AWS_EC2")
- str := BuildHypervisorResourceAwsEc2(t, hypervisor_testResources_aws_ec2) + fmt.Sprintf(machineResource, name, allocation_type, session_support, machine_name, machine_account, availability_zone)
- return str
+ return fmt.Sprintf(machineResource, name, allocation_type, session_support, machine_name, machine_account, availability_zone)
}
func BuildMachineCatalogResourceManualNonPowerManaged(t *testing.T, machineResource string) string {
@@ -2257,9 +2395,7 @@ func BuildMachineCatalogResourceManualNonPowerManaged(t *testing.T, machineResou
allocation_type := os.Getenv("TEST_MC_ALLOCATION_TYPE_MANUAL_NON_POWER_MANAGED")
session_support := os.Getenv("TEST_MC_SESSION_SUPPORT_MANUAL_NON_POWER_MANAGED")
- zoneName := os.Getenv("TEST_ZONE_NAME")
-
- return BuildZoneResource(t, zone_testResource, zoneName) + fmt.Sprintf(machineResource, name, allocation_type, session_support, machine_account)
+ return fmt.Sprintf(machineResource, name, allocation_type, session_support, machine_account)
}
func BuildMachineCatalogResourceRemotePC(t *testing.T, machineResource string) string {
@@ -2269,7 +2405,5 @@ func BuildMachineCatalogResourceRemotePC(t *testing.T, machineResource string) s
ou := os.Getenv("TEST_MC_OU_REMOTE_PC")
include_subfolders := os.Getenv("TEST_MC_INCLUDE_SUBFOLDERS_REMOTE_PC")
- zoneName := os.Getenv("TEST_ZONE_NAME")
-
- return BuildZoneResource(t, zone_testResource, zoneName) + fmt.Sprintf(machineResource, name, allocation_type, machine_account, include_subfolders, ou)
+ return fmt.Sprintf(machineResource, name, allocation_type, machine_account, include_subfolders, ou)
}
diff --git a/internal/test/policy_set_resource_test.go b/internal/test/policy_set_resource_test.go
index 194e996..42e0167 100644
--- a/internal/test/policy_set_resource_test.go
+++ b/internal/test/policy_set_resource_test.go
@@ -159,7 +159,7 @@ func BuildPolicySetResource(t *testing.T, policySet string) string {
policySetName := os.Getenv("TEST_POLICY_SET_NAME")
ddcServerHostName := os.Getenv("CITRIX_DDC_HOST_NAME")
- return BuildDeliveryGroupResource(t, testDeliveryGroupResources_updated) + fmt.Sprintf(policySet, policySetName, ddcServerHostName)
+ return fmt.Sprintf(policySet, policySetName, ddcServerHostName)
}
func TestPolicySetResource(t *testing.T) {
@@ -176,7 +176,15 @@ func TestPolicySetResource(t *testing.T) {
Steps: []resource.TestStep{
// Create and Read testing
{
- Config: BuildPolicySetResource(t, policy_set_testResource),
+ Config: composeTestResourceTf(
+ BuildPolicySetResource(t, policy_set_testResource),
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources_updated),
+ BuildPolicySetResourceWithoutDeliveryGroup(t),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of the policy set
resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "name", os.Getenv("TEST_POLICY_SET_NAME")+"-1"),
@@ -204,7 +212,15 @@ func TestPolicySetResource(t *testing.T) {
},
// Reorder and Read testing
{
- Config: BuildPolicySetResource(t, policy_set_reordered_testResource),
+ Config: composeTestResourceTf(
+ BuildPolicySetResource(t, policy_set_reordered_testResource),
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources_updated),
+ BuildPolicySetResourceWithoutDeliveryGroup(t),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of the policy set
resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "name", os.Getenv("TEST_POLICY_SET_NAME")+"-2"),
@@ -235,7 +251,15 @@ func TestPolicySetResource(t *testing.T) {
},
// Update and Read testing
{
- Config: BuildPolicySetResource(t, policy_set_updated_testResource),
+ Config: composeTestResourceTf(
+ BuildPolicySetResource(t, policy_set_updated_testResource),
+ BuildDeliveryGroupResource(t, testDeliveryGroupResources_updated),
+ BuildPolicySetResourceWithoutDeliveryGroup(t),
+ BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "", "ActiveDirectory"),
+ BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
+ BuildHypervisorResourceAzure(t, hypervisor_testResources),
+ BuildZoneResource(t, zone_testResource, os.Getenv("TEST_ZONE_NAME_AZURE")),
+ ),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify name of the policy set
resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "name", os.Getenv("TEST_POLICY_SET_NAME")+"-3"),
diff --git a/internal/test/resource_locations_resource_test.go b/internal/test/resource_locations_resource_test.go
new file mode 100644
index 0000000..13004ba
--- /dev/null
+++ b/internal/test/resource_locations_resource_test.go
@@ -0,0 +1,81 @@
+// Copyright © 2023. Citrix Systems, Inc.
+
+package test
+
+import (
+ "fmt"
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+func TestResourceLocationPreCheck(t *testing.T) {
+ if name := os.Getenv("TEST_RESOURCE_LOCATION_NAME"); name == "" {
+ t.Fatal("TEST_RESOURCE_LOCATION_NAME must be set for acceptance tests")
+ }
+}
+
+func TestResourceLocationResource(t *testing.T) {
+ name := os.Getenv("TEST_RESOURCE_LOCATION_NAME")
+
+ resource.Test(t, resource.TestCase{
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ PreCheck: func() {
+ TestProviderPreCheck(t)
+ TestResourceLocationPreCheck(t)
+ },
+ Steps: []resource.TestStep{
+ // Create and Read testing
+ {
+ Config: BuildResourceLocationResource(t, resourceLocationTestResource),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify the name of the resource location
+ resource.TestCheckResourceAttr("citrix_resource_location.test_resource_location", "name", name),
+ // Verify the value of the internal_only flag (Set to false by default)
+ resource.TestCheckResourceAttr("citrix_resource_location.test_resource_location", "internal_only", "false"),
+ // Verify the value of the time_zone attribute (Set to "UTC" by default)
+ resource.TestCheckResourceAttr("citrix_resource_location.test_resource_location", "time_zone", "GMT Standard Time"),
+ ),
+ },
+ // ImportState testing
+ {
+ ResourceName: "citrix_resource_location.test_resource_location",
+ ImportState: true,
+ ImportStateVerify: true,
+ },
+ // Update and Read testing
+ {
+ Config: BuildResourceLocationResource(t, resourceLocationTestResource_updated),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify the name of the resource location
+ resource.TestCheckResourceAttr("citrix_resource_location.test_resource_location", "name", fmt.Sprintf("%s-updated", name)),
+ // Verify the value of the internal_only flag (Set to false by default)
+ resource.TestCheckResourceAttr("citrix_resource_location.test_resource_location", "internal_only", "false"),
+ // Verify the value of the time_zone attribute (Set to "UTC" by default)
+ resource.TestCheckResourceAttr("citrix_resource_location.test_resource_location", "time_zone", "Eastern Standard Time"),
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ },
+ })
+}
+
+var (
+ resourceLocationTestResource = `
+ resource "citrix_resource_location" "test_resource_location" {
+ name = "%s"
+
+ }
+ `
+ resourceLocationTestResource_updated = `
+ resource "citrix_resource_location" "test_resource_location" {
+ name = "%s-updated"
+ time_zone = "Eastern Standard Time"
+ }
+ `
+)
+
+func BuildResourceLocationResource(t *testing.T, resourceLocation string) string {
+ return fmt.Sprintf(resourceLocation, os.Getenv("TEST_RESOURCE_LOCATION_NAME"))
+}
diff --git a/internal/test/stf_authentication_service_resource_test.go b/internal/test/stf_authentication_service_resource_test.go
new file mode 100644
index 0000000..890dc67
--- /dev/null
+++ b/internal/test/stf_authentication_service_resource_test.go
@@ -0,0 +1,105 @@
+package test
+
+import (
+ "fmt"
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+ "github.com/hashicorp/terraform-plugin-testing/terraform"
+)
+
+func TestSTFAuthenticationServicePreCheck(t *testing.T) {
+ if v := os.Getenv("TEST_STF_SITE_ID"); v == "" {
+ t.Fatal("TEST_STF_SITE_ID must be set for acceptance tests")
+ }
+
+ if v := os.Getenv("TEST_STF_Auth_Virtual_Path"); v == "" {
+ t.Fatal("TEST_STF_Auth_Virtual_Path must be set for acceptance tests")
+ }
+}
+
+func TestSTFAuthenticationServiceResource(t *testing.T) {
+ siteId := os.Getenv("TEST_STF_SITE_ID")
+ virtualPath := os.Getenv("TEST_STF_Auth_Virtual_Path")
+ resource.Test(t, resource.TestCase{
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ PreCheck: func() {
+ TestProviderPreCheck(t)
+ TestSTFDeploymentPreCheck(t)
+ TestSTFAuthenticationServicePreCheck(t)
+ },
+ Steps: []resource.TestStep{
+
+ // Create and Read testing
+ {
+ Config: BuildSTFAuthenticationServiceResource(t, testSTFAuthenticationServiceResources),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify parameters of the STF authentication service
+ resource.TestCheckResourceAttr("citrix_stf_authentication_service.testSTFAuthenticationService", "site_id", siteId),
+ resource.TestCheckResourceAttr("citrix_stf_authentication_service.testSTFAuthenticationService", "virtual_path", virtualPath),
+ resource.TestCheckResourceAttr("citrix_stf_authentication_service.testSTFAuthenticationService", "friendly_name", "testSTFAuthenticationService"),
+ ),
+ },
+
+ // ImportState testing
+ {
+ ResourceName: "citrix_stf_authentication_service.testSTFAuthenticationService",
+ ImportState: true,
+ ImportStateVerify: true,
+ ImportStateVerifyIdentifierAttribute: "virtual_path",
+ ImportStateIdFunc: generateImportStateId_STFAuthenService,
+ ImportStateVerifyIgnore: []string{"last_updated"},
+ },
+
+ // Update testing for STF authentication service
+ {
+ Config: BuildSTFAuthenticationServiceResource(t, testSTFAuthenticationServiceResources_updated),
+
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify parameters of the updated STF authentication service
+ resource.TestCheckResourceAttr("citrix_stf_authentication_service.testSTFAuthenticationService", "site_id", siteId),
+ resource.TestCheckResourceAttr("citrix_stf_authentication_service.testSTFAuthenticationService", "virtual_path", virtualPath),
+ resource.TestCheckResourceAttr("citrix_stf_authentication_service.testSTFAuthenticationService", "friendly_name", "testAuthServiceUpdated")),
+ },
+ },
+ })
+}
+
+func BuildSTFAuthenticationServiceResource(t *testing.T, authService string) string {
+ siteId := os.Getenv("TEST_STF_SITE_ID")
+ authVirtualPath := os.Getenv("TEST_STF_Auth_Virtual_Path")
+ return BuildSTFDeploymentResource(t, testSTFDeploymentResources, siteId) + fmt.Sprintf(authService, authVirtualPath)
+}
+
+func generateImportStateId_STFAuthenService(state *terraform.State) (string, error) {
+ resourceName := "citrix_stf_authentication_service.testSTFAuthenticationService"
+ var rawState map[string]string
+ for _, m := range state.Modules {
+ if len(m.Resources) > 0 {
+ if v, ok := m.Resources[resourceName]; ok {
+ rawState = v.Primary.Attributes
+ }
+ }
+ }
+
+ return fmt.Sprintf("%s,%s", rawState["site_id"], rawState["virtual_path"]), nil
+}
+
+var (
+ testSTFAuthenticationServiceResources = `
+ resource "citrix_stf_authentication_service" "testSTFAuthenticationService" {
+ site_id = citrix_stf_deployment.testSTFDeployment.site_id
+ virtual_path = "%s"
+ friendly_name = "testSTFAuthenticationService"
+ }
+ `
+
+ testSTFAuthenticationServiceResources_updated = `
+ resource "citrix_stf_authentication_service" "testSTFAuthenticationService" {
+ site_id = citrix_stf_deployment.testSTFDeployment.site_id
+ virtual_path = "%s"
+ friendly_name = "testAuthServiceUpdated"
+ }
+ `
+)
diff --git a/internal/test/stf_deployment_resource_test.go b/internal/test/stf_deployment_resource_test.go
new file mode 100644
index 0000000..0b633fc
--- /dev/null
+++ b/internal/test/stf_deployment_resource_test.go
@@ -0,0 +1,91 @@
+// Copyright © 2023. Citrix Systems, Inc.
+
+package test
+
+import (
+ "fmt"
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+// testAccPreCheck validates the necessary test API keys exist
+// in the testing environment
+
+func TestSTFDeploymentPreCheck(t *testing.T) {
+ if v := os.Getenv("TEST_STF_SITE_ID"); v == "" {
+ t.Fatal("TEST_STF_SITE_ID must be set for acceptance tests")
+ }
+
+ if v := os.Getenv("TEST_STF_SITE_ID_UPDATED"); v == "" {
+ t.Fatal("TEST_STF_SITE_ID_UPDATED must be set for acceptance tests")
+ }
+}
+
+func TestSTFDeploymentResource(t *testing.T) {
+ siteId := os.Getenv("TEST_STF_SITE_ID")
+ siteId_updated := os.Getenv("TEST_STF_SITE_ID_UPDATED")
+ resource.Test(t, resource.TestCase{
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ PreCheck: func() {
+ TestProviderPreCheck(t)
+ TestSTFDeploymentPreCheck(t)
+ },
+ Steps: []resource.TestStep{
+
+ // Create and Read testing
+ {
+ Config: BuildSTFDeploymentResource(t, testSTFDeploymentResources, siteId),
+
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify site_id of STF deployment
+ resource.TestCheckResourceAttr("citrix_stf_deployment.testSTFDeployment", "site_id", siteId),
+ // Verify host_base_url of STF deployment
+ resource.TestCheckResourceAttr("citrix_stf_deployment.testSTFDeployment", "host_base_url", "https://test.com"),
+ ),
+ },
+
+ // ImportState testing
+ {
+ ResourceName: "citrix_stf_deployment.testSTFDeployment",
+ ImportState: true,
+ ImportStateId: siteId,
+ ImportStateVerify: true,
+ ImportStateVerifyIdentifierAttribute: "site_id",
+ ImportStateVerifyIgnore: []string{"last_updated"},
+ },
+
+ // Update testing for STF deployment
+ {
+ Config: BuildSTFDeploymentResource(t, testSTFDeploymentResources_updated, siteId_updated),
+
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify site_id of STF deployment
+ resource.TestCheckResourceAttr("citrix_stf_deployment.testSTFDeployment", "site_id", siteId_updated),
+ // Verify host_base_url of STF deployment
+ resource.TestCheckResourceAttr("citrix_stf_deployment.testSTFDeployment", "host_base_url", "https://test-updated.com"),
+ ),
+ },
+ },
+ })
+}
+
+func BuildSTFDeploymentResource(t *testing.T, deployment string, siteId string) string {
+ return fmt.Sprintf(deployment, siteId)
+}
+
+var (
+ testSTFDeploymentResources = `
+ resource "citrix_stf_deployment" "testSTFDeployment" {
+ site_id = "%s"
+ host_base_url = "https://test.com"
+ }
+ `
+ testSTFDeploymentResources_updated = `
+ resource "citrix_stf_deployment" "testSTFDeployment" {
+ site_id = "%s"
+ host_base_url = "https://test-updated.com"
+ }
+ `
+)
diff --git a/internal/test/stf_store_service_resource_test.go b/internal/test/stf_store_service_resource_test.go
new file mode 100644
index 0000000..94447fa
--- /dev/null
+++ b/internal/test/stf_store_service_resource_test.go
@@ -0,0 +1,112 @@
+// Copyright © 2023. Citrix Systems, Inc.
+
+package test
+
+import (
+ "fmt"
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+ "github.com/hashicorp/terraform-plugin-testing/terraform"
+)
+
+// testAccPreCheck validates the necessary test API keys exist
+// in the testing environment
+
+func TestSTFStoreServicePreCheck(t *testing.T) {
+ if v := os.Getenv("TEST_STF_SITE_ID"); v == "" {
+ t.Fatal("TEST_STF_SITE_ID must be set for acceptance tests")
+ }
+
+ if v := os.Getenv("TEST_STF_STORE_VIRTUAL_PATH"); v == "" {
+ t.Fatal("TEST_STF_STORE_VIRTUAL_PATH must be set for acceptance tests")
+ }
+}
+
+func TestSTFStoreServiceResource(t *testing.T) {
+ siteId := os.Getenv("TEST_STF_SITE_ID")
+ virtualPath := os.Getenv("TEST_STF_STORE_VIRTUAL_PATH")
+ resource.Test(t, resource.TestCase{
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ PreCheck: func() {
+ TestProviderPreCheck(t)
+ TestSTFStoreServicePreCheck(t)
+ },
+ Steps: []resource.TestStep{
+
+ // Create and Read testing
+ {
+ Config: BuildSTFStoreServiceResource(t, testSTFStoreServiceResources),
+
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify site_id of STF Store Service
+ resource.TestCheckResourceAttr("citrix_stf_store_service.testSTFStoreService", "site_id", siteId),
+ // Verify virtual_path of STF Store Service
+ resource.TestCheckResourceAttr("citrix_stf_store_service.testSTFStoreService", "virtual_path", virtualPath),
+ ),
+ },
+
+ // ImportState testing
+ {
+ ResourceName: "citrix_stf_store_service.testSTFStoreService",
+ ImportState: true,
+ ImportStateVerify: true,
+ ImportStateVerifyIdentifierAttribute: "virtual_path",
+ ImportStateIdFunc: generateImportStateId_STFStoreService,
+ ImportStateVerifyIgnore: []string{"last_updated", "authentication_service"},
+ },
+
+ // Update testing for STF Store Service
+ {
+ Config: BuildSTFStoreServiceResource(t, testSTFStoreServiceResources_updated),
+
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify friendly_name of STF Store Service
+ resource.TestCheckResourceAttr("citrix_stf_store_service.testSTFStoreService", "friendly_name", "Store_Updated"),
+ ),
+ },
+ },
+ })
+}
+
+func BuildSTFStoreServiceResource(t *testing.T, storeService string) string {
+ siteId := os.Getenv("TEST_STF_SITE_ID")
+ virtualPath := os.Getenv("TEST_STF_STORE_VIRTUAL_PATH")
+
+ return BuildSTFAuthenticationServiceResource(t, testSTFAuthenticationServiceResources) + fmt.Sprintf(storeService, siteId, virtualPath)
+
+}
+
+func generateImportStateId_STFStoreService(state *terraform.State) (string, error) {
+ resourceName := "citrix_stf_store_service.testSTFStoreService"
+ var rawState map[string]string
+ for _, m := range state.Modules {
+ if len(m.Resources) > 0 {
+ if v, ok := m.Resources[resourceName]; ok {
+ rawState = v.Primary.Attributes
+ }
+ }
+ }
+
+ return fmt.Sprintf("%s,%s", rawState["site_id"], rawState["virtual_path"]), nil
+}
+
+var (
+ testSTFStoreServiceResources = `
+ resource "citrix_stf_store_service" "testSTFStoreService" {
+ site_id = "%s"
+ virtual_path = "%s"
+ friendly_name = "Store"
+ authentication_service = citrix_stf_authentication_service.testSTFAuthenticationService.virtual_path
+ }
+ `
+ testSTFStoreServiceResources_updated = `
+ resource "citrix_stf_store_service" "testSTFStoreService" {
+ site_id = "%s"
+ virtual_path = "%s"
+ friendly_name = "Store_Updated"
+ authentication_service = citrix_stf_authentication_service.testSTFAuthenticationService.virtual_path
+ }
+ `
+)
diff --git a/internal/test/stf_webreceiver_service_resource_test.go b/internal/test/stf_webreceiver_service_resource_test.go
new file mode 100644
index 0000000..848cc77
--- /dev/null
+++ b/internal/test/stf_webreceiver_service_resource_test.go
@@ -0,0 +1,125 @@
+// Copyright © 2023. Citrix Systems, Inc.
+
+package test
+
+import (
+ "fmt"
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+ "github.com/hashicorp/terraform-plugin-testing/terraform"
+)
+
+// testAccPreCheck validates the necessary test API keys exist
+// in the testing environment
+
+func TestSTFWebReceiverServicePreCheck(t *testing.T) {
+ if v := os.Getenv("TEST_STF_SITE_ID"); v == "" {
+ t.Fatal("TEST_STF_SITE_ID must be set for acceptance tests")
+ }
+
+ if v := os.Getenv("TEST_STF_WEBRECEIVER_VIRTUAL_PATH"); v == "" {
+ t.Fatal("TEST_STF_WEBRECEIVER_VIRTUAL_PATH must be set for acceptance tests")
+ }
+}
+
+func TestSTFWebReceiverServiceResource(t *testing.T) {
+ siteId := os.Getenv("TEST_STF_SITE_ID")
+ virtualPath := os.Getenv("TEST_STF_WEBRECEIVER_VIRTUAL_PATH")
+ resource.Test(t, resource.TestCase{
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ PreCheck: func() {
+ TestProviderPreCheck(t)
+ TestSTFWebReceiverServicePreCheck(t)
+ },
+ Steps: []resource.TestStep{
+
+ // Create and Read testing
+ {
+ Config: BuildSTFWebReceiverServiceResource(t, testSTFWebReceiverServiceResources),
+
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify site_id of STF WebReceiver Service
+ resource.TestCheckResourceAttr("citrix_stf_webreceiver_service.testSTFWebReceiverService", "site_id", siteId),
+ // Verify virtual_path of STF WebReceiver Service
+ resource.TestCheckResourceAttr("citrix_stf_webreceiver_service.testSTFWebReceiverService", "virtual_path", virtualPath),
+ ),
+ },
+
+ // ImportState testing
+ {
+ ResourceName: "citrix_stf_webreceiver_service.testSTFWebReceiverService",
+ ImportState: true,
+ ImportStateVerify: true,
+ ImportStateVerifyIdentifierAttribute: "virtual_path",
+ ImportStateIdFunc: generateImportStateId_STFWebReceiverService,
+ ImportStateVerifyIgnore: []string{"last_updated", "store_service"},
+ },
+
+ // Update testing for STF WebReceiver Service
+ {
+ Config: BuildSTFWebReceiverServiceResource(t, testSTFWebReceiverServiceResources_updated),
+
+ Check: resource.ComposeAggregateTestCheckFunc(
+ // Verify friendly_name of STF WebReceiver Service
+ resource.TestCheckResourceAttr("citrix_stf_webreceiver_service.testSTFWebReceiverService", "friendly_name", "WebReceiver_Updated"),
+
+ resource.TestCheckResourceAttr("citrix_stf_webreceiver_service.testSTFWebReceiverService", "authentication_methods.#", "2"),
+
+ resource.TestCheckResourceAttr("citrix_stf_webreceiver_service.testSTFWebReceiverService", "plugin_assistant.enabled", "true"),
+ ),
+ },
+ },
+ })
+}
+
+func BuildSTFWebReceiverServiceResource(t *testing.T, webreceiverService string) string {
+ siteId := os.Getenv("TEST_STF_SITE_ID")
+ virtualPath := os.Getenv("TEST_STF_WEBRECEIVER_VIRTUAL_PATH")
+
+ return BuildSTFStoreServiceResource(t, testSTFStoreServiceResources) + fmt.Sprintf(webreceiverService, siteId, virtualPath)
+
+}
+
+func generateImportStateId_STFWebReceiverService(state *terraform.State) (string, error) {
+ resourceName := "citrix_stf_webreceiver_service.testSTFWebReceiverService"
+ var rawState map[string]string
+ for _, m := range state.Modules {
+ if len(m.Resources) > 0 {
+ if v, ok := m.Resources[resourceName]; ok {
+ rawState = v.Primary.Attributes
+ }
+ }
+ }
+
+ return fmt.Sprintf("%s,%s", rawState["site_id"], rawState["virtual_path"]), nil
+}
+
+var (
+ testSTFWebReceiverServiceResources = `
+ resource "citrix_stf_webreceiver_service" "testSTFWebReceiverService" {
+ site_id = "%s"
+ virtual_path = "%s"
+ friendly_name = "WebReceiver"
+ store_service = citrix_stf_store_service.testSTFStoreService.virtual_path
+
+ }
+ `
+ testSTFWebReceiverServiceResources_updated = `
+ resource "citrix_stf_webreceiver_service" "testSTFWebReceiverService" {
+ site_id = "%s"
+ virtual_path = "%s"
+ friendly_name = "WebReceiver_Updated"
+ store_service = citrix_stf_store_service.testSTFStoreService.virtual_path
+ authentication_methods = [
+ "ExplicitForms",
+ "CitrixAGBasic"
+ ]
+ plugin_assistant = {
+ enabled = true
+ html5_single_tab_launch = true
+ }
+ }
+ `
+)
diff --git a/internal/test/zone_resource_test.go b/internal/test/zone_resource_test.go
index 892292a..fac068b 100644
--- a/internal/test/zone_resource_test.go
+++ b/internal/test/zone_resource_test.go
@@ -71,7 +71,7 @@ func TestZoneResource(t *testing.T) {
resource.TestCheckResourceAttr("citrix_zone.test", "metadata.3.name", "key4"),
resource.TestCheckResourceAttr("citrix_zone.test", "metadata.3.value", "value4"),
),
- SkipFunc: getSkipFunc(isOnPremises),
+ SkipFunc: skipForCloud(isOnPremises),
},
// Delete testing automatically occurs in TestCase
},
diff --git a/internal/util/common.go b/internal/util/common.go
index e53397f..49392e2 100644
--- a/internal/util/common.go
+++ b/internal/util/common.go
@@ -45,6 +45,9 @@ const IPv4Regex string = `^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$`
// IPv4 with https
const IPv4RegexWithProtocol string = `^(http|https)://((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$`
+// AWS Network Name
+const AwsNetworkNameRegex string = `^(\d{1,3}\.){3}\d{1,3}` + "`" + `/\d{1,3}\s\(vpc-.+\)\.network$`
+
// Date YYYY-MM-DD
const DateRegex string = `^\d{4}-\d{2}-\d{2}$`
@@ -60,6 +63,9 @@ const SslThumbprintRegex string = `^([0-9a-fA-F]{40}|[0-9a-fA-F]{64})$`
// AWS EC2 Instance Type
const AwsEc2InstanceTypeRegex string = `^[a-z0-9]{1,15}\.[a-z0-9]{1,15}$`
+// NOT_EXIST error code
+const NOT_EXIST string = "NOT_EXIST"
+
// Resource Types
const ImageVersionResourceType string = "ImageVersion"
const RegionResourceType string = "Region"
@@ -83,6 +89,12 @@ const AzureEphemeralOSDisk = "Azure_Ephemeral_OS_Disk"
const WindowsClientLicenseType string = "Windows_Client"
const WindowsServerLicenseType string = "Windows_Server"
+// GAC
+const AssignmentPriority = 0
+const GacAppName = "Workspace"
+
+var PlatformSettingsAssignedTo = []string{"AllUsersNoAuthentication"}
+
// Terraform model for name value string pair
type NameValueStringPairModel struct {
Name types.String `tfsdk:"name"`
@@ -209,6 +221,25 @@ func ConvertPrimitiveStringArrayToBaseStringArray(v []string) []types.String {
return res
}
+//
+// Helper function to convert array of golang primitive interface to array of terraform strings
+//
+// Array of golang primitive interface
+// Array of terraform strings
+func ConvertPrimitiveInterfaceArrayToBaseStringArray(v []interface{}) ([]types.String, string) {
+ res := []types.String{}
+ for _, val := range v {
+ switch stringVal := val.(type) {
+ case string:
+ res = append(res, types.StringValue(stringVal))
+ default:
+ return nil, "At this time, only string values are supported in arrays."
+ }
+ }
+
+ return res, ""
+}
+
//
// Helper function to convert terraform bool value to string
//
@@ -276,6 +307,21 @@ type HttpErrorBody struct {
// Response of the Get call. Raw http response. Error if failed to read the resource.
func ReadResource[ResponseType any](request any, ctx context.Context, client *citrixdaasclient.CitrixDaasClient, resp *resource.ReadResponse, resourceType, resourceIdOrName string) (ResponseType, *http.Response, error) {
response, httpResp, err := citrixdaasclient.ExecuteWithRetry[ResponseType](request, client)
+
+ // Resource Location does not return an error if not found
+ if resourceType == "Resource Location" {
+ if httpResp.StatusCode == http.StatusNoContent {
+ resp.Diagnostics.AddWarning(
+ fmt.Sprintf("%s not found", resourceType),
+ fmt.Sprintf("%s %s was not found and will be removed from the state file. An apply action will result in the creation of a new resource.", resourceType, resourceIdOrName),
+ )
+
+ resp.State.RemoveResource(ctx)
+ // Set err so that control does not go to refresh properties in the read method
+ err = fmt.Errorf("could not find resource location %s", resourceIdOrName)
+ return response, httpResp, err
+ }
+ }
if err != nil && resp != nil {
body, _ := io.ReadAll(httpResp.Body)
httpErrorBody := HttpErrorBody{}
@@ -498,3 +544,67 @@ func PanicHandler(diagnostics *diag.Diagnostics) {
)
}
}
+
+//
+// Helper function to get the allowed functional level values for setting the minimum functional level for machine catalog and deliver group.
+//
+func GetAllowedFunctionalLevelValues() []string {
+ res := []string{}
+ for _, v := range citrixorchestration.AllowedFunctionalLevelEnumValues {
+ if v != citrixorchestration.FUNCTIONALLEVEL_UNKNOWN &&
+ v != citrixorchestration.FUNCTIONALLEVEL_LMIN &&
+ v != citrixorchestration.FUNCTIONALLEVEL_LMAX {
+ res = append(res, string(v))
+ }
+ }
+
+ return res
+}
+
+//
+// Helper function to check the version requirement for DDC.
+//
+func CheckProductVersion(client *citrixdaasclient.CitrixDaasClient, diagnostic *diag.Diagnostics, requiredOrchestrationApiVersion int32, requiredProductMajorVersion int, requiredProductMinorVersion int, resourceName string) bool {
+ // Validate DDC version
+ if client.AuthConfig.OnPremises {
+ productVersionSplit := strings.Split(client.ClientConfig.ProductVersion, ".")
+ productMajorVersion, err := strconv.Atoi(productVersionSplit[0])
+ if err != nil {
+ diagnostic.AddError(
+ "Error parsing product major version",
+ "Error message: "+err.Error(),
+ )
+ return false
+ }
+
+ productMinorVersion, err := strconv.Atoi(productVersionSplit[1])
+ if err != nil {
+ diagnostic.AddError(
+ "Error parsing product minor version",
+ "Error message: "+err.Error(),
+ )
+ return false
+ }
+
+ if productMajorVersion < requiredProductMajorVersion ||
+ (productMajorVersion == requiredProductMajorVersion && productMinorVersion < requiredProductMinorVersion) {
+ diagnostic.AddError(
+ fmt.Sprintf("Current DDC version %d.%d does not support operations on %s resources.", productMajorVersion, productMinorVersion, resourceName),
+ fmt.Sprintf("Please upgrade your DDC product version to %d.%d or above to operate on %s resources.", requiredProductMajorVersion, requiredProductMinorVersion, resourceName),
+ )
+ return false
+ }
+ }
+
+ // Validate Orchestration version
+ if client.ClientConfig.OrchestrationApiVersion < requiredOrchestrationApiVersion {
+ diagnostic.AddError(
+ fmt.Sprintf("Current DDC version %d does not support operations on %s resources.", client.ClientConfig.OrchestrationApiVersion, resourceName),
+ "",
+ )
+
+ return false
+ }
+
+ return true
+}
diff --git a/internal/util/resource.go b/internal/util/resource.go
index 301e131..6d2f947 100644
--- a/internal/util/resource.go
+++ b/internal/util/resource.go
@@ -214,7 +214,12 @@ func GetFilteredResourcePathList(ctx context.Context, client *citrixdaasclient.C
req := client.ApiClient.HypervisorsAPIsDAAS.HypervisorsGetHypervisorAllResources(ctx, hypervisorId)
req = req.Children(1)
req = req.Path(folderPath)
- req = req.Type_([]string{resourceType})
+ // Skip resource type filter for on-prem hypervisors to avoid server side filtering timeout
+ if connectionType != citrixorchestration.HYPERVISORCONNECTIONTYPE_CUSTOM &&
+ connectionType != citrixorchestration.HYPERVISORCONNECTIONTYPE_XEN_SERVER &&
+ connectionType != citrixorchestration.HYPERVISORCONNECTIONTYPE_V_CENTER {
+ req = req.Type_([]string{resourceType})
+ }
resources, _, err := citrixdaasclient.AddRequestData(req, client).Execute()
if err != nil {
@@ -224,24 +229,28 @@ func GetFilteredResourcePathList(ctx context.Context, client *citrixdaasclient.C
result := []string{}
if filter != nil {
for _, child := range resources.Children {
- name := child.GetName()
- if connectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_AWS {
- name = strings.Split(name, " ")[0]
- }
- if Contains(filter, name) {
- if connectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_V_CENTER && strings.EqualFold(resourceType, NetworkResourceType) {
- result = append(result, child.GetRelativePath())
- } else if connectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_CUSTOM && strings.EqualFold(pluginId, NUTANIX_PLUGIN_ID) && strings.EqualFold(resourceType, NetworkResourceType) {
- result = append(result, child.GetFullName())
- } else {
- result = append(result, child.GetXDPath())
+ if strings.EqualFold(child.ResourceType, resourceType) {
+ name := child.GetName()
+ if connectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_AWS {
+ name = strings.Split(name, " ")[0]
+ }
+ if Contains(filter, name) {
+ if connectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_V_CENTER && strings.EqualFold(resourceType, NetworkResourceType) {
+ result = append(result, child.GetRelativePath())
+ } else if connectionType == citrixorchestration.HYPERVISORCONNECTIONTYPE_CUSTOM && strings.EqualFold(pluginId, NUTANIX_PLUGIN_ID) && strings.EqualFold(resourceType, NetworkResourceType) {
+ result = append(result, child.GetFullName())
+ } else {
+ result = append(result, child.GetXDPath())
+ }
}
}
}
} else {
//when the filter is empty
for _, child := range resources.Children {
- result = append(result, child.GetXDPath())
+ if strings.EqualFold(child.ResourceType, resourceType) {
+ result = append(result, child.GetXDPath())
+ }
}
}
@@ -256,3 +265,32 @@ func Contains[T comparable](s []T, e T) bool {
}
return false
}
+
+func ValidateHypervisorResource(ctx context.Context, client *citrixdaasclient.CitrixDaasClient, hypervisorName, hypervisorPoolName, resourcePath string) (bool, string) {
+ req := client.ApiClient.HypervisorsAPIsDAAS.HypervisorsValidateHypervisorResourcePoolResource(ctx, hypervisorName, hypervisorPoolName)
+ var validationRequestModel citrixorchestration.HypervisorResourceValidationRequestModel
+ validationRequestModel.SetPath(resourcePath)
+ req = req.HypervisorResourceValidationRequestModel(validationRequestModel)
+
+ responseModel, _, err := citrixdaasclient.AddRequestData(req, client).Execute()
+ if err != nil {
+ return false, ReadClientError(err)
+ }
+
+ reports := responseModel.GetReports()
+ index := slices.IndexFunc(reports, func(report citrixorchestration.ResourceValidationReportModel) bool {
+ return report.GetCategory() == citrixorchestration.RESOURCEVALIDATIONCATEGORY_MACHINE_PROFILE
+ })
+
+ report := reports[index]
+ if report.GetResult() == citrixorchestration.RESOURCEVALIDATIONRESULT_FAILED {
+ violations := report.GetViolations()
+ errIndex := slices.IndexFunc(violations, func(violation citrixorchestration.ResourceValidationViolationModel) bool {
+ return violation.GetLevel() == citrixorchestration.RESOURCEVIOLATIONLEVEL_ERROR
+ })
+ violation := violations[errIndex]
+ return false, violation.GetMessage()
+ }
+
+ return true, ""
+}
diff --git a/main.go b/main.go
index 12dec00..b29fda8 100644
--- a/main.go
+++ b/main.go
@@ -12,7 +12,7 @@ import (
)
// Provider documentation generation.
-//go:generate go run github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs generate --provider-name citrix
+//go:generate go run github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs generate --provider-name citrix --examples-dir internal/examples
var (
// these will be set by the goreleaser configuration
diff --git a/scripts/onboarding-helper/terraform-onboarding.ps1 b/scripts/onboarding-helper/terraform-onboarding.ps1
index 58e7339..372ec5f 100644
--- a/scripts/onboarding-helper/terraform-onboarding.ps1
+++ b/scripts/onboarding-helper/terraform-onboarding.ps1
@@ -118,12 +118,13 @@ function Invoke-WebRequestWithRetry {
while ($true) {
try {
$attempt++
+ Write-Verbose "Attempting $Method $Uri..."
$response = Invoke-WebRequest -Uri $Uri -Method $Method -Headers $Headers -ContentType $ContentType -Body $Body
return $response
}
catch {
if ($attempt -ge $MaxRetries) {
- Write-Output "Max retries reached. Throwing exception."
+ Write-Verbose "Max retries reached. Throwing exception."
throw
}
else {
@@ -132,7 +133,7 @@ function Invoke-WebRequestWithRetry {
# The jitter is a random number between 0 and 10% of the base delay.
$jitter = Get-Random -Minimum 0 -Maximum ([math]::Ceiling($baseDelay * $JitterFactor))
$delay = $baseDelay + $jitter
- Write-Output "Error occurred, retrying $Method $Uri after $delay seconds..."
+ Write-Verbose "Error occurred, retrying $Method $Uri after $delay seconds..."
Start-Sleep -Seconds $delay
}
}
@@ -200,7 +201,7 @@ function New-RequiredFiles {
# Create temporary import.tf for terraform import
if (!(Test-Path ".\citrix.tf")) {
New-Item -path ".\" -name "citrix.tf" -type "file" -Force
- Write-Output "Created new file for terraform citrix provider configuration."
+ Write-Verbose "Created new file for terraform citrix provider configuration."
}
if ($script:onPremise) {
$disable_ssl_verification = $script:disable_ssl.ToString().ToLower()
@@ -208,7 +209,7 @@ function New-RequiredFiles {
provider "citrix" {
hostname = "$script:hostname"
client_id = "$script:domainFqdn\\$script:clientId"
- client_secret = "$script:clientSecret"
+ # client_secret = ""
disable_ssl_verification = $disable_ssl_verification
}
"@
@@ -218,8 +219,8 @@ provider "citrix" {
$config = @"
provider "citrix" {
customer_id = "$script:customerId"
- client_id = "$script:clientId"
- client_secret = "$script:clientSecret"
+ client_id = "$script:domainFqdn\\$script:clientId"
+ # client_secret = ""
hostname = "$script:hostname"
environment = "$script:environment"
}
@@ -229,21 +230,21 @@ provider "citrix" {
if (!(Test-Path ".\import.tf")) {
New-Item -path ".\" -name "import.tf" -type "file" -Force
- Write-Output "Created new file for terraform import."
+ Write-Verbose "Created new file for terraform import."
}
else {
Clear-Content -path ".\import.tf"
- Write-Output "Cleared content in terraform import file."
+ Write-Verbose "Cleared content in terraform import file."
}
# Create resource.tf for final terraform resources
if (!(Test-Path ".\resource.tf")) {
New-Item -path ".\" -name "resource.tf" -type "file" -Force
- Write-Output "Created new file for terraform resource."
+ Write-Verbose "Created new file for terraform resource."
}
else {
Clear-Content -path ".\resource.tf"
- Write-Output "Cleared content in terraform resource file."
+ Write-Verbose "Cleared content in terraform resource file."
}
}
@@ -542,6 +543,18 @@ function PostProcessTerraformOutput {
Set-Content -Path ".\resource.tf" -Value $content
}
+function PostProcessProviderConfig {
+
+ # Post-process the provider config output in citrix.tf
+ $content = Get-Content -Path ".\citrix.tf" -Raw
+
+ # Uncomment field for client secret in provider config
+ $content =$content -replace "# ", ""
+
+ # Overwrite provider config with processed value
+ Set-Content -Path ".\citrix.tf" -Value $content
+}
+
if ($DisableSSLValidation) {
$code = @"
using System.Net;
@@ -574,27 +587,38 @@ $script:hypervisorResourceMap = @{
}
$script:applicationFolderPathMap = @{}
-Get-Site
-Get-RequestBaseUrl
-New-RequiredFiles
+# Set environment variables for client secret
+$env:CITRIX_CLIENT_SECRET = $ClientSecret
+
+try {
+ Get-Site
+ Get-RequestBaseUrl
+ New-RequiredFiles
+
+ # Get CVAD resources from existing site
+ Get-ExistingCVADResources
-# Get CVAD resources from existing site
-Get-ExistingCVADResources
+ # Initialize terraform
+ terraform init
-# Initialize terraform
-terraform init
+ # Import terraform resources into state
+ Import-ResourcesToState
-# Import terraform resources into state
-Import-ResourcesToState
+ # Export terraform resources
+ terraform show >> ".\resource.tf"
-# Export terraform resources
-terraform show >> ".\resource.tf"
+ # Post-process citrix.tf output
+ PostProcessProviderConfig
-# Post-process terraform output
-PostProcessTerraformOutput
+ # Post-process terraform output
+ PostProcessTerraformOutput
-# Remove temporary TF file
-Remove-Item ".\import.tf"
+ # Remove temporary TF file
+ Remove-Item ".\import.tf"
-# Format terraform files
-terraform fmt
\ No newline at end of file
+ # Format terraform files
+ terraform fmt
+} finally {
+ # Clean up environment variables for client secret
+ $env:CITRIX_CLIENT_SECRET = ''
+}
\ No newline at end of file
diff --git a/settings.cloud.example.json b/settings.cloud.example.json
index 73480c5..f272c18 100644
--- a/settings.cloud.example.json
+++ b/settings.cloud.example.json
@@ -221,7 +221,25 @@
// Policy Set env variable
"TEST_POLICY_SET_NAME" :"ctx-test-policy-set",
- "CITRIX_DDC_HOST_NAME" : "{customerId}.xendesktop.net"
+ "CITRIX_DDC_HOST_NAME" : "{customerId}.xendesktop.net",
+
+ // GAC Go Tests
+ "TEST_SETTINGS_CONFIG_SERVICE_URL" : "{workspace_url_with_port_number}",
+ "TEST_SETTINGS_CONFIG_NAME" : "test-settings-config",
+
+ // Resource Location Go Tests
+ "TEST_RESOURCE_LOCATION_NAME": "ctx-test-resource-location",
+
+ // StoreFront env variable
+ "SF_COMPUTER_NAME" : "{storefront_computer_name}",
+ "SF_AD_ADMAIN_USERNAME" : "{storefront_admin_username}",
+ "SF_AD_ADMIN_PASSWORD" : "{storefront_admin_password}",
+ "TEST_STF_SITE_ID" :"1",
+ "TEST_STF_SITE_ID_UPDATED" :"2",
+ "TEST_STF_Auth_Virtual_Path" : "/Citrix/Auth" ,
+ "TEST_STF_Store_Virtual_Path" : "/Citrix/Store",
+ "TEST_STF_WEBRECEIVER_VIRTUAL_PATH" : "/Citrix/StoreWeb"
+
},
"go.testTimeout": "30m"
}
\ No newline at end of file
diff --git a/settings.onprem.example.json b/settings.onprem.example.json
index bc987fd..9fbc8c4 100644
--- a/settings.onprem.example.json
+++ b/settings.onprem.example.json
@@ -224,7 +224,17 @@
// Policy Set env variable
"TEST_POLICY_SET_NAME" :"ctx-test-policy-set",
- "CITRIX_DDC_HOST_NAME" : "{ddcHostname}"
+ "CITRIX_DDC_HOST_NAME" : "{ddcHostname}",
+
+ // StoreFront env variable
+ "SF_COMPUTER_NAME" : "{storefront_computer_name}",
+ "SF_AD_ADMAIN_USERNAME" : "{storefront_admin_username}",
+ "SF_AD_ADMIN_PASSWORD" : "{storefront_admin_password}",
+ "TEST_STF_SITE_ID" :"1",
+ "TEST_STF_SITE_ID_UPDATED" :"2",
+ "TEST_STF_Auth_Virtual_Path" : "/Citrix/Auth" ,
+ "TEST_STF_Store_Virtual_Path" : "/Citrix/Store",
+ "TEST_STF_WEBRECEIVER_VIRTUAL_PATH" : "/Citrix/StoreWeb"
},
"go.testTimeout": "30m"
}
\ No newline at end of file