Importing Existing Genesys Cloud Resources into Terraform State
What You Will Build
- You will execute
terraform importcommands to attach existing Genesys Cloud entities to your Terraform state file. - You will utilize the Genesys Cloud Terraform Provider to manage infrastructure as code without destroying and recreating live resources.
- You will use Bash and HCL to configure and execute the import workflow.
Prerequisites
- Terraform Version: 1.0 or later.
- Genesys Cloud Provider Version: 1.0.0 or later (check
registry.terraform.io/mypurecloud/genesyscloud/latest). - Genesys Cloud API Credentials: A valid OAuth Client ID and Client Secret with the necessary scopes for the resources you are importing.
- Resource Identifiers: The unique ID (UUID) of the Genesys Cloud resource you wish to import. This is found in the Admin UI URL or via API calls.
- Required Scopes:
- Users:
user:read - Queues:
routing:queue:read - Users (for assignment):
routing:queue:write - Webchat:
webchat:widget:read
- Users:
Authentication Setup
Terraform handles authentication via environment variables or a credentials block in the provider configuration. For importing resources, the provider must be initialized before the import command can succeed.
Create a file named main.tf with the following provider configuration. This example uses environment variables for credentials, which is the standard secure practice in CI/CD pipelines.
terraform {
required_providers {
genesyscloud = {
source = "myPureCloud/genesyscloud"
version = "~> 1.0"
}
}
}
provider "genesyscloud" {
# The provider reads these from environment variables automatically:
# GENESYS_CLOUD_CLIENT_ID
# GENESYS_CLOUD_CLIENT_SECRET
# GENESYS_CLOUD_BASE_URL (optional, defaults to https://api.mypurecloud.com)
}
Set the environment variables in your terminal before running any Terraform commands:
export GENESYS_CLOUD_CLIENT_ID="your_client_id_here"
export GENESYS_CLOUD_CLIENT_SECRET="your_client_secret_here"
Initialize the working directory:
terraform init
Implementation
Step 1: Identify the Resource and Its ID
The terraform import command requires the exact resource type and the unique identifier used by the Genesys Cloud API. This ID is typically a UUID.
For example, if you are importing a Queue, you must know the Queue ID. You can find this by navigating to the Queue in the Genesys Cloud Admin UI. The URL will look like:
https://{{domain}}.mypurecloud.com/admin/routing/queues/queue/{{queue-id}}
The {{queue-id}} is the value you need. Alternatively, you can retrieve it via the API:
curl -X GET "https://api.mypurecloud.com/api/v2/routing/queues" \
-H "Authorization: Bearer $YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" | jq '.entities[] | select(.name == "Support Queue") | .id'
Step 2: Define the Resource Configuration
Before importing, you must define the resource in your HCL file. The configuration does not need to match the existing state of the resource in Genesys Cloud exactly at this stage, but it must be syntactically correct and represent the resource type.
If you define the resource incorrectly, terraform import will fail or result in a massive diff that attempts to destroy or modify the resource immediately.
Create queue_import.tf:
resource "genesyscloud_routing_queue" "support_queue" {
name = "Support Queue"
description = "General support queue for customer inquiries"
# Note: These fields might not be fully populated yet.
# The import process will pull the current state from Genesys Cloud.
}
Step 3: Execute the Import Command
Run the terraform import command. The syntax is:
terraform import <resource_type>.<resource_name> <resource_id>
For the queue defined above:
terraform import genesyscloud_routing_queue.support_queue a1b2c3d4-e5f6-7890-abcd-ef1234567890
Replace a1b2c3d4-e5f6-7890-abcd-ef1234567890 with the actual UUID of your queue.
Expected Output:
genesyscloud_routing_queue.support_queue: Importing from ID "a1b2c3d4-e5f6-7890-abcd-ef1234567890"...
genesyscloud_routing_queue.support_queue: Import prepared!
Prepared genesyscloud_routing_queue for import
genesyscloud_routing_queue.support_queue: Refreshing state... [id=a1b2c3d4-e5f6-7890-abcd-ef1234567890]
Import successful!
The resources that were imported are shown above. These resources are now in
your local state and will be managed by Terraform.
Step 4: Verify and Align State
After the import, run terraform plan. This is the critical step. Terraform will compare the state it just pulled from Genesys Cloud against your HCL definition.
terraform plan
Scenario A: No Changes
If your HCL matches the remote state, you will see “No changes. Your infrastructure matches the configuration.”
Scenario B: Changes Detected
If your HCL is sparse, Terraform will propose changes to align the remote resource with your HCL. For example, if you did not specify outbound_email in your HCL, but the queue has one set, Terraform might propose removing it (depending on the field’s lifecycle rules).
To fix this, you must update your HCL to reflect the actual state of the resource. You can export the current state to JSON to see the full attribute map:
terraform state show -json genesyscloud_routing_queue.support_queue > queue_state.json
Review queue_state.json, update queue_import.tf to match the desired state, and run terraform plan again until it shows no changes.
Complete Working Example
This example demonstrates importing a Genesys Cloud User.
1. main.tf
terraform {
required_providers {
genesyscloud = {
source = "myPureCloud/genesyscloud"
version = "~> 1.0"
}
}
}
provider "genesyscloud" {}
2. user_import.tf
resource "genesyscloud_user" "existing_user" {
name = "John Doe"
email = "john.doe@example.com"
division_id = "division-uuid-here" # Must match the user's actual division
}
3. Import Command
# Export credentials
export GENESYS_CLOUD_CLIENT_ID="your_client_id"
export GENESYS_CLOUD_CLIENT_SECRET="your_client_secret"
# Initialize
terraform init
# Import the user using their UUID
terraform import genesyscloud_user.existing_user 12345678-1234-1234-1234-123456789012
# Check for drift
terraform plan
4. Handling Complex Imports (Nested Resources)
Some resources, like Queues, have nested blocks like outbound_email or wrapup_code. If these are not present in your HCL, the import will succeed, but terraform plan will show a deletion of these nested blocks.
You must manually add these blocks to your HCL. There is no automatic “export to HCL” command in Terraform. You must read the terraform state show output and manually construct the HCL.
resource "genesyscloud_routing_queue" "support_queue" {
name = "Support Queue"
description = "General support queue"
# Added after import to prevent drift
outbound_email {
enabled = true
from_name = "Support Team"
from_email = "support@example.com"
}
}
Common Errors & Debugging
Error: 404 Not Found
Cause: The resource ID provided in the import command does not exist, or the OAuth client does not have permission to view it.
Fix:
- Verify the ID is correct. Copy it directly from the URL in the Admin UI.
- Check the OAuth scopes. Ensure the client has
readpermissions for the resource type. - Verify the
division_idif the resource is division-scoped. Some imports require the division ID to be part of the import identifier string.
Example for Division-Scoped Resources:
For some resources, the import ID is resource_id:division_id.
terraform import genesyscloud_user.existing_user 12345678-1234-1234-1234-123456789012:division-uuid-here
Error: 403 Forbidden
Cause: The OAuth client lacks the specific scope required to read the resource.
Fix:
Add the required scope to your OAuth client in the Genesys Cloud Admin UI. For users, ensure user:read is present. For queues, ensure routing:queue:read is present.
Error: 422 Unprocessable Entity
Cause: The resource configuration in your HCL is invalid or missing required fields that the provider expects during the refresh phase.
Fix:
Check the Terraform provider documentation for the specific resource. Ensure all required fields are defined in the HCL block before importing.
Error: State Mismatch After Import
Cause: The imported state contains attributes that are not defined in your HCL, leading to planned deletions.
Fix:
Run terraform state show <resource_address> to see the full state. Update your HCL to include these attributes. Use lifecycle { ignore_changes = [...] } if you intentionally want to manage certain fields outside of Terraform.
resource "genesyscloud_routing_queue" "support_queue" {
name = "Support Queue"
lifecycle {
ignore_changes = [
description, # Allow manual edits to description
]
}
}