Update Genesys Cloud User Configurations for Terraform Provider v1.35.0 Schema Changes

Update Genesys Cloud User Configurations for Terraform Provider v1.35.0 Schema Changes

What You Will Build

  • This tutorial demonstrates how to update Terraform configurations to comply with the breaking schema changes introduced in the Genesys Cloud CX as Code provider version 1.35.0.
  • The code uses the HashiCorp Terraform framework with the genesyscloud provider.
  • The implementation covers HCL (HashiCorp Configuration Language) syntax updates and the necessary state migration steps.

Prerequisites

  • Terraform Version: 1.5.0 or later.
  • Provider Version: Genesys Cloud Terraform Provider v1.35.0 (or later).
  • Genesys Cloud Environment: An active Genesys Cloud organization with API credentials.
  • Authentication: An OAuth client ID and client secret with the user:read and user:write scopes.
  • External Dependencies: None beyond the standard Terraform CLI and the provider itself.

Authentication Setup

The Genesys Cloud Terraform provider handles OAuth 2.0 client credentials flow automatically. You must configure the provider block with your environment details. In production environments, use environment variables or a secrets manager to inject credentials.

terraform {
  required_providers {
    genesyscloud = {
      source  = "mikesdotcom/genesyscloud"
      version = "1.35.0"
    }
  }
}

provider "genesyscloud" {
  # Use environment variables for sensitive data
  client_id     = var.genesys_client_id
  client_secret = var.genesys_client_secret
  environment   = "mypurecloud.com"
}

Required OAuth Scopes:

  • user:read
  • user:write
  • user:read:bulk (if importing multiple users)

If the provider fails to authenticate, you will receive a 401 Unauthorized error during terraform plan. Ensure the client application in the Genesys Cloud admin console is set to “Public” or has the correct redirect URIs configured if using interactive flows, though client credentials are standard for CI/CD pipelines.

Implementation

Step 1: Identify the Breaking Change in genesyscloud_user

In provider versions prior to 1.35.0, the genesyscloud_user resource allowed certain attributes to be defined at the root level or within loosely structured blocks. Version 1.35.0 introduced a stricter schema to align with the underlying Genesys Cloud API v2 structures. Specifically, the routing_skills and routing_email_skills attributes have been moved into a dedicated routing_profile block or require explicit association with a routing profile ID.

The most common breaking change involves the removal of direct routing_skills definitions on the user resource when a routing_profile is also specified. The provider now enforces that skills are managed either exclusively through the routing profile or exclusively through the user resource, but not both simultaneously in a conflicting manner.

Old Schema (v1.34.0 and earlier):

resource "genesyscloud_user" "example_user" {
  name                = "Test User"
  email               = "test.user@example.com"
  division_id         = var.default_division_id
  routing_skills      = [var.skill_id_1, var.skill_id_2]
  routing_profile_id  = var.routing_profile_id
}

New Schema (v1.35.0+):
The routing_skills attribute is now deprecated when routing_profile_id is present. Skills must be managed via the genesyscloud_routing_profile resource or removed from the user configuration entirely to avoid drift.

Step 2: Refactor the User Resource Definition

You must update your HCL to remove conflicting skill definitions. If your skills are tied to a specific routing profile, ensure the genesyscloud_routing_profile resource includes the skills.

Corrected HCL:

resource "genesyscloud_user" "example_user" {
  name             = "Test User"
  email            = "test.user@example.com"
  division_id      = var.default_division_id
  routing_profile_id = var.routing_profile_id
  # routing_skills is removed to prevent schema conflict
}

If you require skills to be assigned directly to the user without a routing profile (which is rare in modern architectures but possible), you must omit the routing_profile_id.

Alternative Configuration (No Routing Profile):

resource "genesyscloud_user" "agent_only" {
  name             = "Agent Only"
  email            = "agent.only@example.com"
  division_id      = var.default_division_id
  routing_skills   = [var.skill_id_1]
  # routing_profile_id is omitted
}

Error Handling:
If you attempt to apply the old schema with the new provider, Terraform will throw a validation error:

Error: "routing_skills": conflicts with routing_profile_id

Step 3: Update Routing Profile Resources

Since skills are no longer managed on the user resource when a routing profile is present, you must ensure the genesyscloud_routing_profile resource explicitly defines the skills.

Updated Routing Profile:

resource "genesyscloud_routing_profile" "support_profile" {
  name        = "Support Profile"
  division_id = var.default_division_id
  
  skills {
    id = var.skill_id_1
    level = 1
  }
  
  skills {
    id = var.skill_id_2
    level = 2
  }
  
  default_outbound_wrapup_code_id = var.wrapup_code_id
}

Expected Response:
When you run terraform plan with the updated configuration, Terraform should show no changes to the genesyscloud_user resource regarding skills, and the genesyscloud_routing_profile should show the skills as managed.

Step 4: Handle State Migration

If you have existing state files, Terraform may detect that the routing_skills attribute is being removed from the user resource. This will trigger a plan to remove skills from the user in the Genesys Cloud API. However, since the skills are now managed by the routing profile, the user effectively retains access to those skills through the profile.

