Update Terraform Configs for Genesys Cloud User Schema v1.35.0 Breaking Changes

Update Terraform Configs for Genesys Cloud User Schema v1.35.0 Breaking Changes

What You Will Build

  • Update existing Terraform configurations to handle the removal of deprecated attributes and the introduction of new required fields in the genesyscloud_user resource.
  • Use the Genesys Cloud Terraform Provider (version 1.35.0 or later) to provision users without encountering schema validation errors.
  • The tutorial covers HCL configuration updates and the underlying REST API changes that drive these Terraform modifications.

Prerequisites

  • Terraform: Version 1.5.0 or higher.
  • Genesys Cloud Provider: Version 1.35.0 or higher.
  • Genesys Cloud Organization: An active org with API credentials (OAuth Client ID and Secret) or a valid API Token.
  • Required Scopes: user:read, user:write, user:group:read (if assigning groups).
  • Environment: A local machine with Terraform installed and access to a Git repository or local directory for state management.

Authentication Setup

Terraform handles authentication via environment variables or a credentials file. For this tutorial, we assume environment variable configuration, which is the standard for CI/CD pipelines.

Set the following environment variables in your shell or CI/CD runner:

export GENESYS_CLOUD_CLIENT_ID="your_client_id"
export GENESYS_CLOUD_CLIENT_SECRET="your_client_secret"
export GENESYS_CLOUD_REGION="mypurecloud.com"

Initialize the provider in your main.tf:

terraform {
  required_providers {
    genesyscloud = {
      source  = "mikesplain/genesyscloud"
      version = ">= 1.35.0"
    }
  }
}

provider "genesyscloud" {
  # Authentication is handled via environment variables
}

Implementation

Step 1: Identify the Breaking Change in genesyscloud_user

In provider version 1.35.0, the genesyscloud_user resource underwent a significant schema update. The primary breaking change involves the deprecation and removal of the routing_email_address attribute as a standalone top-level field in certain contexts, and stricter validation on routing_email_domain. Additionally, the groups attribute handling changed to enforce stricter ID validation.

Previously, users might have defined a user with:

# OUTDATED CONFIGURATION (Pre-1.35.0)
resource "genesyscloud_user" "example_user" {
  name             = "John Doe"
  email            = "john.doe@example.com"
  routing_email_address = "john.doe@company.com" # This may now be invalid or handled differently
  groups {
    group_id       = "some-group-id"
    role           = "agent" # Role is often managed separately now
    skill_level    = 5
  }
}

In v1.35.0, the schema aligns closer to the actual Genesys Cloud REST API (/api/v2/users). The routing_email_address is now strictly validated against the organization’s allowed email domains. If your organization uses external email routing, you must ensure the domain is configured in Genesys Cloud Admin. Furthermore, group assignments are often better managed via the genesyscloud_user_group resource to avoid circular dependencies.

Step 2: Update the User Resource Definition

Update your genesyscloud_user resource to reflect the new schema. We will remove the deprecated routing_email_address if it is causing conflicts, or ensure it matches the validated domain. We will also separate group assignments.

resource "genesyscloud_user" "example_user" {
  name             = "John Doe"
  email            = "john.doe@example.com"
  
  # In v1.35.0, routing_email_address is still available but strictly validated.
  # If your org does not have external email routing configured, this will fail.
  # If you are unsure, omit it initially and add it after the user is created.
  # routing_email_address = "john.doe@company.com" 

  division_id = var.default_division_id

  # Phone numbers are now strictly validated
  phone_numbers = [
    {
      number_type = "WORK"
      number      = "+15551234567"
      primary     = true
    }
  ]

  # Time zone is required
  user_settings {
    timezone = "America/New_York"
    language = "en-US"
  }
}

Step 3: Handle Group Assignments Separately

To avoid state drift and dependency issues, define group assignments in a separate resource. This approach is more robust in v1.35.0.

# First, define or reference the group
data "genesyscloud_group" "agents_group" {
  name = "Agents"
}

resource "genesyscloud_user_group" "example_user_agent" {
  user_id  = genesyscloud_user.example_user.id
  group_id = data.genesyscloud_group.agents_group.id
  role     = "agent"
  
  # Skill levels can be defined here if needed
  # skills = [
  #   {
  #     skill_id    = data.genesyscloud_skill.general.id
  #     skill_level = 5
  #   }
  # ]
}

