Creating agentic AI to deploy ARO cluster using Terraform with Red Hat OpenShift AI on ARO and Azure OpenAI

Learn how to create an artificial intelligence (AI) that can deploy Microsoft Azure Red Hat® OpenShift® clusters using Terraform. Explore prompt-based infrastructure and how it can be used to maintain clusters in your own environment.

Learn how to create an artificial intelligence (AI) that can deploy Microsoft Azure Red Hat® OpenShift® clusters using Terraform. Explore prompt-based infrastructure and how it can be used to maintain clusters in your own environment.

Setup for creating Agentic AI to deploy ARO clusters using Terraform

10 mins

There are several steps to getting your agentic AI created so it can be sophisticated enough to deploy and destroy clusters as needed. In order to accomplish this, we must create setup files within Azure, as well as create a parser. 

What will you learn?

  • How to create a setup file within Azure Red Hat® OpenShift®
  • How to create a parser using OpenAI

What do you need before starting?

  • Azure Red Hat OpenShift cluster
  • Azure OpenAI model access

Creating the setup file within Azure

First, you will create the setup file and to do so, you would need your Azure credentials such as your Azure Client ID, Azure Client Secret, Azure Tenant ID, and Azure Subscription ID.

You can retrieve these credentials via Azure Portal or via az cli, the latter being the easier one. To do so via CLI, first run:

$ az account show

From the output, use the id value as your Azure Subscription ID, and tenantId as your Azure Tenant ID.

As for the other credentials, you can either use the existing Service Principal or create a new one. For the latter, run the following (give it a proper name and replace the subscription ID):

$ az ad sp create-for-rbac --name "YOUR-NEW-SP-NAME" --role contributor --scopes /subscriptions/YOUR-SUBSCRIPTION-ID

And if you choose to update an existing service principal:

$ az role assignment create --assignee “YOUR-APPLICATION-ID” --role "Contributor" --scope /subscriptions/YOUR-SUBSCRIPTION-ID

From the output, take the appId as your Azure Client ID and the password as your Azure Secret ID. Keep all these credentials handy for this step.

The setup here essentially is an environment bootstrapping module that handles dependency installation (Terraform, Azure CLI), configures Azure service principal credentials, and ensures the execution environment is properly initialized.

On the Red Hat OpenShift AI dashboard, launch a Jupyter notebook instance. To do so, on the navigation pane, click Application, then click Enabled, and then on the Jupyter tab, select Launch application

In this example, you will be using TensorFlow 2025.1 image with Medium container size for the notebook. This might take a few minutes to provision.

And once the notebook is ready, go to the File tab on the upper left and choose New, and select Python File. Copy the lines below, save and rename the file as setup.py. Replace the env vars with your Azure credentials.


import os
import sys
from pathlib import Path
import subprocess

def setup_environment():
   os.environ.update({
        'AZURE_CLIENT_ID': 'YOUR-AZURE-CLIENT-ID',
        'AZURE_CLIENT_SECRET': 'YOUR-AZURE-CLIENT-SECRET',
        'AZURE_TENANT_ID': 'YOUR-AZURE-TENANT-ID',
        'AZURE_SUBSCRIPTION_ID': 'YOUR-AZURE-SUBSCRIPTION-ID'
    })
    
    terraform_installed = install_terraform()
    az_installed = install_azure_cli()
    openai_installed = install_openai()  
    
    return {
        "terraform_installed": terraform_installed,
        "az_cli_installed": az_installed,
        "openai_sdk_installed": openai_installed  
    }

