Skip to content

Commit 1471b5a

Browse files
committed
Enhancing validation script
1 parent a6ff670 commit 1471b5a

File tree

1 file changed

+159
-12
lines changed

1 file changed

+159
-12
lines changed

deployment/scripts/validate-deployment.sh

Lines changed: 159 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,104 @@
22

33
# MaaS Platform Deployment Validation Script
44
# This script validates that the MaaS platform is correctly deployed and functional
5+
#
6+
# Usage: ./validate-deployment.sh [MODEL_NAME]
7+
# MODEL_NAME: Optional. If provided, the script will validate using this specific model
58

69
# Note: We don't use 'set -e' because we want to continue validation even if some checks fail
710

11+
# Parse command line arguments
12+
REQUESTED_MODEL=""
13+
CUSTOM_REQUEST_PAYLOAD=""
14+
INFERENCE_ENDPOINT="chat/completions" # Default to chat completions
15+
16+
# Show help if requested
17+
if [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
18+
echo "MaaS Platform Deployment Validation Script"
19+
echo ""
20+
echo "Usage: $0 [OPTIONS] [MODEL_NAME]"
21+
echo ""
22+
echo "This script validates that the MaaS platform is correctly deployed and functional."
23+
echo "It performs checks on components, gateway status, policies, and API endpoints."
24+
echo ""
25+
echo "Arguments:"
26+
echo " MODEL_NAME Optional. Name of a specific model to use for validation."
27+
echo " If not provided, the first available model will be used."
28+
echo ""
29+
echo "Options:"
30+
echo " -h, --help Show this help message and exit"
31+
echo " --request-payload JSON Custom JSON request payload for model inference tests."
32+
echo " Use \${MODEL_NAME} as a placeholder for the model name."
33+
echo " Default (Chat): '{\"model\": \"\${MODEL_NAME}\", \"messages\": [{\"role\": \"user\", \"content\": \"Hello\"}], \"max_tokens\": 5}'"
34+
echo " --endpoint ENDPOINT API endpoint to use: 'chat/completions' or 'completions'"
35+
echo " Default: 'chat/completions'"
36+
echo ""
37+
echo "Examples:"
38+
echo " # Basic validation"
39+
echo " $0 # Validate using first available model (default chat format)"
40+
echo " $0 llm-simulator # Validate using llm-simulator model"
41+
echo ""
42+
echo " # For base models like granite (use completions endpoint with 'prompt')"
43+
echo " $0 granite-8b-base --endpoint completions --request-payload '{\"model\": \"\${MODEL_NAME}\", \"messages\": \"Hello, how are you?\", \"max_tokens\": 50}'"
44+
echo ""
45+
echo " # For instruction/chat models (default format works)"
46+
echo " $0 qwen3-instruct"
47+
echo ""
48+
echo "Exit Codes:"
49+
echo " 0 All critical checks passed"
50+
echo " 1 Some checks failed"
51+
echo ""
52+
exit 0
53+
fi
54+
55+
# Parse arguments
56+
while [ $# -gt 0 ]; do
57+
case "$1" in
58+
--request-payload)
59+
CUSTOM_REQUEST_PAYLOAD="$2"
60+
shift 2
61+
;;
62+
--endpoint)
63+
INFERENCE_ENDPOINT="$2"
64+
shift 2
65+
;;
66+
-*)
67+
echo "Unknown option: $1"
68+
echo "Use --help for usage information"
69+
exit 1
70+
;;
71+
*)
72+
if [ -z "$REQUESTED_MODEL" ]; then
73+
REQUESTED_MODEL="$1"
74+
else
75+
echo "Error: Multiple model names provided"
76+
echo "Use --help for usage information"
77+
exit 1
78+
fi
79+
shift
80+
;;
81+
esac
82+
done
83+
84+
# Set default request payload if not provided (OpenAI Chat Completions format)
85+
if [ -z "$CUSTOM_REQUEST_PAYLOAD" ]; then
86+
DEFAULT_REQUEST_PAYLOAD='{"model": "${MODEL_NAME}", "messages": [{"role": "user", "content": "Hello"}], "max_tokens": 5}'
87+
else
88+
DEFAULT_REQUEST_PAYLOAD="$CUSTOM_REQUEST_PAYLOAD"
89+
fi
90+
91+
if [ -n "$REQUESTED_MODEL" ]; then
92+
echo "Requested model for validation: $REQUESTED_MODEL"
93+
fi
94+
95+
if [ -n "$CUSTOM_REQUEST_PAYLOAD" ]; then
96+
echo "Using custom request payload: $CUSTOM_REQUEST_PAYLOAD"
97+
fi
98+
99+
if [ "$INFERENCE_ENDPOINT" != "chat/completions" ]; then
100+
echo "Using custom endpoint: /v1/$INFERENCE_ENDPOINT"
101+
fi
102+
8103
# Color codes for output
9104
RED='\033[0;31m'
10105
GREEN='\033[0;32m'
@@ -72,6 +167,10 @@ fi
72167