Warning:
Terraform might plan to delete the skills from the user resource. You must verify that the routing profile already has the skills assigned. If the routing profile does not have the skills, Terraform will remove them from the user, and the routing profile will not add them, resulting in a loss of skill assignments.

Mitigation Strategy:

  1. Ensure the genesyscloud_routing_profile resource includes all necessary skills before updating the user resource.
  2. Run terraform plan to review the changes.
  3. If Terraform plans to remove skills from the user and add them to the routing profile, this is acceptable.
  4. If Terraform plans to remove skills from the user and does not plan to add them to the routing profile, you must manually add the skills to the routing profile resource in your HCL.

Complete Working Example

The following is a complete, runnable Terraform configuration that demonstrates the correct usage of the genesyscloud_user resource in provider v1.35.0.

main.tf

terraform {
  required_providers {
    genesyscloud = {
      source  = "mikesdotcom/genesyscloud"
      version = "1.35.0"
    }
  }
}

provider "genesyscloud" {
  client_id     = var.genesys_client_id
  client_secret = var.genesys_client_secret
  environment   = "mypurecloud.com"
}

variable "genesys_client_id" {
  description = "Genesys Cloud OAuth Client ID"
  type        = string
  sensitive   = true
}

variable "genesys_client_secret" {
  description = "Genesys Cloud OAuth Client Secret"
  type        = string
  sensitive   = true
}

variable "default_division_id" {
  description = "Default Division ID"
  type        = string
}

variable "skill_id_1" {
  description = "ID of Skill 1"
  type        = string
}

variable "skill_id_2" {
  description = "ID of Skill 2"
  type        = string
}

variable "wrapup_code_id" {
  description = "ID of Default Wrap-up Code"
  type        = string
}

# Define the Routing Profile with Skills
resource "genesyscloud_routing_profile" "support_profile" {
  name        = "Support Profile v1.35"
  division_id = var.default_division_id
  
  skills {
    id = var.skill_id_1
    level = 1
  }
  
  skills {
    id = var.skill_id_2
    level = 2
  }
  
  default_outbound_wrapup_code_id = var.wrapup_code_id
}

# Define the User with Routing Profile
resource "genesyscloud_user" "example_user" {
  name             = "Terraform Test User"
  email            = "terraform.test@example.com"
  division_id      = var.default_division_id
  routing_profile_id = genesyscloud_routing_profile.support_profile.id
  
  # Note: routing_skills is omitted to comply with v1.35.0 schema
}

output "user_id" {
  value = genesyscloud_user.example_user.id
}

output "routing_profile_id" {
  value = genesyscloud_routing_profile.support_profile.id
}

variables.tf

# This file is included in main.tf for completeness in this example.
# In a real project, separate variables into their own file.

terraform.tfvars

genesys_client_id     = "your_client_id_here"
genesys_client_secret = "your_client_secret_here"
default_division_id   = "your_division_id_here"
skill_id_1            = "your_skill_id_1_here"
skill_id_2            = "your_skill_id_2_here"
wrapup_code_id        = "your_wrapup_code_id_here"

Common Errors & Debugging

Error: conflicts with routing_profile_id

What causes it:
You have specified both routing_skills and routing_profile_id in the genesyscloud_user resource. The v1.35.0 schema prohibits this combination to prevent ambiguity in skill assignment.

How to fix it:
Remove the routing_skills attribute from the user resource. Ensure that the skills are defined in the genesyscloud_routing_profile resource referenced by routing_profile_id.

Code showing the fix:

# Incorrect
resource "genesyscloud_user" "bad_user" {
  name             = "Bad User"
  email            = "bad@example.com"
  division_id      = var.default_division_id
  routing_profile_id = var.routing_profile_id
  routing_skills   = [var.skill_id_1] # Remove this line
}

# Correct
resource "genesyscloud_user" "good_user" {
  name             = "Good User"
  email            = "good@example.com"
  division_id      = var.default_division_id
  routing_profile_id = var.routing_profile_id
}

Error: 422 Unprocessable Entity

What causes it:
The underlying Genesys Cloud API rejects the request because the routing profile ID is invalid or does not exist in the specified division.

How to fix it:
Verify that the routing_profile_id exists and is in the same division as the user, or that the user division allows cross-division assignments if your organization policy permits.

Code showing the fix:

# Ensure the routing profile is created before the user
resource "genesyscloud_routing_profile" "profile" {
  name        = "Profile"
  division_id = var.default_division_id
}

resource "genesyscloud_user" "user" {
  name             = "User"
  email            = "user@example.com"
  division_id      = var.default_division_id
  routing_profile_id = genesyscloud_routing_profile.profile.id
}

Error: State Migration Failed

What causes it:
Terraform attempts to remove skills from the user resource, but the API returns an error because the skills are still referenced elsewhere or the user is active in a way that prevents modification.

How to fix it:
Use terraform state mv to manually migrate the state if necessary, or temporarily disable the user, update the configuration, and then re-enable the user. In most cases, ensuring the routing profile has the skills first prevents this error.

Official References