def install_terraform():
    local_bin = Path.home() / '.local' / 'bin'
    local_bin.mkdir(parents=True, exist_ok=True)
    os.environ['PATH'] = f"{local_bin}:{os.environ['PATH']}"
    
    try:
        subprocess.run(["terraform", "--version"], capture_output=True, text=True)
        return True
    except FileNotFoundError:
        try:
            subprocess.run(["wget", "-q", "https://releases.hashicorp.com/terraform/1.7.4/terraform_1.7.4_linux_amd64.zip"], check=True)
            subprocess.run(["unzip", "-o", "terraform_1.7.4_linux_amd64.zip", "-d", str(local_bin)], check=True)
            subprocess.run(["chmod", "+x", f"{local_bin}/terraform"], check=True)
            subprocess.run(["rm", "terraform_1.7.4_linux_amd64.zip"], check=True)
            return True
        except:
            return False

def install_azure_cli():
    try:
        subprocess.run(["az", "--version"], capture_output=True, text=True)
        return True
    except FileNotFoundError:
        try:
            subprocess.run([sys.executable, "-m", "pip", "install", "--quiet", "azure-cli"], check=True)
            return True
        except:
            return False

def install_openai(): 
    try:
        import openai
        return True
    except ImportError:
        try:
            subprocess.run([sys.executable, "-m", "pip", "install", "--quiet", "openai"], check=True)
            return True
        except:
            return False

if __name__ == "__main__":
    setup_environment()

Creating the OpenAI parser

Next, let's create the parser which acts as the Natural Language Processing interface using an Azure OpenAI’s model, i.e. GPT-4o-mini.  to extract structured parameters from unstructured text. That way, the agent will understand our prompts intelligently and convert it into technical parameters the system can use.

Here you will also set up the default parameters if not specified in the user prompts such as cluster name, region, worker node size, worker node count, version, and private/public. Note that some of these default parameters are slightly different from those of the Terraform repository. For example, the default region here is westus and the default cluster name is agentic-aro, so feel free to adjust these parameters accordingly. Also note that it will spin up the latest version if users do not specify it in the prompt.

Create a new Python file called parser.py and copy the below code and save it.