73168
print_header "🚀 MaaS Platform Deployment Validation"
74169

170+
if [ -n "$REQUESTED_MODEL" ]; then
171+
print_info "Validation will use model: $REQUESTED_MODEL"
172+
fi
173+
75174
# ==========================================
76175
# 1. Component Status Checks
77176
# ==========================================
@@ -302,7 +401,6 @@ else
302401
-H "Content-Type: application/json" \
303402
-H "Authorization: Bearer ${TOKEN}" \
304403
"${ENDPOINT}" 2>/dev/null || echo "")
305-
echo "$MODELS_RESPONSE"
306404
HTTP_CODE=$(echo "$MODELS_RESPONSE" | tail -n1)
307405
RESPONSE_BODY=$(echo "$MODELS_RESPONSE" | sed '$d')
308406

@@ -316,14 +414,44 @@ else
316414
elif [ "$HTTP_CODE" = "200" ]; then
317415
MODEL_COUNT=$(echo "$RESPONSE_BODY" | jq -r '.data | length' 2>/dev/null || echo "0")
318416
if [ "$MODEL_COUNT" -gt 0 ]; then
319-
MODEL_NAME=$(echo "$RESPONSE_BODY" | jq -r '.data[0].id' 2>/dev/null || echo "")
320-
MODEL_CHAT=$(echo "$RESPONSE_BODY" | jq -r '.data[0].url' 2>/dev/null || echo "")
321-
if [ -n "$MODEL_CHAT" ]; then
322-
MODEL_CHAT_ENDPOINT="${MODEL_CHAT}/v1/chat/completions"
417+
print_success "Models endpoint accessible, found $MODEL_COUNT model(s)"
418+
419+
# Print list of available models
420+
print_info "Available models:"
421+
echo "$RESPONSE_BODY" | jq -r '.data[] | " • \(.id) - \(.url)"' 2>/dev/null || echo " Could not parse model list"
422+
echo ""
423+
424+
# Check if a specific model was requested
425+
if [ -n "$REQUESTED_MODEL" ]; then
426+
# Look for the requested model in the response
427+
MODEL_INDEX=$(echo "$RESPONSE_BODY" | jq -r ".data | map(.id) | index(\"$REQUESTED_MODEL\")" 2>/dev/null || echo "null")
428+
429+
if [ "$MODEL_INDEX" != "null" ] && [ -n "$MODEL_INDEX" ]; then
430+
MODEL_NAME=$(echo "$RESPONSE_BODY" | jq -r ".data[$MODEL_INDEX].id" 2>/dev/null || echo "")
431+
MODEL_CHAT=$(echo "$RESPONSE_BODY" | jq -r ".data[$MODEL_INDEX].url" 2>/dev/null || echo "")
432+
print_info "Using requested model: $MODEL_NAME for validation"
433+
else
434+
# Requested model not found
435+
print_fail "Requested model '$REQUESTED_MODEL' not found" "See available models above" "Use one of the available models or deploy the requested model"
436+
MODEL_NAME=""
437+
MODEL_CHAT=""
438+
MODEL_CHAT_ENDPOINT=""
439+
fi
323440
else
324-
print_warning "Model chat endpoint not found" "Model chat endpoint not found for $MODEL_NAME" "Check model HTTPRoute configuration: kubectl get httproute -n llm"
441+
# No specific model requested, use the first one (default behavior)
442+
MODEL_NAME=$(echo "$RESPONSE_BODY" | jq -r '.data[0].id' 2>/dev/null || echo "")
443+
MODEL_CHAT=$(echo "$RESPONSE_BODY" | jq -r '.data[0].url' 2>/dev/null || echo "")
444+
print_info "Using first available model: $MODEL_NAME for validation"
445+
fi
446+
447+
# Set the inference endpoint if we have a valid model
448+
if [ -n "$MODEL_CHAT" ] && [ "$MODEL_CHAT" != "null" ]; then
449+
MODEL_CHAT_ENDPOINT="${MODEL_CHAT}/v1/${INFERENCE_ENDPOINT}"
450+
elif [ -n "$MODEL_NAME" ]; then
451+
print_warning "Model endpoint not found" "Model endpoint not found for $MODEL_NAME" "Check model HTTPRoute configuration: kubectl get httproute -n llm"
452+
MODEL_NAME=""
453+
MODEL_CHAT_ENDPOINT=""
325454
fi
326-
print_success "Models endpoint accessible, found $MODEL_COUNT model(s) using $MODEL_NAME for validation"
327455
else
328456
print_warning "Models endpoint accessible but no models found" "You may need to deploy a model a simulated model can be deployed with the following command:" "kustomize build docs/samples/models/simulator | kubectl apply --server-side=true --force-conflicts -f -"
329457
MODEL_NAME=""
@@ -355,12 +483,16 @@ else
355483
# Test model inference endpoint (if model exists)
356484
if [ -n "$TOKEN" ] && [ -n "$MODEL_NAME" ] && [ -n "$MODEL_CHAT_ENDPOINT" ]; then
357485
print_check "Model inference endpoint"
358-
print_info "Testing: curl -sSk -X POST ${MODEL_CHAT_ENDPOINT} -H 'Authorization: Bearer \$TOKEN' -H 'Content-Type: application/json' -d '{\"model\": \"${MODEL_NAME}\", \"prompt\": \"Hello\", \"max_tokens\": 5}'"
486+
487+
# Substitute MODEL_NAME placeholder in the request payload
488+
REQUEST_PAYLOAD="${DEFAULT_REQUEST_PAYLOAD//\$\{MODEL_NAME\}/$MODEL_NAME}"
489+
490+
print_info "Testing: curl -sSk -X POST ${MODEL_CHAT_ENDPOINT} -H 'Authorization: Bearer \$TOKEN' -H 'Content-Type: application/json' -d '${REQUEST_PAYLOAD}'"
359491

