Skip to content

Commit efc7aca

Browse files
committed
github-action: add ci workflow
Runs some test using latest apache/cloudstack release as simulator MS. Signed-off-by: Abhishek Kumar <[email protected]>
1 parent a55409a commit efc7aca

File tree

1 file changed

+273
-0
lines changed

1 file changed

+273
-0
lines changed

.github/workflows/ci.yml

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
name: Simulator CI
19+
20+
on:
21+
pull_request:
22+
23+
concurrency:
24+
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
25+
cancel-in-progress: true
26+
27+
permissions:
28+
contents: read
29+
30+
jobs:
31+
sim:
32+
runs-on: ubuntu-24.04
33+
timeout-minutes: 60
34+
35+
env:
36+
GO111MODULE: on
37+
CMK_BIN: bin/cmk
38+
CLOUDSTACK_SIM_API: http://127.0.0.1:8096/client/api
39+
CLOUDSTACK_UI_API: http://127.0.0.1:8080/client/api
40+
MAVEN_OPTS: -Xmx4096m -XX:MaxMetaspaceSize=800m -Djava.security.egd=file:/dev/urandom --add-opens=java.base/java.lang=ALL-UNNAMED --add-exports=java.base/sun.security.x509=ALL-UNNAMED --add-opens=java.base/jdk.internal.reflect=ALL-UNNAMED
41+
42+
steps:
43+
- name: Check out CloudMonkey
44+
uses: actions/checkout@v4
45+
46+
- name: Set up Go
47+
uses: actions/setup-go@v5
48+
with:
49+
go-version: '1.22'
50+
51+
- name: Build cmk
52+
run: |
53+
make run
54+
55+
- name: Set up JDK 11 + Maven cache
56+
uses: actions/setup-java@v4
57+
with:
58+
java-version: '11'
59+
distribution: 'temurin'
60+
cache: maven
61+
62+
- name: Set up Python 3.10
63+
uses: actions/setup-python@v5
64+
with:
65+
python-version: '3.10'
66+
67+
- name: Install OS deps
68+
run: |
69+
sudo apt-get update
70+
sudo apt-get install -y \
71+
mysql-server uuid-runtime genisoimage netcat-openbsd ipmitool \
72+
build-essential libgcrypt20 libgpg-error-dev libgpg-error0 \
73+
libopenipmi0 libssl-dev jq curl
74+
75+
- name: Install Python deps
76+
run: |
77+
python3 -m pip install --upgrade pip
78+
python3 -m pip install --user urllib3 lxml paramiko nose texttable ipmisim pyopenssl pycryptodome mock flask netaddr pylint pycodestyle six astroid mysql-connector-python
79+
80+
- name: Setup MySQL
81+
run: |
82+
sudo systemctl start mysql
83+
sudo mysql -uroot -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY ''; FLUSH PRIVILEGES;"
84+
sudo systemctl restart mysql
85+
sudo mysql -uroot -e "SELECT VERSION();"
86+
87+
- name: Fetch latest CloudStack release tag
88+
id: csrel
89+
run: |
90+
TAG=$(curl -s https://api.github.com/repos/apache/cloudstack/releases/latest | jq -r .tag_name)
91+
echo "tag=$TAG" >> $GITHUB_OUTPUT
92+
echo "Latest CloudStack tag: $TAG"
93+
94+
- name: Clone CloudStack at latest release
95+
run: |
96+
git clone --depth=1 --branch "${{ steps.csrel.outputs.tag }}" https://github.com/apache/cloudstack.git
97+
98+
- name: Build CloudStack (simulator)
99+
working-directory: cloudstack
100+
run: |
101+
mvn -B -P developer,systemvm -Dsimulator -DskipTests -T"$(nproc)" clean install
102+
103+
- name: Deploy simulator DB + marvin
104+
working-directory: cloudstack
105+
run: |
106+
mvn -q -Pdeveloper -pl developer -Ddeploydb
107+
mvn -q -Pdeveloper -pl developer -Ddeploydb-simulator
108+
python3 -m pip install --user --upgrade tools/marvin/dist/Marvin-*.tar.gz
109+
110+
- name: Start CloudStack mgmt (Jetty) in background
111+
working-directory: cloudstack
112+
run: |
113+
set -euo pipefail
114+
LOG=/tmp/jetty-log.txt
115+
mvn -Dsimulator -Dorg.eclipse.jetty.annotations.maxWait=120 -pl :cloud-client-ui jetty:run > "$LOG" 2>&1 &
116+
JETTY_PID=$!
117+
echo "$JETTY_PID" > /tmp/jetty.pid
118+
echo "Waiting for simulator API @ 8096…"
119+
for i in $(seq 1 60); do
120+
if nc -z 127.0.0.1 8096; then
121+
echo "Simulator API is up."
122+
break
123+
fi
124+
sleep 5
125+
tail -n 50 "$LOG" || true
126+
if ! kill -0 "$JETTY_PID" 2>/dev/null; then
127+
echo "Jetty exited early. Last 200 lines:"
128+
tail -n 200 "$LOG" || true
129+
exit 1
130+
fi
131+
done
132+
133+
- name: Deploy Advanced Zone via Marvin (best-effort)
134+
working-directory: cloudstack
135+
continue-on-error: true
136+
run: |
137+
python3 tools/marvin/marvin/deployDataCenter.py -i setup/dev/advdualzone.cfg || true
138+
139+
- name: Configure cmk profile -> simulator (no auth)
140+
run: |
141+
"${CMK_BIN}" set profile simulator
142+
"${CMK_BIN}" set url "${CLOUDSTACK_UI_API}"
143+
"${CMK_BIN}" set output json
144+
145+
- name: API discovery parity (curl vs cmk)
146+
run: |
147+
CURL_COUNT=$(curl -s "${CLOUDSTACK_SIM_API}?command=listApis&response=json" | jq '.listapisresponse.count')
148+
echo "curl count: $CURL_COUNT"
149+
CMK_COUNT=$("${CMK_BIN}" listApis | jq '.count')
150+
echo "cmk count: $CMK_COUNT"
151+
test -n "$CURL_COUNT" -a -n "$CMK_COUNT"
152+
[ "$CMK_COUNT" -ge 1 ]
153+
154+
- name: List zones (table) + export first id
155+
run: |
156+
"${CMK_BIN}" set output table
157+
"${CMK_BIN}" listZones || true
158+
"${CMK_BIN}" set output json
159+
ZONE_ID=$("${CMK_BIN}" listZones | jq -r '.zone[0].id')
160+
echo "ZONE_ID=$ZONE_ID" >> $GITHUB_ENV
161+
test -n "$ZONE_ID"
162+
163+
- name: listZones with filter (only id,name)
164+
run: |
165+
"${CMK_BIN}" set output json
166+
OUT=$("${CMK_BIN}" listZones filter=id,name)
167+
echo "$OUT" | jq -e '
168+
.zone and (.zone|length>=1)
169+
and (all(.zone[]; has("id") and has("name") and ((. | keys - ["id","name"])|length==0)))
170+
'
171+
172+
- name: listZones with exclude (no id,name)
173+
run: |
174+
"${CMK_BIN}" set output json
175+
OUT=$("${CMK_BIN}" listZones exclude=id,name)
176+
echo "$OUT" | jq -e '
177+
.zone and (.zone|length>=1)
178+
and (all(.zone[]; (has("id") or has("name"))|not))
179+
'
180+
181+
- name: createProject (base)
182+
run: |
183+
"${CMK_BIN}" set output json
184+
"${CMK_BIN}" createProject name=test || true
185+
186+
- name: createProject with filter (only id,name)
187+
run: |
188+
"${CMK_BIN}" set output json
189+
OUT=$("${CMK_BIN}" createProject name=test-filter filter=id,name || true)
190+
echo "$OUT"
191+
if [ -n "$OUT" ]; then
192+
echo "$OUT" | jq -e '
193+
(.project // {}) as $p
194+
| ($p|type=="object")
195+
and ($p|has("id") and has("name"))
196+
and ((($p|keys) - ["id","name"])|length==0)
197+
'
198+
else
199+
echo "No output. Skipping strict check."
200+
fi
201+
202+
- name: createProject with exclude (no id,name)
203+
run: |
204+
"${CMK_BIN}" set output json
205+
OUT=$("${CMK_BIN}" createProject name=test-exclude exclude=id,name || true)
206+
echo "$OUT"
207+
if [ -n "$OUT" ]; then
208+
echo "$OUT" | jq -e '
209+
(.project // {}) as $p
210+
| ($p|type=="object")
211+
and ((($p|has("id")) or ($p|has("name")))|not)
212+
'
213+
else
214+
echo "No output. Skipping strict check."
215+
fi
216+
217+
- name: Get template and service offering IDs
218+
run: |
219+
TID=$("${CMK_BIN}" listTemplates listall=true templatefilter=executable | jq -r '.template[0].id')
220+
SOID=$("${CMK_BIN}" listServiceOfferings | jq -r '.serviceoffering[0].id')
221+
echo "TEMPLATE_ID=$TID" >> $GITHUB_ENV
222+
echo "SERVICE_OFFERING_ID=$SOID" >> $GITHUB_ENV
223+
test -n "$TID" -a -n "$SOID"
224+
225+
- name: deployVirtualMachine (base)
226+
run: |
227+
"${CMK_BIN}" set output json
228+
"${CMK_BIN}" deployVirtualMachine zoneid=${ZONE_ID} templateid=${TEMPLATE_ID} serviceofferingid=${SERVICE_OFFERING_ID} || true
229+
230+
- name: deployVirtualMachine with filter (only id)
231+
run: |
232+
"${CMK_BIN}" set output json
233+
OUT=$("${CMK_BIN}" deployVirtualMachine zoneid=${ZONE_ID} templateid=${TEMPLATE_ID} serviceofferingid=${SERVICE_OFFERING_ID} filter=id || true)
234+
echo "$OUT"
235+
if [ -n "$OUT" ]; then
236+
echo "$OUT" | jq -e '
237+
((.virtualmachine?.id? // empty) | tostring | length) > 0
238+
'
239+
else
240+
echo "No output. Skipping strict check."
241+
fi
242+
243+
- name: deployVirtualMachine with exclude (no id)
244+
run: |
245+
"${CMK_BIN}" set output json
246+
OUT=$("${CMK_BIN}" deployVirtualMachine zoneid=${ZONE_ID} templateid=${TEMPLATE_ID} serviceofferingid=${SERVICE_OFFERING_ID} exclude=id || true)
247+
echo "$OUT"
248+
if [ -n "$OUT" ]; then
249+
echo "$OUT" | jq -e '
250+
(.virtualmachine? | has("id") | not)
251+
'
252+
else
253+
echo "No output. Skipping strict check."
254+
fi
255+
256+
- name: Change profile (user) and compare API surface
257+
run: |
258+
ADMIN_COUNT=$("${CMK_BIN}" listApis | jq '.count')
259+
"${CMK_BIN}" createAccount username=user password=p@ssw0rd accounttype=0 domainid=1 firstname=Test lastname=User [email protected] || true
260+
"${CMK_BIN}" set profile user
261+
"${CMK_BIN}" set url "${CLOUDSTACK_UI_API}"
262+
"${CMK_BIN}" set username user
263+
"${CMK_BIN}" set password p@ssw0rd
264+
USER_COUNT=$("${CMK_BIN}" listApis | jq '.count // 0')
265+
echo "admin=${ADMIN_COUNT} user=${USER_COUNT}"
266+
test $USER_COUNT -le $ADMIN_COUNT
267+
268+
- name: Stop simulator MS
269+
working-directory: cloudstack
270+
run: |
271+
echo -e "Stopping Simulator, integration tests run completed\n"
272+
mvn -Dsimulator -pl client jetty:stop 2>&1
273+

0 commit comments

Comments
 (0)