Skip to content

Commit dec31ef

Browse files
committed
Add calendar test script with URL-encoded timezone offsets
1 parent aaf1390 commit dec31ef

1 file changed

Lines changed: 364 additions & 0 deletions

File tree

test_calendar.sh

Lines changed: 364 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,364 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Test script for Resource Availability Calendar feature
4+
#
5+
# Usage:
6+
# ./test_calendar.sh --reports-url https://beta-7.fabric-testbed.net:8443/reports \
7+
# --orchestrator-url https://beta-7.fabric-testbed.net \
8+
# --token <reports_bearer_token> \
9+
# [--fabric-token <fabric_id_token>]
10+
#
11+
# The --token is the static bearer token from reports config (bearer_tokens list).
12+
# The --fabric-token is optional; needed only to test the orchestrator proxy endpoint.
13+
14+
set -euo pipefail
15+
16+
RED='\033[0;31m'
17+
GREEN='\033[0;32m'
18+
YELLOW='\033[1;33m'
19+
NC='\033[0m'
20+
21+
REPORTS_URL="https://alpha-5.fabric-testbed.net/reports"
22+
ORCH_URL="https://beta-7.fabric-testbed.net/"
23+
TOKEN="eyJhbGciOiJSUzI1NiIsImtpZCI6InJ0M1FQeGVwRTk4QjVKdUEyMFIyMFdiblVLRlFDbTkzNW1MZTJMU2syVjAiLCJ0eXAiOiJKV1QifQ.eyJzdWIiOiJodHRwOi8vY2lsb2dvbi5vcmcvc2VydmVyQS91c2Vycy8xMTkwNDEwMSIsImlzcyI6Imh0dHBzOi8vY2lsb2dvbi5vcmciLCJnaXZlbl9uYW1lIjoiS29tYWwiLCJhdWQiOiJjaWxvZ29uOi9jbGllbnRfaWQvNGQ3ZWE1ODNkZDA2MTljMjkwZWRhN2FiNjZmMmNlZmEiLCJhY3IiOiJodHRwczovL3JlZmVkcy5vcmcvcHJvZmlsZS9tZmEiLCJhenAiOiJjaWxvZ29uOi9jbGllbnRfaWQvNGQ3ZWE1ODNkZDA2MTljMjkwZWRhN2FiNjZmMmNlZmEiLCJhdXRoX3RpbWUiOjE3NzQyNzYxNDMsIm5hbWUiOiJLb21hbCBUaGFyZWphIiwiZXhwIjoxNzc0Mjk3NTA1LCJpYXQiOjE3NzQyODMxMDUsImZhbWlseV9uYW1lIjoiVGhhcmVqYSIsImp0aSI6Imh0dHBzOi8vY2lsb2dvbi5vcmcvb2F1dGgyL2lkVG9rZW4vNWYwZGNlMzU1YTNkYjY3NmZiYzcwZjU1NjY0MDNlZi8xNzc0MjgzMDk5MTQxIiwiZW1haWwiOiJrdGhhcmUxMEBlbWFpbC51bmMuZWR1IiwicHJvamVjdHMiOlt7Im5hbWUiOiJGQUJSSUMgU3RhZmYiLCJ1dWlkIjoiYjk4NDdmYTEtMTNlZi00OWY5LTllMDctYWU2YWQwNmNkYTNmIiwidGFncyI6WyJOZXQuRmFjaWxpdHlQb3J0LlJFTkMtQ2hhbWVsZW9uIiwiQ29tcG9uZW50LlN0b3JhZ2UiLCJOZXQuQWxsRmFjaWxpdHlQb3J0cyIsIk5ldC5GQUJOZXR2NEV4dCIsIk5ldC5GQUJOZXR2NkV4dCIsIk5ldC5GYWNpbGl0eVBvcnQuUkVOQy1HU1UiLCJOZXQuTm9MaW1pdEJXIiwiU2xpY2UuTWVhc3VyZW1lbnRzIiwiU2xpY2UuTXVsdGlzaXRlIiwiU2xpY2UuTm9MaW1pdExpZmV0aW1lIiwiVk0uTm9MaW1pdCIsIlZNLk5vTGltaXRDUFUiLCJWTS5Ob0xpbWl0RGlzayIsIlZNLk5vTGltaXRSQU0iLCJOZXQuUG9ydE1pcnJvcmluZyIsIlN3aXRjaC5QNCIsIkNvbXBvbmVudC5GUEdBX1hpbGlueF9TTjEwMjIiLCJDb21wb25lbnQuRlBHQV9YaWxpbnhfVTI4MCIsIkNvbXBvbmVudC5HUFVfQTMwIiwiQ29tcG9uZW50LkdQVV9BNDAiLCJDb21wb25lbnQuR1BVX1JUWDYwMDAiLCJDb21wb25lbnQuR1BVX1Rlc2xhX1Q0IiwiQ29tcG9uZW50Lk5WTUVfUDQ1MTAiLCJDb21wb25lbnQuU21hcnROSUNfQmx1ZUZpZWxkXzNfQ29ubmVjdFhfNiIsIkNvbXBvbmVudC5TbWFydE5JQ19Db25uZWN0WF81IiwiQ29tcG9uZW50LlNtYXJ0TklDX0Nvbm5lY3RYXzYiXSwibWVtYmVyc2hpcHMiOnsiaXNfY3JlYXRvciI6ZmFsc2UsImlzX2xlYWQiOnRydWUsImlzX21lbWJlciI6dHJ1ZSwiaXNfb3duZXIiOnRydWUsImlzX3Rva2VuX2hvbGRlciI6dHJ1ZX19XSwicm9sZXMiOlt7Im5hbWUiOiJmYWJyaWMtYWN0aXZlLXVzZXJzIn0seyJuYW1lIjoiZmFjaWxpdHktb3BlcmF0b3JzIn0seyJuYW1lIjoiSnVweXRlcmh1YiJ9LHsibmFtZSI6InByb2plY3QtbGVhZHMifV0sInNjb3BlIjoiYWxsIiwidXVpZCI6ImRkYjVmMzc0LTdlODItNDVhZi04MmQwLTMzMGQwYjk2MWVhYSJ9.X7HkD8NpUesYfsOeoLPDDehCdRcXwsuYJpyQ1RBlV3XpERw5rfUEDgGThu1cLKhK2JrMlSelrSsDBNmyoYl7hAPx6PPe4NVNB5876KE4eBuR7QB53mwDWrO70h_Fje-dESOBQON3PzWNhCv40sKi0CsCcTVVpcOumFkMhHIyGWkyyryFsO0s_yf8pWtueA_RQJtssUC08CW421M1uDKoIAAA4Dx8DHnnVqhCO3tj_p5blOviLKOReLuShjXH7V4vFEF2HsuAzmCJC80KhWKElMab-TrMywZ2v6c6T9IWQLFbnOEhSo1O6lIVLxDWAejWNK4v9vTyC-rxjfhzVwar7b_7hKg6I8ECNlq5IzgCjsKtI0OK9eKUnvyd0grVS07uSQKOj_Y64k3V4l7nYupxAIZSd86RwNtwRaQqcll2FQwnAFqNMi3FCEECu1mttnJ35EoyydioeGOpna0q_I6cGhPOnt-X58HIn7B2I6M9_yAT6_ubgwEqPo94yZZ7eWnxtp5SpKkLCUXpBFpPDgfFiQo4AF1uyXZxyunePwQ2QKcpFBcNJ7elMNNnfoO-8pwRGtACv_qtSXQb264_FRBYX553UBFKpn_6S0JUfTd8Z14ZWxHo6RK4-RJ1OJ9625GaNUmln1nMXnmM7BKtvL2E5DCRtQrPB4mfqMVvZaALLoM"
24+
FABRIC_TOKEN="eyJhbGciOiJSUzI1NiIsImtpZCI6InJ0M1FQeGVwRTk4QjVKdUEyMFIyMFdiblVLRlFDbTkzNW1MZTJMU2syVjAiLCJ0eXAiOiJKV1QifQ.eyJzdWIiOiJodHRwOi8vY2lsb2dvbi5vcmcvc2VydmVyQS91c2Vycy8xMTkwNDEwMSIsImlzcyI6Imh0dHBzOi8vY2lsb2dvbi5vcmciLCJnaXZlbl9uYW1lIjoiS29tYWwiLCJhdWQiOiJjaWxvZ29uOi9jbGllbnRfaWQvNGQ3ZWE1ODNkZDA2MTljMjkwZWRhN2FiNjZmMmNlZmEiLCJhY3IiOiJodHRwczovL3JlZmVkcy5vcmcvcHJvZmlsZS9tZmEiLCJhenAiOiJjaWxvZ29uOi9jbGllbnRfaWQvNGQ3ZWE1ODNkZDA2MTljMjkwZWRhN2FiNjZmMmNlZmEiLCJhdXRoX3RpbWUiOjE3NzQyNzYxNDMsIm5hbWUiOiJLb21hbCBUaGFyZWphIiwiZXhwIjoxNzc0Mjk3NTA1LCJpYXQiOjE3NzQyODMxMDUsImZhbWlseV9uYW1lIjoiVGhhcmVqYSIsImp0aSI6Imh0dHBzOi8vY2lsb2dvbi5vcmcvb2F1dGgyL2lkVG9rZW4vNWYwZGNlMzU1YTNkYjY3NmZiYzcwZjU1NjY0MDNlZi8xNzc0MjgzMDk5MTQxIiwiZW1haWwiOiJrdGhhcmUxMEBlbWFpbC51bmMuZWR1IiwicHJvamVjdHMiOlt7Im5hbWUiOiJGQUJSSUMgU3RhZmYiLCJ1dWlkIjoiYjk4NDdmYTEtMTNlZi00OWY5LTllMDctYWU2YWQwNmNkYTNmIiwidGFncyI6WyJOZXQuRmFjaWxpdHlQb3J0LlJFTkMtQ2hhbWVsZW9uIiwiQ29tcG9uZW50LlN0b3JhZ2UiLCJOZXQuQWxsRmFjaWxpdHlQb3J0cyIsIk5ldC5GQUJOZXR2NEV4dCIsIk5ldC5GQUJOZXR2NkV4dCIsIk5ldC5GYWNpbGl0eVBvcnQuUkVOQy1HU1UiLCJOZXQuTm9MaW1pdEJXIiwiU2xpY2UuTWVhc3VyZW1lbnRzIiwiU2xpY2UuTXVsdGlzaXRlIiwiU2xpY2UuTm9MaW1pdExpZmV0aW1lIiwiVk0uTm9MaW1pdCIsIlZNLk5vTGltaXRDUFUiLCJWTS5Ob0xpbWl0RGlzayIsIlZNLk5vTGltaXRSQU0iLCJOZXQuUG9ydE1pcnJvcmluZyIsIlN3aXRjaC5QNCIsIkNvbXBvbmVudC5GUEdBX1hpbGlueF9TTjEwMjIiLCJDb21wb25lbnQuRlBHQV9YaWxpbnhfVTI4MCIsIkNvbXBvbmVudC5HUFVfQTMwIiwiQ29tcG9uZW50LkdQVV9BNDAiLCJDb21wb25lbnQuR1BVX1JUWDYwMDAiLCJDb21wb25lbnQuR1BVX1Rlc2xhX1Q0IiwiQ29tcG9uZW50Lk5WTUVfUDQ1MTAiLCJDb21wb25lbnQuU21hcnROSUNfQmx1ZUZpZWxkXzNfQ29ubmVjdFhfNiIsIkNvbXBvbmVudC5TbWFydE5JQ19Db25uZWN0WF81IiwiQ29tcG9uZW50LlNtYXJ0TklDX0Nvbm5lY3RYXzYiXSwibWVtYmVyc2hpcHMiOnsiaXNfY3JlYXRvciI6ZmFsc2UsImlzX2xlYWQiOnRydWUsImlzX21lbWJlciI6dHJ1ZSwiaXNfb3duZXIiOnRydWUsImlzX3Rva2VuX2hvbGRlciI6dHJ1ZX19XSwicm9sZXMiOlt7Im5hbWUiOiJmYWJyaWMtYWN0aXZlLXVzZXJzIn0seyJuYW1lIjoiZmFjaWxpdHktb3BlcmF0b3JzIn0seyJuYW1lIjoiSnVweXRlcmh1YiJ9LHsibmFtZSI6InByb2plY3QtbGVhZHMifV0sInNjb3BlIjoiYWxsIiwidXVpZCI6ImRkYjVmMzc0LTdlODItNDVhZi04MmQwLTMzMGQwYjk2MWVhYSJ9.X7HkD8NpUesYfsOeoLPDDehCdRcXwsuYJpyQ1RBlV3XpERw5rfUEDgGThu1cLKhK2JrMlSelrSsDBNmyoYl7hAPx6PPe4NVNB5876KE4eBuR7QB53mwDWrO70h_Fje-dESOBQON3PzWNhCv40sKi0CsCcTVVpcOumFkMhHIyGWkyyryFsO0s_yf8pWtueA_RQJtssUC08CW421M1uDKoIAAA4Dx8DHnnVqhCO3tj_p5blOviLKOReLuShjXH7V4vFEF2HsuAzmCJC80KhWKElMab-TrMywZ2v6c6T9IWQLFbnOEhSo1O6lIVLxDWAejWNK4v9vTyC-rxjfhzVwar7b_7hKg6I8ECNlq5IzgCjsKtI0OK9eKUnvyd0grVS07uSQKOj_Y64k3V4l7nYupxAIZSd86RwNtwRaQqcll2FQwnAFqNMi3FCEECu1mttnJ35EoyydioeGOpna0q_I6cGhPOnt-X58HIn7B2I6M9_yAT6_ubgwEqPo94yZZ7eWnxtp5SpKkLCUXpBFpPDgfFiQo4AF1uyXZxyunePwQ2QKcpFBcNJ7elMNNnfoO-8pwRGtACv_qtSXQb264_FRBYX553UBFKpn_6S0JUfTd8Z14ZWxHo6RK4-RJ1OJ9625GaNUmln1nMXnmM7BKtvL2E5DCRtQrPB4mfqMVvZaALLoM"
25+
26+
usage() {
27+
echo "Usage: $0 --reports-url <url> --orchestrator-url <url> --token <token> [--fabric-token <token>]"
28+
exit 1
29+
}
30+
31+
while [[ $# -gt 0 ]]; do
32+
case $1 in
33+
--reports-url) REPORTS_URL="$2"; shift 2 ;;
34+
--orchestrator-url) ORCH_URL="$2"; shift 2 ;;
35+
--token) TOKEN="$2"; shift 2 ;;
36+
--fabric-token) FABRIC_TOKEN="$2"; shift 2 ;;
37+
-h|--help) usage ;;
38+
*) echo "Unknown option: $1"; usage ;;
39+
esac
40+
done
41+
42+
if [[ -z "$REPORTS_URL" || -z "$ORCH_URL" || -z "$TOKEN" ]]; then
43+
usage
44+
fi
45+
46+
REPORTS_URL="${REPORTS_URL%/}"
47+
ORCH_URL="${ORCH_URL%/}"
48+
PASS=0
49+
FAIL=0
50+
SKIP=0
51+
52+
log_pass() { echo -e "${GREEN}[PASS]${NC} $1"; PASS=$((PASS + 1)); }
53+
log_fail() { echo -e "${RED}[FAIL]${NC} $1"; FAIL=$((FAIL + 1)); }
54+
log_skip() { echo -e "${YELLOW}[SKIP]${NC} $1"; SKIP=$((SKIP + 1)); }
55+
log_info() { echo -e " $1"; }
56+
57+
check_status() {
58+
local desc="$1" status="$2" body="$3" expected="${4:-200}"
59+
if [[ "$status" == "$expected" ]]; then
60+
log_pass "$desc (HTTP $status)"
61+
else
62+
log_fail "$desc (HTTP $status, expected $expected)"
63+
log_info "Response: $(echo "$body" | head -5)"
64+
fi
65+
}
66+
67+
# ─────────────────────────────────────────────────────────
68+
echo ""
69+
echo "=========================================="
70+
echo " Resource Calendar Test Suite"
71+
echo "=========================================="
72+
echo " Reports: $REPORTS_URL"
73+
echo " Orchestrator: $ORCH_URL"
74+
echo "=========================================="
75+
echo ""
76+
77+
# ─────────────────────────────────────────────────────────
78+
echo "--- Step 1: Fetch host data from orchestrator ---"
79+
echo ""
80+
81+
SUMMARY_RESP=$(curl -sk -w "\n%{http_code}" "$ORCH_URL/portalresources/summary?type=hosts")
82+
SUMMARY_STATUS=$(echo "$SUMMARY_RESP" | tail -1)
83+
SUMMARY_BODY=$(echo "$SUMMARY_RESP" | sed '$d')
84+
85+
check_status "GET /portalresources/summary?type=hosts" "$SUMMARY_STATUS" "$SUMMARY_BODY"
86+
87+
# Extract hosts from summary
88+
HOSTS_JSON=$(echo "$SUMMARY_BODY" | python3 -c "
89+
import sys, json
90+
data = json.load(sys.stdin)
91+
hosts = []
92+
for item in data.get('data', []):
93+
if isinstance(item, dict) and 'hosts' in item:
94+
hosts = item['hosts']
95+
break
96+
print(json.dumps(hosts))
97+
" 2>/dev/null || echo "[]")
98+
99+
HOST_COUNT=$(echo "$HOSTS_JSON" | python3 -c "import sys,json; print(len(json.load(sys.stdin)))")
100+
log_info "Found $HOST_COUNT hosts in orchestrator summary"
101+
102+
# Grab first host/site for later queries
103+
FIRST_HOST=$(echo "$HOSTS_JSON" | python3 -c "import sys,json; h=json.load(sys.stdin); print(h[0]['name'] if h else '')" 2>/dev/null)
104+
FIRST_SITE=$(echo "$HOSTS_JSON" | python3 -c "import sys,json; h=json.load(sys.stdin); print(h[0]['site'] if h else '')" 2>/dev/null)
105+
echo ""
106+
107+
# ─────────────────────────────────────────────────────────
108+
echo "--- Step 2: Query calendar - basic (3 days, daily) ---"
109+
echo ""
110+
111+
START="2025-06-01T00:00:00%2B00:00"
112+
END="2025-06-04T00:00:00%2B00:00"
113+
114+
RESP=$(curl -sk -w "\n%{http_code}" \
115+
"$REPORTS_URL/calendar?start_time=$START&end_time=$END&interval=day" \
116+
-H "Authorization: Bearer $TOKEN")
117+
STATUS=$(echo "$RESP" | tail -1)
118+
BODY=$(echo "$RESP" | sed '$d')
119+
120+
check_status "GET /calendar (3 days, daily)" "$STATUS" "$BODY"
121+
122+
# Validate response structure
123+
echo "$BODY" | python3 -c "
124+
import sys, json
125+
data = json.load(sys.stdin)
126+
slots = data.get('data', [])
127+
total = data.get('total', 0)
128+
interval = data.get('interval', '')
129+
errors = []
130+
if total != 3:
131+
errors.append(f'Expected 3 slots, got {total}')
132+
if interval != 'day':
133+
errors.append(f'Expected interval=day, got {interval}')
134+
for slot in slots:
135+
if 'hosts' not in slot or 'sites' not in slot:
136+
errors.append('Slot missing hosts or sites key')
137+
break
138+
for h in slot['hosts']:
139+
for key in ['cores_capacity', 'cores_allocated', 'cores_available', 'components']:
140+
if key not in h:
141+
errors.append(f'Host missing key: {key}')
142+
break
143+
if errors:
144+
print('VALIDATION ERRORS: ' + '; '.join(errors))
145+
sys.exit(1)
146+
else:
147+
print(f'OK: {total} slots, {len(slots[0][\"hosts\"])} hosts, {len(slots[0][\"sites\"])} sites per slot')
148+
" 2>/dev/null && log_pass "Response structure validation" || log_fail "Response structure validation"
149+
echo ""
150+
151+
# ─────────────────────────────────────────────────────────
152+
echo "--- Step 3: Query calendar - weekly interval ---"
153+
echo ""
154+
155+
RESP=$(curl -sk -w "\n%{http_code}" \
156+
"$REPORTS_URL/calendar?start_time=2025-06-01T00:00:00%2B00:00&end_time=2025-06-30T00:00:00%2B00:00&interval=week" \
157+
-H "Authorization: Bearer $TOKEN")
158+
STATUS=$(echo "$RESP" | tail -1)
159+
BODY=$(echo "$RESP" | sed '$d')
160+
161+
check_status "GET /calendar (weekly, June)" "$STATUS" "$BODY"
162+
163+
SLOT_COUNT=$(echo "$BODY" | python3 -c "import sys,json; print(json.load(sys.stdin).get('total',0))" 2>/dev/null)
164+
log_info "Got $SLOT_COUNT weekly slots"
165+
echo ""
166+
167+
# ─────────────────────────────────────────────────────────
168+
echo "--- Step 4: Query calendar - site filter ---"
169+
echo ""
170+
171+
if [[ -n "$FIRST_SITE" ]]; then
172+
RESP=$(curl -sk -w "\n%{http_code}" \
173+
"$REPORTS_URL/calendar?start_time=$START&end_time=$END&interval=day&site=$FIRST_SITE" \
174+
-H "Authorization: Bearer $TOKEN")
175+
STATUS=$(echo "$RESP" | tail -1)
176+
BODY=$(echo "$RESP" | sed '$d')
177+
178+
check_status "GET /calendar (site=$FIRST_SITE)" "$STATUS" "$BODY"
179+
180+
echo "$BODY" | python3 -c "
181+
import sys, json
182+
data = json.load(sys.stdin)
183+
slots = data.get('data', [])
184+
if slots:
185+
sites = set()
186+
for s in slots:
187+
for h in s['hosts']:
188+
sites.add(h['site'])
189+
print(f'Sites in response: {sites}')
190+
if len(sites) == 1 and '$FIRST_SITE' in sites:
191+
print('OK: Only $FIRST_SITE hosts returned')
192+
else:
193+
print(f'WARNING: Expected only $FIRST_SITE, got {sites}')
194+
" 2>/dev/null
195+
else
196+
log_skip "Site filter test (no hosts found)"
197+
fi
198+
echo ""
199+
200+
# ─────────────────────────────────────────────────────────
201+
echo "--- Step 5: Query calendar - exclude_site filter ---"
202+
echo ""
203+
204+
if [[ -n "$FIRST_SITE" ]]; then
205+
RESP=$(curl -sk -w "\n%{http_code}" \
206+
"$REPORTS_URL/calendar?start_time=$START&end_time=$END&interval=day&exclude_site=$FIRST_SITE" \
207+
-H "Authorization: Bearer $TOKEN")
208+
STATUS=$(echo "$RESP" | tail -1)
209+
BODY=$(echo "$RESP" | sed '$d')
210+
211+
check_status "GET /calendar (exclude_site=$FIRST_SITE)" "$STATUS" "$BODY"
212+
213+
echo "$BODY" | python3 -c "
214+
import sys, json
215+
data = json.load(sys.stdin)
216+
slots = data.get('data', [])
217+
if slots:
218+
sites = set()
219+
for s in slots:
220+
for h in s['hosts']:
221+
sites.add(h['site'])
222+
if '$FIRST_SITE' not in sites:
223+
print(f'OK: $FIRST_SITE excluded, got sites: {sites}')
224+
else:
225+
print(f'WARNING: $FIRST_SITE still present in response')
226+
" 2>/dev/null
227+
else
228+
log_skip "Exclude site filter test (no hosts found)"
229+
fi
230+
echo ""
231+
232+
# ─────────────────────────────────────────────────────────
233+
echo "--- Step 6: Query calendar - host filter ---"
234+
echo ""
235+
236+
if [[ -n "$FIRST_HOST" ]]; then
237+
RESP=$(curl -sk -w "\n%{http_code}" \
238+
"$REPORTS_URL/calendar?start_time=$START&end_time=$END&interval=day&host=$FIRST_HOST" \
239+
-H "Authorization: Bearer $TOKEN")
240+
STATUS=$(echo "$RESP" | tail -1)
241+
BODY=$(echo "$RESP" | sed '$d')
242+
243+
check_status "GET /calendar (host=$FIRST_HOST)" "$STATUS" "$BODY"
244+
245+
HOST_IN_RESP=$(echo "$BODY" | python3 -c "
246+
import sys, json
247+
data = json.load(sys.stdin)
248+
slots = data.get('data', [])
249+
if slots:
250+
names = [h['name'] for h in slots[0]['hosts']]
251+
print(f'{len(names)} host(s): {names}')
252+
" 2>/dev/null)
253+
log_info "$HOST_IN_RESP"
254+
else
255+
log_skip "Host filter test (no hosts found)"
256+
fi
257+
echo ""
258+
259+
# ─────────────────────────────────────────────────────────
260+
echo "--- Step 7: Query calendar - with active slivers (current time range) ---"
261+
echo ""
262+
263+
NOW=$(date -u +%Y-%m-%dT%H:%M:%S%2B00:00)
264+
NEXT_WEEK=$(python3 -c "from datetime import datetime,timedelta,timezone; print((datetime.now(timezone.utc)+timedelta(days=7)).strftime('%Y-%m-%dT%H:%M:%S%2B00:00'))")
265+
266+
RESP=$(curl -sk -w "\n%{http_code}" \
267+
"$REPORTS_URL/calendar?start_time=$NOW&end_time=$NEXT_WEEK&interval=day" \
268+
-H "Authorization: Bearer $TOKEN")
269+
STATUS=$(echo "$RESP" | tail -1)
270+
BODY=$(echo "$RESP" | sed '$d')
271+
272+
check_status "GET /calendar (current week)" "$STATUS" "$BODY"
273+
274+
echo "$BODY" | python3 -c "
275+
import sys, json
276+
data = json.load(sys.stdin)
277+
slots = data.get('data', [])
278+
if not slots:
279+
print(' No slots returned')
280+
else:
281+
total_alloc = 0
282+
for slot in slots:
283+
for h in slot.get('hosts', []):
284+
total_alloc += h.get('cores_allocated', 0)
285+
if total_alloc > 0:
286+
print(f' Allocations detected: {total_alloc} total cores allocated across all slots')
287+
# Show first slot details
288+
s = slots[0]
289+
for h in s['hosts']:
290+
if h['cores_allocated'] > 0:
291+
print(f' {h[\"name\"]} ({h[\"site\"]}): {h[\"cores_allocated\"]}/{h[\"cores_capacity\"]} cores, {h[\"ram_allocated\"]}/{h[\"ram_capacity\"]} RAM')
292+
else:
293+
print(' No active allocations found (expected if no slivers overlap this time range)')
294+
" 2>/dev/null
295+
echo ""
296+
297+
# ─────────────────────────────────────────────────────────
298+
echo "--- Step 8: Validation - bad requests ---"
299+
echo ""
300+
301+
# Missing end_time
302+
RESP=$(curl -sk -w "\n%{http_code}" \
303+
"$REPORTS_URL/calendar?start_time=$START" \
304+
-H "Authorization: Bearer $TOKEN")
305+
STATUS=$(echo "$RESP" | tail -1)
306+
check_status "GET /calendar missing end_time -> 400" "$STATUS" "" "400"
307+
308+
# start > end
309+
RESP=$(curl -sk -w "\n%{http_code}" \
310+
"$REPORTS_URL/calendar?start_time=2025-06-04T00:00:00%2B00:00&end_time=2025-06-01T00:00:00%2B00:00" \
311+
-H "Authorization: Bearer $TOKEN")
312+
STATUS=$(echo "$RESP" | tail -1)
313+
check_status "GET /calendar start > end -> 400" "$STATUS" "" "400"
314+
315+
# Invalid interval
316+
RESP=$(curl -sk -w "\n%{http_code}" \
317+
"$REPORTS_URL/calendar?start_time=$START&end_time=$END&interval=month" \
318+
-H "Authorization: Bearer $TOKEN")
319+
STATUS=$(echo "$RESP" | tail -1)
320+
check_status "GET /calendar invalid interval -> 400" "$STATUS" "" "400"
321+
322+
# No auth
323+
RESP=$(curl -sk -w "\n%{http_code}" \
324+
"$REPORTS_URL/calendar?start_time=$START&end_time=$END")
325+
STATUS=$(echo "$RESP" | tail -1)
326+
check_status "GET /calendar no auth -> 401" "$STATUS" "" "401"
327+
echo ""
328+
329+
# ─────────────────────────────────────────────────────────
330+
echo "--- Step 9: Orchestrator proxy ---"
331+
echo ""
332+
333+
if [[ -n "$FABRIC_TOKEN" ]]; then
334+
RESP=$(curl -sk -w "\n%{http_code}" \
335+
"$ORCH_URL/resources/calendar?start_date=$START&end_date=$END&interval=day" \
336+
-H "Authorization: Bearer $FABRIC_TOKEN")
337+
STATUS=$(echo "$RESP" | tail -1)
338+
BODY=$(echo "$RESP" | sed '$d')
339+
340+
check_status "GET /resources/calendar via orchestrator" "$STATUS" "$BODY"
341+
342+
SLOT_COUNT=$(echo "$BODY" | python3 -c "
343+
import sys, json
344+
data = json.load(sys.stdin)
345+
# Orchestrator wraps in Resources: {data: [{...calendar...}]}
346+
for item in data.get('data', []):
347+
if isinstance(item, dict) and 'total' in item:
348+
print(item['total'])
349+
break
350+
" 2>/dev/null || echo "?")
351+
log_info "Calendar returned $SLOT_COUNT slots via orchestrator proxy"
352+
else
353+
log_skip "Orchestrator proxy test (no --fabric-token provided)"
354+
fi
355+
echo ""
356+
357+
# ─────────────────────────────────────────────────────────
358+
echo "=========================================="
359+
echo -e " Results: ${GREEN}${PASS} passed${NC}, ${RED}${FAIL} failed${NC}, ${YELLOW}${SKIP} skipped${NC}"
360+
echo "=========================================="
361+
362+
if [[ $FAIL -gt 0 ]]; then
363+
exit 1
364+
fi

0 commit comments

Comments
 (0)