360492
INFERENCE_RESPONSE=$(curl -sSk --connect-timeout 10 --max-time 30 -w "\n%{http_code}" \
361493
-H "Authorization: Bearer ${TOKEN}" \
362494
-H "Content-Type: application/json" \
363-
-d "{\"model\": \"${MODEL_NAME}\", \"prompt\": \"Hello\", \"max_tokens\": 5}" \
495+
-d "${REQUEST_PAYLOAD}" \
364496
"${MODEL_CHAT_ENDPOINT}" 2>/dev/null || echo "")
365497

366498
HTTP_CODE=$(echo "$INFERENCE_RESPONSE" | tail -n1)
@@ -373,6 +505,7 @@ else
373505
"Check Gateway and model HTTPRoute: kubectl get httproute -n llm"
374506
elif [ "$HTTP_CODE" = "200" ]; then
375507
print_success "Model inference endpoint working"
508+
print_info "Response: $(echo $RESPONSE_BODY | head -c 200)"
376509
elif [ "$HTTP_CODE" = "404" ]; then
377510
print_fail "Model inference endpoint not found (HTTP 404)" \
378511
"Path is incorrect - traffic reaching but wrong path" \
@@ -381,8 +514,12 @@ else
381514
print_fail "Gateway/Service error (HTTP $HTTP_CODE)" \
382515
"Gateway cannot reach model service" \
383516
"Check: 1) Model pods running: kubectl get pods -n llm, 2) Model service exists, 3) HTTPRoute configured: kubectl get httproute -n llm"
517+
elif [ "$HTTP_CODE" = "401" ]; then
518+
print_fail "Authorization failed (HTTP 401)" "Response: $(echo $RESPONSE_BODY | head -c 200)" "Check AuthPolicy and TokenRateLimitPolicy"
519+
elif [ "$HTTP_CODE" = "429" ]; then
520+
print_warning "Rate limiting (HTTP 429)" "Response: $(echo $RESPONSE_BODY | head -c 200)" "wait a minute and try again"
384521
else
385-
print_fail "Model inference failed (HTTP $HTTP_CODE)" "Response: $(echo $RESPONSE_BODY | head -c 200)" "Check model pod logs and HTTPRoute configuration"
522+
print_fail "Model inference failed (HTTP $HTTP_CODE)" "Response: $(echo $RESPONSE_BODY | head -c 200)" "Check model pod logs and HTTPRoute configuration, this model may also have a different response format"
386523
fi
387524
fi
388525

