Bulk User and Provider Setup
This document provides information about setting up multiple providers, users, and models using automated scripts. The script automates the process of configuring your AI Controller with the necessary components for immediate use.
Setup Script Overview
The setup script handles the following tasks:
- License Configuration: Registers your AI Controller license
- Provider Setup: Adds AI providers with their respective models and API keys
- User Account Creation: Creates user accounts with appropriate roles and permissions
- Verification: Checks that all components were properly configured
Using the Setup Script
The setup script is available in both Bash (for Linux/Mac) and PowerShell (for Windows) formats. Choose the appropriate script for your operating system.
#!/bin/bash
# Debug and verify flags
DEBUG=0
VERIFY_ONLY=0
# Parse command line arguments
while getopts "dv" opt; do
case $opt in
d)
DEBUG=1
echo "Debug mode enabled"
;;
v)
VERIFY_ONLY=1
echo "Verification mode enabled"
;;
\?)
echo "Invalid option: -$OPTARG" >&2
echo "Usage: $0 [-d] [-v]" >&2
echo " -d: Debug mode" >&2
echo " -v: Verification only mode" >&2
exit 1
;;
esac
done
# Debug print function
debug_print() {
if [ $DEBUG -eq 1 ]; then
echo "[DEBUG] $1"
fi
}
# Base URL from the docker setup
BASE_URL="http://localhost:8080"
# Read the configuration data
CONFIG_DATA=$(cat config.json)
debug_print "Read configuration data: ${CONFIG_DATA}"
# Function to handle errors
check_response() {
if [ $1 -ne 0 ]; then
echo "Error: $2 failed with status code $1"
exit 1
fi
}
# Set curl verbose flag based on debug mode
CURL_OPTS="-s -k"
if [ $DEBUG -eq 1 ]; then
CURL_OPTS="-v -s -k"
fi
echo "Logging in to AIC server..."
# Extract access token from AICUserCookie
LOGIN_RESPONSE=$(curl $CURL_OPTS -i -X POST \
-H "Content-Type: application/vnd.api+json" \
-d '{"data":{"attributes":{"grantType":"password","userName":"admin","password":"admin"}}}' \
"${BASE_URL}/login/")
debug_print "Login response: ${LOGIN_RESPONSE}"
# Extract AICUserCookie from the login response
ACCESS_TOKEN=$(echo "$LOGIN_RESPONSE" | grep -i "Set-Cookie" | grep "AICUserCookie" | cut -d"=" -f2 | cut -d";" -f1)
check_response $? "Login"
debug_print "Access token obtained: ${ACCESS_TOKEN}"
echo "Successfully logged in"
# Setup function
perform_setup() {
# Check and setup License
if echo "${CONFIG_DATA}" | jq -e '.license' > /dev/null; then
echo "Setting up license..."
LICENSE_KEY=$(echo "${CONFIG_DATA}" | jq -r '.license.licenseKey')
LICENSE_REQUEST='{"data":{"attributes":{"licenceKey":"'${LICENSE_KEY}'"}}}'
debug_print "License request payload: ${LICENSE_REQUEST}"
LICENSE_RESPONSE=$(curl $CURL_OPTS -i -X PATCH \
-H "Content-Type: application/vnd.api+json" \
-H "Cookie: AICUserCookie=${ACCESS_TOKEN}" \
--data "${LICENSE_REQUEST}" \
"${BASE_URL}/licensing/")
check_response $? "License addition"
echo "✓ License setup completed"
# Short pause to allow the license to be processed
sleep 10
else
echo "⚠ No license configuration found, skipping license setup"
fi
# Check and setup Providers
if echo "${CONFIG_DATA}" | jq -e '.providers' > /dev/null; then
echo "Adding providers and their models..."
for provider in $(echo "${CONFIG_DATA}" | jq -c '.providers[]'); do
name=$(echo $provider | jq -r '.name')
debug_print "Processing provider: ${name}"
provider_request='{"data":{"attributes":'$(echo $provider)'}}'
debug_print "Provider request payload: ${provider_request}"
provider_response=$(curl $CURL_OPTS -i -X POST \
-H "Content-Type: application/vnd.api+json" \
-H "Cookie: AICUserCookie=${ACCESS_TOKEN}" \
--data "${provider_request}" \
"${BASE_URL}/providers/")
response_code=$(echo "$provider_response" | head -n 1 | awk '{print $2}')
if [ "$response_code" != "201" ]; then
echo "❌ Failed to add provider: ${name}"
echo "Response: ${provider_response}"
exit 1
fi
echo "✓ Added provider: ${name}"
done
else
echo "⚠ No providers configuration found, skipping providers setup"
fi
# Check and setup Users
if echo "${CONFIG_DATA}" | jq -e '.users' > /dev/null; then
echo "Adding users..."
added_count=0
skipped_count=0
echo "${CONFIG_DATA}" | jq -c '.users[]' | while read -r user; do
username=$(echo $user | jq -r '.userName')
debug_print "Processing user: ${username}"
user_request='{"data":{"attributes":'$(echo $user)'}}'
debug_print "User request payload: ${user_request}"
user_response=$(curl $CURL_OPTS -i -X POST \
-H "Content-Type: application/vnd.api+json" \
-H "Cookie: AICUserCookie=${ACCESS_TOKEN}" \
--data "${user_request}" \
"${BASE_URL}/users/")
response_code=$(echo "$user_response" | head -n 1 | awk '{print $2}')
debug_print "Response code: ${response_code}"
if [ "$response_code" = "201" ]; then
echo "✓ Added user: ${username}"
added_count=$((added_count + 1))
elif [ "$response_code" = "409" ]; then
echo "⚠ Skipped existing user: ${username}"
skipped_count=$((skipped_count + 1))
else
echo "❌ Failed to add user: ${username}"
echo "Response: ${user_response}"
exit 1
fi
done
else
echo "⚠ No users configuration found, skipping users setup"
fi
}
# Verification function
perform_verification() {
echo -e "\nVerifying setup..."
# License verification
if echo "${CONFIG_DATA}" | jq -e '.license' > /dev/null; then
echo "Verifying license..."
LICENSE_STATUS=$(curl $CURL_OPTS -X GET \
-H "Content-Type: application/vnd.api+json" \
-H "Cookie: AICUserCookie=${ACCESS_TOKEN}" \
"${BASE_URL}/licensing/")
if echo "$LICENSE_STATUS" | grep -q '"valid":true'; then
echo "✓ License verification successful"
else
echo "✗ License verification failed"
exit 1
fi
fi
# Providers verification
if echo "${CONFIG_DATA}" | jq -e '.providers' > /dev/null; then
echo "Verifying providers..."
PROVIDERS_RESPONSE=$(curl $CURL_OPTS -X GET \
-H "Content-Type: application/vnd.api+json" \
-H "Cookie: AICUserCookie=${ACCESS_TOKEN}" \
"${BASE_URL}/providers/")
expected_providers=$(echo "${CONFIG_DATA}" | jq '.providers | length')
actual_providers=$(echo "${PROVIDERS_RESPONSE}" | jq '. | length')
if [ "$actual_providers" -eq "$expected_providers" ]; then
echo "✓ Providers verification successful"
else
echo "✗ Providers verification failed (expected: ${expected_providers}, actual: ${actual_providers})"
exit 1
fi
fi
# Users verification
if echo "${CONFIG_DATA}" | jq -e '.users' > /dev/null; then
echo "Verifying users..."
USERS_RESPONSE=$(curl $CURL_OPTS -X GET \
-H "Content-Type: application/vnd.api+json" \
-H "Cookie: AICUserCookie=${ACCESS_TOKEN}" \
"${BASE_URL}/users/")
actual_users=$(echo "${USERS_RESPONSE}" | jq '. | length')
expected_users=$(echo "${CONFIG_DATA}" | jq '.users | length')
if [ "$actual_users" -ge "$expected_users" ]; then
echo "✓ Users verification successful"
else
echo "✗ Users verification failed (expected at least: ${expected_users}, actual: ${actual_users})"
exit 1
fi
fi
echo -e "\nVerification completed successfully!"
}
# Main execution logic
if [ $VERIFY_ONLY -eq 1 ]; then
perform_verification
else
perform_setup
perform_verification
fi
# Debug and verify flags
param(
[switch]$Debug,
[switch]$VerifyOnly
)
# Debug print function
function Debug-Print {
param([string]$Message)
if ($Debug) {
Write-Host "[DEBUG] $Message" -ForegroundColor Cyan
}
}
# Base URL from the docker setup
$BASE_URL = "http://localhost:8080"
# Read the configuration data
$CONFIG_DATA = Get-Content -Raw -Path "config.json" | ConvertFrom-Json
Debug-Print "Read configuration data: $($CONFIG_DATA | ConvertTo-Json -Compress)"
# Function to handle errors
function Check-Response {
param(
[int]$StatusCode,
[string]$Operation
)
if ($StatusCode -lt 200 -or $StatusCode -ge 300) {
Write-Host "Error: $Operation failed with status code $StatusCode" -ForegroundColor Red
exit 1
}
}
# Invoke REST API with proper parameters
function Invoke-AicApi {
param(
[string]$Method,
[string]$Uri,
[object]$Body = $null,
[string]$ContentType = "application/vnd.api+json",
[string]$Cookie = ""
)
$headers = @{
"Content-Type" = $ContentType
}
if ($Cookie) {
$headers["Cookie"] = "AICUserCookie=$Cookie"
}
$params = @{
Method = $Method
Uri = $Uri
Headers = $headers
UseBasicParsing = $true
}
if ($Body) {
$params["Body"] = ($Body | ConvertTo-Json -Depth 10 -Compress)
}
if ($Debug) {
Write-Host "Request: $Method $Uri" -ForegroundColor Gray
if ($Body) {
Write-Host "Request Body: $($params.Body)" -ForegroundColor Gray
}
}
try {
$response = Invoke-WebRequest @params
return $response
}
catch {
$statusCode = $_.Exception.Response.StatusCode.value__
$statusDescription = $_.Exception.Response.StatusDescription
if ($Debug) {
Write-Host "Response Status: $statusCode $statusDescription" -ForegroundColor Red
if ($_.ErrorDetails.Message) {
Write-Host "Response Body: $($_.ErrorDetails.Message)" -ForegroundColor Red
}
}
return [PSCustomObject]@{
StatusCode = $statusCode
Content = $_.ErrorDetails.Message
Headers = $_.Exception.Response.Headers
}
}
}
Write-Host "Logging in to AIC server..." -ForegroundColor Green
# Login to get access token
$loginBody = @{
data = @{
attributes = @{
grantType = "password"
userName = "admin"
password = "admin"
}
}
}
$loginResponse = Invoke-AicApi -Method "POST" -Uri "$BASE_URL/login/" -Body $loginBody
Debug-Print "Login response status: $($loginResponse.StatusCode)"
# Extract AICUserCookie from the login response
$cookieHeader = $loginResponse.Headers["Set-Cookie"]
$ACCESS_TOKEN = ($cookieHeader -split ";" | Where-Object { $_ -match "AICUserCookie=" }) -replace "AICUserCookie=", ""
Check-Response -StatusCode $loginResponse.StatusCode -Operation "Login"
Debug-Print "Access token obtained: $ACCESS_TOKEN"
Write-Host "Successfully logged in" -ForegroundColor Green
# Setup function
function Perform-Setup {
# Check and setup License
if ($CONFIG_DATA.license) {
Write-Host "Setting up license..." -ForegroundColor Green
$licenseKey = $CONFIG_DATA.license.licenseKey
$licenseBody = @{
data = @{
attributes = @{
licenceKey = $licenseKey
}
}
}
Debug-Print "License request payload: $($licenseBody | ConvertTo-Json -Compress)"
$licenseResponse = Invoke-AicApi -Method "PATCH" -Uri "$BASE_URL/licensing/" -Body $licenseBody -Cookie $ACCESS_TOKEN
Check-Response -StatusCode $licenseResponse.StatusCode -Operation "License addition"
Write-Host "✓ License setup completed" -ForegroundColor Green
# Short pause to allow the license to be processed
Start-Sleep -Seconds 10
}
else {
Write-Host "⚠ No license configuration found, skipping license setup" -ForegroundColor Yellow
}
# Check and setup Providers
if ($CONFIG_DATA.providers) {
Write-Host "Adding providers and their models..." -ForegroundColor Green
foreach ($provider in $CONFIG_DATA.providers) {
$name = $provider.name
Debug-Print "Processing provider: $name"
$providerBody = @{
data = @{
attributes = $provider
}
}
Debug-Print "Provider request payload: $($providerBody | ConvertTo-Json -Compress)"
$providerResponse = Invoke-AicApi -Method "POST" -Uri "$BASE_URL/providers/" -Body $providerBody -Cookie $ACCESS_TOKEN
if ($providerResponse.StatusCode -ne 201) {
Write-Host "❌ Failed to add provider: $name" -ForegroundColor Red
Write-Host "Response: $($providerResponse.Content)" -ForegroundColor Red
exit 1
}
Write-Host "✓ Added provider: $name" -ForegroundColor Green
}
}
else {
Write-Host "⚠ No providers configuration found, skipping providers setup" -ForegroundColor Yellow
}
# Check and setup Users
if ($CONFIG_DATA.users) {
Write-Host "Adding users..." -ForegroundColor Green
$addedCount = 0
$skippedCount = 0
foreach ($user in $CONFIG_DATA.users) {
$username = $user.userName
Debug-Print "Processing user: $username"
$userBody = @{
data = @{
attributes = $user
}
}
Debug-Print "User request payload: $($userBody | ConvertTo-Json -Compress)"
$userResponse = Invoke-AicApi -Method "POST" -Uri "$BASE_URL/users/" -Body $userBody -Cookie $ACCESS_TOKEN
if ($userResponse.StatusCode -eq 201) {
Write-Host "✓ Added user: $username" -ForegroundColor Green
$addedCount++
}
elseif ($userResponse.StatusCode -eq 409) {
Write-Host "⚠ Skipped existing user: $username" -ForegroundColor Yellow
$skippedCount++
}
else {
Write-Host "❌ Failed to add user: $username" -ForegroundColor Red
Write-Host "Response: $($userResponse.Content)" -ForegroundColor Red
exit 1
}
}
Write-Host "User addition summary: $addedCount added, $skippedCount skipped" -ForegroundColor Green
}
else {
Write-Host "⚠ No users configuration found, skipping users setup" -ForegroundColor Yellow
}
}
# Verification function
function Perform-Verification {
Write-Host "`nVerifying setup..." -ForegroundColor Green
# License verification
if ($CONFIG_DATA.license) {
Write-Host "Verifying license..." -ForegroundColor Green
$licenseResponse = Invoke-AicApi -Method "GET" -Uri "$BASE_URL/licensing/" -Cookie $ACCESS_TOKEN
$licenseStatus = $licenseResponse.Content | ConvertFrom-Json
if ($licenseStatus.valid -eq $true) {
Write-Host "✓ License verification successful" -ForegroundColor Green
}
else {
Write-Host "✗ License verification failed" -ForegroundColor Red
exit 1
}
}
# Providers verification
if ($CONFIG_DATA.providers) {
Write-Host "Verifying providers..." -ForegroundColor Green
$providersResponse = Invoke-AicApi -Method "GET" -Uri "$BASE_URL/providers/" -Cookie $ACCESS_TOKEN
$providers = $providersResponse.Content | ConvertFrom-Json
$expectedProviders = $CONFIG_DATA.providers.Count
$actualProviders = $providers.Count
if ($actualProviders -eq $expectedProviders) {
Write-Host "✓ Providers verification successful" -ForegroundColor Green
}
else {
Write-Host "✗ Providers verification failed (expected: $expectedProviders, actual: $actualProviders)" -ForegroundColor Red
exit 1
}
}
# Users verification
if ($CONFIG_DATA.users) {
Write-Host "Verifying users..." -ForegroundColor Green
$usersResponse = Invoke-AicApi -Method "GET" -Uri "$BASE_URL/users/" -Cookie $ACCESS_TOKEN
$users = $usersResponse.Content | ConvertFrom-Json
$expectedUsers = $CONFIG_DATA.users.Count
$actualUsers = $users.Count
if ($actualUsers -ge $expectedUsers) {
Write-Host "✓ Users verification successful" -ForegroundColor Green
}
else {
Write-Host "✗ Users verification failed (expected at least: $expectedUsers, actual: $actualUsers)" -ForegroundColor Red
exit 1
}
}
Write-Host "`nVerification completed successfully!" -ForegroundColor Green
}
# Main execution logic
if ($VerifyOnly) {
Perform-Verification
}
else {
Perform-Setup
Perform-Verification
}
Configuration File
The setup script requires a JSON configuration file that defines the providers, models, users, and license information. Create a file named config.json
with the following structure:
{
"license": {
"licenseKey": "your-license-key-here"
},
"providers": [
{
"id": 1,
"name": "openai",
"url": "https://api.openai.com/v1/chat/completions",
"authMethod": "Bearer",
"apiKey": "your-api-key-here",
"models": [
"gpt-4o",
"gpt-3.5-turbo",
"dall-e-3"
]
},
{
"id": 2,
"name": "anthropic",
"url": "https://api.anthropic.com/v1/messages",
"authMethod": "Bearer",
"apiKey": "your-api-key-here",
"models": [
"claude-3-opus-20240229",
"claude-3-sonnet-20240229",
"claude-3-haiku-20240307"
]
}
],
"users": [
{
"userName": "john.doe",
"password": "SecurePassword123",
"displayName": "John Doe",
"email": "john.doe@example.com",
"active": true,
"isDeleted": false,
"roles": [{"id": 2, "name": "User"}]
},
{
"userName": "jane.smith",
"password": "SecurePassword456",
"displayName": "Jane Smith",
"email": "jane.smith@example.com",
"active": true,
"isDeleted": false,
"roles": [{"id": 1, "name": "Admin"}]
}
]
}
Running the Script
Prerequisites
-
For the Bash script:
- Linux or macOS system
curl
andjq
installed- Bash shell
-
For the PowerShell script:
- Windows system
- PowerShell 5.1 or later
Execution Steps
- Save the appropriate script (Bash or PowerShell) to your local system
- Create the
config.json
file with your configuration - Place both files in the same directory
For Bash (Linux/Mac)
# Make the script executable
chmod +x setup.sh
# Run the script
./setup.sh
# For debug mode
./setup.sh -d
# For verification only
./setup.sh -v
For PowerShell (Windows)
# Run the script
.\setup.ps1
# For debug mode
.\setup.ps1 -Debug
# For verification only
.\setup.ps1 -VerifyOnly
Troubleshooting
If you encounter issues running the script:
- Check that your
config.json
file is properly formatted - Ensure your AI Controller server is running and accessible at the specified URL
- Verify that the admin credentials are correct
- Run the script in debug mode to get more detailed error information
For further assistance, contact the AI Controller support team.
Updated: 2025-05-20