Step 4: Validate the API Payload

Behind the scenes, Terraform sends a POST /api/v2/users request. The breaking change affects the JSON payload structure. Ensure your configuration generates a valid payload.

Example of the expected JSON body for a valid user creation in v1.35.0:

{
  "name": "John Doe",
  "email": "john.doe@example.com",
  "divisionId": "division-uuid-here",
  "phoneNumbers": [
    {
      "numberType": "WORK",
      "number": "+15551234567",
      "primary": true
    }
  ],
  "userSettings": {
    "timezone": "America/New_York",
    "language": "en-US"
  }
}

If you include routingEmailAddress, it must match a domain configured in your Genesys Cloud organization. Otherwise, the API returns a 400 Bad Request.

Complete Working Example

Below is a complete, copy-pasteable Terraform configuration that creates a user with the v1.35.0 schema requirements.

terraform {
  required_providers {
    genesyscloud = {
      source  = "mikesplain/genesyscloud"
      version = ">= 1.35.0"
    }
  }
}

provider "genesyscloud" {
  # Auth via ENV vars: GENESYS_CLOUD_CLIENT_ID, GENESYS_CLOUD_CLIENT_SECRET, GENESYS_CLOUD_REGION
}

variable "default_division_id" {
  description = "The ID of the default division for the user"
  type        = string
  default     = "default-division-id" # Replace with your actual division ID
}

variable "agent_group_name" {
  description = "Name of the agent group to assign the user to"
  type        = string
  default     = "Agents"
}

resource "genesyscloud_user" "new_agent" {
  name             = "Jane Smith"
  email            = "jane.smith@example.com"
  division_id      = var.default_division_id

  # Phone number configuration
  phone_numbers = [
    {
      number_type = "WORK"
      number      = "+15559876543"
      primary     = true
    }
  ]

  # User settings are now often nested or required
  user_settings {
    timezone = "America/Chicago"
    language = "en-US"
  }
}

# Data source to look up the group
data "genesyscloud_group" "target_group" {
  name = var.agent_group_name
}

# Assign the user to the group
resource "genesyscloud_user_group" "new_agent_assignment" {
  user_id  = genesyscloud_user.new_agent.id
  group_id = data.genesyscloud_group.target_group.id
  role     = "agent"
}

# Output the user ID for reference
output "user_id" {
  value = genesyscloud_user.new_agent.id
}

To run this:

  1. Save the code to main.tf.
  2. Run terraform init.
  3. Run terraform plan to verify no schema errors.
  4. Run terraform apply to create the user.

Common Errors & Debugging

Error: 400 Bad Request: Invalid routing email address

Cause: The routing_email_address provided does not match any configured domain in the Genesys Cloud organization, or external email routing is not enabled.

Fix:

  1. Check Genesys Cloud Admin > Settings > Email Routing to see allowed domains.
  2. In Terraform, either update the routing_email_address to use a valid domain or remove the attribute if not needed.
  3. If you need to set it after creation, use a null_resource with local-exec to call the API directly, or wait until the domain is configured.
# If you must set it and are unsure of the domain, omit it initially.
# Then, after the user is created, you can update it via API or Terraform plan again.

Error: 403 Forbidden: Insufficient permissions

Cause: The OAuth client used by Terraform lacks the user:write scope.

Fix:

  1. Go to Genesys Cloud Admin > Security > API Credentials.
  2. Edit your client credentials.
  3. Add the user:write and user:read scopes.
  4. Regenerate the secret if necessary and update your environment variables.

Error: ValidationError: divisionId is required

Cause: The division_id is not provided, and the provider cannot determine the default division for the user.

Fix:

  1. Explicitly set division_id in the genesyscloud_user resource.
  2. You can find the division ID by running terraform import on an existing user or by querying the API: GET /api/v2/divisions.
# Example of fetching division ID via data source
data "genesyscloud_division" "default" {
  name = "Default"
}

resource "genesyscloud_user" "new_agent" {
  division_id = data.genesyscloud_division.default.id
  # ... other config
}

Official References