Automate Genesys User Provisioning with Terraform Provider v1.35.0

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_user resource introduced in the Genesys Cloud CX as Code provider version 1.35.0.
  • The code uses the HashiCorp Terraform CLI and the genesyscloud Terraform 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:read and user:write OAuth scopes.
  • Terraform State: An existing state file containing genesyscloud_user resources (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:

  1. Division ID: The division_id is now strictly enforced. If omitted, the user defaults to the default division. Explicitly setting it prevents drift if your organization uses multiple divisions.
  2. 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.
  3. Routing Email: The routing_email_address must be a valid, unique email address. The provider sends a PUT /api/v2/users/{userId} request. If the API returns a 409 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:

  1. Save the files in a new directory.
  2. Set the environment variables GENESYS_CLOUD_CLIENT_ID and GENESYS_CLOUD_CLIENT_SECRET.
  3. Run terraform init.
  4. Run terraform plan to review the changes.
  5. Run terraform apply to 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:

  1. Verify the email address is unique.
  2. 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>
    
  3. If you intend to create a new user, change the email and routing_email_address attributes 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:

  1. You cannot change user types directly via Terraform for all transitions.
  2. Use the Genesys Cloud UI to change the user type manually.
  3. Update the Terraform configuration to match the new user type.
  4. Run terraform plan to 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:

  1. Ensure the genesyscloud_division resource is created before the user.
  2. Check that the division name is unique.
  3. 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:

  1. Create the skills using the genesyscloud_skill resource.
  2. Reference the skill IDs or names correctly.
  3. Ensure the skills are in the same division as the user, or use global skills.

Official References