import os
import json
import re
from typing import Dict, Any
from openai import AzureOpenAI
class AzureOpenAIParser:
    def __init__(self, 
                 azure_endpoint=None,
                 api_key=None, 
                 api_version="2024-12-01-preview",  
                 deployment_name="gpt-4o-mini",     
                 debug=False):
        self.debug = debug
        self.deployment_name = deployment_name
        
        self.azure_endpoint = azure_endpoint or os.environ.get('AZURE_OPENAI_ENDPOINT')
        self.api_key = api_key or os.environ.get('AZURE_OPENAI_KEY')
        
        if not self.azure_endpoint or not self.api_key:
            raise ValueError("Azure OpenAI endpoint and API key must be provided")
        
        self.client = AzureOpenAI(
            azure_endpoint=self.azure_endpoint,
            api_key=self.api_key,
            api_version=api_version
        )
    
    def is_available(self) -> bool:
        try:
            self.client.chat.completions.create(
                model=self.deployment_name,
                messages=[{"role": "user", "content": "test"}],
                max_tokens=5
            )
            return True
        except:
            return False
    
    def extract_parameters(self, request: str, param_schema: Dict[str, Any]) -> Dict[str, Any]:
        if not self.is_available():
            return {}
        
        schema_text = "\n".join([
            f"- {param}: {details.get('description', '')} (default: {details.get('default', 'None')})"
            for param, details in param_schema.items()
        ])
        
        instruction = """
Important specific rules for ARO parameters:
1. If request mentions "private", set "is_private" to true
2. Default "name" should be "agentic-aro" unless specified
3. Default region is "westus" unless specified
4. Default VM size is "Standard_D4s_v3" unless specified
5. Minimum worker_node_count is 3
"""
        
        prompt = f"""
You are an AI assistant helping to extract parameters from a deployment request for an Azure Red Hat OpenShift (ARO) cluster.
REQUEST: "{request}"
Extract the following parameters:
{schema_text}
{instruction}
Format your response as a valid JSON object with the parameter names as keys.
ONLY include the extracted parameters in your response, nothing else - no explanation, no comments.
Return ONLY valid JSON.
If a parameter is not explicitly mentioned in the request, use the default value provided.
RESPONSE (JSON only):
"""
        
        try:
            response = self.client.chat.completions.create(
                model=self.deployment_name,
                messages=[
                    {"role": "system", "content": "You are a helpful assistant that extracts parameters from text and returns only JSON."},
                    {"role": "user", "content": prompt}
                ],
                temperature=0.1,
                max_tokens=1000
            )
            
            content = response.choices[0].message.content
            
            json_match = re.search(r'\{[^}]+\}', content, re.DOTALL)
            if json_match:
                params = json.loads(json_match.group())
            else:
                params = json.loads(content)
            
            self._apply_defaults(params, param_schema)
            return params
            
        except Exception as e:
            if self.debug:
                print(f"Error extracting parameters: {e}")
            return {}
    
    def _apply_defaults(self, params, param_schema):
        for param, details in param_schema.items():
            if param not in params or params[param] is None:
                params[param] = details.get("default")
    
    def extract_aro_parameters(self, request: str) -> Dict[str, Any]:
        param_schema = {
            "name": {"type": "string", "default": "agentic-aro", "description": "Cluster name"},
            "region": {"type": "string", "default": "westus", "description": "Azure region"},
            "worker_vm_size": {"type": "string", "default": "Standard_D4s_v3", "description": "VM size for workers"},
            "worker_node_count": {"type": "integer", "default": 3, "description": "Number of worker nodes"},
            "version": {"type": "string", "default": None, "description": "ARO version"},
            "is_private": {"type": "boolean", "default": False, "description": "Private cluster"}
        }
        
        params = self.extract_parameters(request, param_schema)
        
        if params.get("worker_node_count", 0) < 3:
            params["worker_node_count"] = 3
        
        return params
    
    def extract_deletion_parameters(self, request: str) -> Dict[str, Any]:
        param_schema = {
            "name": {"type": "string", "default": None, "description": "Cluster name to delete"}
        }
        
        schema_text = "- name: Cluster name to delete (default: None)"
        
        prompt = f"""
You are an AI assistant helping to extract parameters from a deletion request for an ARO cluster.
REQUEST: "{request}"
Extract the following parameters:
{schema_text}
The "name" should be the specific name of the ARO cluster to be deleted (e.g., "my-cluster", "test-deployment").
If no name is specified, use "agentic-aro" as default.
Format your response as a valid JSON object.
ONLY include the extracted parameters in your response, nothing else.
RESPONSE (JSON only):
"""
        
        try:
            response = self.client.chat.completions.create(
                model=self.deployment_name,
                messages=[
                    {"role": "system", "content": "You are a helpful assistant that extracts parameters from text and returns only JSON."},
                    {"role": "user", "content": prompt}
                ],
                temperature=0.1,
                max_tokens=500
            )
            
            content = response.choices[0].message.content
            
            json_match = re.search(r'\{[^}]+\}', content, re.DOTALL)
            if json_match:
                params = json.loads(json_match.group())
            else:
                params = json.loads(content)
            
            if not params.get("name"):
                params["name"] = "agentic-aro"
            
            return params
            
        except Exception as e:
            if self.debug:
                print(f"Error extracting deletion parameters: {e}")
            return {"name": "agentic-aro"}

Once this file is saved, we’re good to proceed onto the deployment specific portions of this task.

Previous resource
Prerequisites
Next resource
Deployment agent

This learning path is for operations teams or system administrators

Developers may want to check out Getting started with Red Hat OpenShift AI on developers.redhat.com. 

Get started on developers.redhat.com

Hybrid Cloud Logo LinkedIn YouTube Facebook Twitter

Platforms

Tools

Try, buy, sell

Communicate

About Red Hat

We’re the world’s leading provider of enterprise open source solutions—including Linux, cloud, container, and Kubernetes. We deliver hardened solutions that make it easier for enterprises to work across platforms and environments, from the core datacenter to the network edge.

© 2025 Red Hat