@@ -391,14 +528,17 @@ else
391528
print_check "Rate limiting"
392529
print_info "Sending 10 rapid requests to test rate limiting..."
393530

531+
# Use the same request payload for rate limiting tests
532+
REQUEST_PAYLOAD="${DEFAULT_REQUEST_PAYLOAD//\$\{MODEL_NAME\}/$MODEL_NAME}"
533+
394534
SUCCESS_COUNT=0
395535
RATE_LIMITED_COUNT=0
396536

397537
for i in {1..10}; do
398538
HTTP_CODE=$(curl -sSk --connect-timeout 5 --max-time 15 -o /dev/null -w "%{http_code}" \
399539
-H "Authorization: Bearer ${TOKEN}" \
400540
-H "Content-Type: application/json" \
401-
-d "{\"model\": \"${MODEL_NAME}\", \"prompt\": \"Test\", \"max_tokens\": 1}" \
541+
-d "${REQUEST_PAYLOAD}" \
402542
"${MODEL_CHAT_ENDPOINT}" 2>/dev/null || echo "000")
403543

404544
if [ "$HTTP_CODE" = "200" ]; then
@@ -420,9 +560,12 @@ else
420560
# Test unauthorized access
421561
print_check "Authorization enforcement (401 without token)"
422562
if [ -n "$MODEL_NAME" ] && [ -n "$MODEL_CHAT_ENDPOINT" ]; then
563+
# Use the same request payload for unauthorized test
564+
REQUEST_PAYLOAD="${DEFAULT_REQUEST_PAYLOAD//\$\{MODEL_NAME\}/$MODEL_NAME}"
565+
423566
UNAUTH_CODE=$(curl -sSk --connect-timeout 5 --max-time 15 -o /dev/null -w "%{http_code}" \
424567
-H "Content-Type: application/json" \
425-
-d "{\"model\": \"${MODEL_NAME}\", \"prompt\": \"Test\", \"max_tokens\": 1}" \
568+
-d "${REQUEST_PAYLOAD}" \
426569
"${MODEL_CHAT_ENDPOINT}" 2>/dev/null || echo "000")
427570

428571
if [ "$UNAUTH_CODE" = "401" ]; then
@@ -453,6 +596,7 @@ if [ "$FAILED" -eq 0 ]; then
453596
echo " 1. Deploy a model: kustomize build docs/samples/models/simulator | kubectl apply -f -"
454597
echo " 2. Access the API at: ${HOST:-https://maas.\${CLUSTER_DOMAIN}}"
455598
echo " 3. Check documentation: docs/README.md"
599+
echo " 4. Re-run validation with specific model: ./deployment/scripts/validate-deployment.sh MODEL_NAME"
456600
exit 0
457601
else
458602
print_fail "Some checks failed. Please review the errors above."
@@ -462,6 +606,9 @@ else
462606
echo " - Check operator logs: kubectl logs -n kuadrant-system -l app.kubernetes.io/name=kuadrant-operator"
463607
echo " - Re-run deployment: ./deployment/scripts/deploy-openshift.sh"
464608
echo ""
609+
echo "Usage: ./deployment/scripts/validate-deployment.sh [MODEL_NAME]"
610+
echo " MODEL_NAME: Optional. Specify a model to validate against"
611+
echo ""
465612
exit 1
466613
fi
467614

0 commit comments

Comments
 (0)