Automate Genesys User Provisioning with Terraform Provider v1.35.0
What You Will Build
- This tutorial demonstrates how to update existing Terraform configurations to accommodate the breaking schema changes in the
genesyscloud_userresource introduced in the Genesys Cloud CX as Code provider version 1.35.0. - The code uses the HashiCorp Terraform CLI and the
genesyscloudTerraform provider to provision and manage user identities via Infrastructure as Code. - The implementation covers HCL (HashiCorp Configuration Language) syntax and the underlying REST API interactions managed by the provider.
Prerequisites
- Terraform Version: 1.0.0 or higher.
- Genesys Cloud CX as Code Provider: v1.35.0 or higher.
- Genesys Cloud Organization: An active Genesys Cloud organization with API access.
- API Credentials: A Genesys Cloud API client ID and secret with the
user:readanduser:writeOAuth scopes. - Terraform State: An existing state file containing
genesyscloud_userresources (if migrating) or a new empty state.
Authentication Setup
The Genesys Cloud Terraform provider handles OAuth 2.0 client credentials flow automatically. You do not need to write Python or JavaScript to authenticate. Instead, you configure the provider block in your Terraform root module.
Ensure your Terraform configuration includes the provider block with the required authentication method. For production environments, use environment variables to avoid committing secrets.
terraform {
required_providers {
genesyscloud = {
source = "mikeschub/genesyscloud"
version = "1.35.0" # Explicitly pin to the version containing the breaking change
}
}
}
provider "genesyscloud" {
# Use environment variables for security
# export GENESYS_CLOUD_CLIENT_ID="your_client_id"
# export GENESYS_CLOUD_CLIENT_SECRET="your_client_secret"
client_id = var.genesys_client_id
client_secret = var.genesys_client_secret
}
The provider requires the user:read and user:write scopes to manage user resources. If your API client lacks these scopes, you will receive a 403 Forbidden error during the terraform apply phase.
Implementation
Step 1: Understand the Breaking Change in v1.35.0
In versions prior to 1.35.0, the genesyscloud_user resource allowed direct manipulation of certain attributes that are now immutable or managed differently in the Genesys Cloud API. Specifically, the schema has been tightened to align with the underlying REST API constraints.
The most significant breaking change involves the user_type and routing_email_address attributes. In previous versions, you could sometimes toggle a user type from AGENT to ADMIN directly in the resource block. In v1.35.0, the provider enforces stricter validation. If you attempt to change a property that the API does not support as an update operation, the provider will now fail fast with a clear error message rather than silently ignoring the change or causing a partial state update.
Additionally, the genesyscloud_user resource now explicitly requires the routing_email_address to be unique across the organization. The provider performs a pre-flight check via the POST /api/v2/users endpoint. If the email is already in use, the apply fails.
Step 2: Update the User Resource Schema
You must review your existing HCL files for genesyscloud_user resources. The following example shows the correct schema structure for v1.35.0.
Old Pattern (Pre-1.35.0 - Potentially Deprecated Behavior):
# Do not use this pattern in v1.35.0
resource "genesyscloud_user" "legacy_user" {
name = "John Doe"
email = "john.doe@example.com"
user_type = "AGENT" # Direct setting was looser in validation
routing_email_address = "john.doe@example.com"
}
New Pattern (v1.35.0 Compliant):
resource "genesyscloud_user" "current_user" {
name = "Jane Smith"
email = "jane.smith@example.com"
user_type = "AGENT"
routing_email_address = "jane.smith@example.com"
division_id = genesyscloud_division.general.id
auto_offline_enabled = true
wrap_up_policy = "OPT_IN"
default_group_id = genesyscloud_group.default_group.id
# Explicitly define skills if required by your routing strategy
skills = [
"english",
"support"
]
}
Key changes to note:
- Division ID: The
division_idis now strictly enforced. If omitted, the user defaults to the default division. Explicitly setting it prevents drift if your organization uses multiple divisions. - Skills: Skills are now managed as a list of strings. In older versions, this might have been handled via a separate data source or nested block. The v1.35.0 provider consolidates this.
- Routing Email: The
routing_email_addressmust be a valid, unique email address. The provider sends aPUT /api/v2/users/{userId}request. If the API returns a409 Conflict, Terraform will halt and report the conflict.
Step 3: Handle State Migration for Existing Resources
If you have an existing Terraform state file with users created in versions prior to 1.35.0, you must refresh the state to align with the new schema. The provider may detect differences between the state and the actual API resource due to the stricter schema.
Run the following command to import or refresh the state:
terraform init -upgrade
terraform plan
If terraform plan shows changes for existing users, review the proposed changes carefully. The provider might be attempting to “fix” attributes that were previously ignored. For example, if a user was created without a division_id, the plan might show an addition of the default division ID. This is expected behavior and ensures consistency.
If you encounter errors related to user_type changes, you may need to manually update the Genesys Cloud UI or use a script to adjust the user type before Terraform can manage it. The API does not allow changing user_type from ADMIN to AGENT directly via the standard update endpoint in all contexts.
Complete Working Example
The following is a complete, copy-pasteable Terraform configuration. It creates a division, a group, and a user with the updated v1.35.0 schema.
main.tf
terraform {
required_providers {
genesyscloud = {
source = "mikeschub/genesyscloud"
version = "1.35.0"
}
}
}
provider "genesyscloud" {
client_id = var.genesys_client_id
client_secret = var.genesys_client_secret
}
variable "genesys_client_id" {
description = "Genesys Cloud API Client ID"
type = string
sensitive = true
}
variable "genesys_client_secret" {
description = "Genesys Cloud API Client Secret"
type = string
sensitive = true
}
# Create a division for the user
resource "genesyscloud_division" "general" {
name = "General Division"
description = "Default division for automated users"
}
# Create a group for the user
resource "genesyscloud_group" "support_group" {
name = "Support Team"
description = "Group for support agents"
division_id = genesyscloud_division.general.id
}
# Create the user with v1.35.0 compliant schema
resource "genesyscloud_user" "support_agent" {
name = "Terraform Test Agent"
email = "terraform.test.agent@your-domain.com"
user_type = "AGENT"
routing_email_address = "terraform.test.agent@your-domain.com"
division_id = genesyscloud_division.general.id
auto_offline_enabled = true
wrap_up_policy = "OPT_IN"
default_group_id = genesyscloud_group.support_group.id
# Set initial skills
skills = [
"billing",
"technical_support"
]
# Lifecycle block to prevent accidental deletion
lifecycle {
prevent_destroy = true
}
}
# Output the user ID for verification
output "user_id" {
value = genesyscloud_user.support_agent.id
description = "The ID of the created user"
}
variables.tf
# No additional variables needed beyond those in main.tf
To run this example:
- Save the files in a new directory.
- Set the environment variables
GENESYS_CLOUD_CLIENT_IDandGENESYS_CLOUD_CLIENT_SECRET. - Run
terraform init. - Run
terraform planto review the changes. - Run
terraform applyto create the resources.
Common Errors & Debugging
Error: 409 Conflict: Email address already exists
What causes it:
The routing_email_address provided in the genesyscloud_user resource is already associated with another user in your Genesys Cloud organization. The API endpoint POST /api/v2/users returns a 409 status code.
How to fix it:
- Verify the email address is unique.
- If the user already exists, import the existing user into Terraform state instead of creating a new one.
terraform import genesyscloud_user.support_agent <user_id_from_genesys_cloud> - If you intend to create a new user, change the
emailandrouting_email_addressattributes to a unique value.
Error: Invalid user_type transition
What causes it:
You attempted to change the user_type from ADMIN to AGENT or vice versa in a single apply. The Genesys Cloud API restricts certain user type transitions. The v1.35.0 provider now validates this locally and sends a more descriptive error.
How to fix it:
- You cannot change user types directly via Terraform for all transitions.
- Use the Genesys Cloud UI to change the user type manually.
- Update the Terraform configuration to match the new user type.
- Run
terraform planto ensure no further changes are detected.
Error: Division ID not found
What causes it:
The division_id specified in the genesyscloud_user resource does not exist or is inaccessible to the API client.
How to fix it:
- Ensure the
genesyscloud_divisionresource is created before the user. - Check that the division name is unique.
- Verify that the API client has permissions to read the division.
Error: Skill not found
What causes it:
The skills listed in the skills attribute do not exist in your Genesys Cloud organization. The provider attempts to link existing skills.
How to fix it:
- Create the skills using the
genesyscloud_skillresource. - Reference the skill IDs or names correctly.
- Ensure the skills are in the same division as the user, or use global skills.