Skip to content

Commit 400c58b

Browse files
committed
added deploy information in markdown
updated indexer to also update central catalog
1 parent e4a8c46 commit 400c58b

2 files changed

Lines changed: 234 additions & 0 deletions

File tree

Deploy.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# deploying the ICRN kernel manager services
2+
3+
## Changes needed to ICRN containers in dev
4+
5+
6+
7+
## running the kernel index process
8+
9+
This is done via a container, currently located at: `docker://hdpriest0uiuc/icrn-kernel-indexer`;
10+
11+
Tested on campus cluster via apptainer, this indexes the central repository of kernels and places the two manifest files at their location in `/sw/icrn/jupyter/icrn_ncsa_resources/Kernels/`. If we want to keep them somewhere else, we can shift that via bind-mount changes.
12+
13+
```sh
14+
(base) [hdpriest@cc-login2 icrn_manager]$ cd /sw/icrn/jupyter/icrn_ncsa_resources/tools/icrn_manager
15+
(base) [hdpriest@cc-login2 icrn_manager]$ apptainer pull docker://hdpriest0uiuc/icrn-kernel-indexer
16+
17+
(base) [hdpriest@cc-login2 icrn_manager]$ apptainer run --bind /sw/icrn/jupyter/icrn_ncsa_resources/Kernels:/sw/icrn/jupyter/icrn_ncsa_resources/Kernels icrn-kernel-indexer_latest.sif
18+
## ... output
19+
Collated manifest written to: /sw/icrn/jupyter/icrn_ncsa_resources/Kernels/collated_manifests.json
20+
## ... output
21+
Package-centric index written to: /sw/icrn/jupyter/icrn_ncsa_resources/Kernels/package_index.json
22+
## ... output
23+
```
24+
25+
26+
## running the web server, based on the index contents of the central repository
27+
28+
Docker build from git root:
29+
```sh
30+
docker build -t icrn-web -f web/Dockerfile web/
31+
```
32+
33+
Assuming you have a built container (obtained from dockerhub, or built locally), the container expects bind mounts to the location where the manifests/index are kept, and so is flexible for its back-end storage as long as it has access to the same disk mount as the index job:
34+
```bash
35+
docker run -d -p 8080:80 --name icrn-web \
36+
-v /sw/icrn/jupyter/icrn_ncsa_resources/Kernels/collated_manifests.json:/app/data/collated_manifests.json \
37+
-v /sw/icrn/jupyter/icrn_ncsa_resources/Kernels/package_index.json:/app/data/package_index.json \
38+
icrn-web
39+
```
40+
41+
Generic docker run commands:
42+
```bash
43+
docker run -d -p 8080:80 --name icrn-web \
44+
-v /path/to/collated_manifests.json:/app/data/collated_manifests.json \
45+
-v /path/to/package_index.json:/app/data/package_index.json \
46+
icrn-web
47+
```

kernel-indexer/entrypoint.sh

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ EXIT_MISSING_DEPS=2
88
EXIT_KERNEL_ROOT_INVALID=3
99
EXIT_INDEX_FAILED=4
1010
EXIT_COLLATE_FAILED=5
11+
EXIT_CATALOG_UPDATE_FAILED=6
1112

1213
# Default configuration
1314
DEFAULT_KERNEL_ROOT="/sw/icrn/jupyter/icrn_ncsa_resources/Kernels"
@@ -151,6 +152,174 @@ validate_collated_file() {
151152
return 0
152153
}
153154

155+
# Normalize language name to match catalog conventions (capitalize first letter)
156+
normalize_language() {
157+
local lang="$1"
158+
if [ -z "$lang" ]; then
159+
echo ""
160+
return
161+
fi
162+
# Capitalize first letter, lowercase the rest
163+
local first_char=$(echo "${lang:0:1}" | tr '[:lower:]' '[:upper:]')
164+
local rest_chars=$(echo "${lang:1}" | tr '[:upper:]' '[:lower:]')
165+
echo "${first_char}${rest_chars}"
166+
}
167+
168+
# Update icrn_kernel_catalog.json with discovered kernels
169+
update_kernel_catalog() {
170+
local collated_manifests="$1"
171+
local catalog_file="${KERNEL_ROOT}/icrn_kernel_catalog.json"
172+
173+
log_info "Starting catalog update phase..."
174+
log_info "Reading collated manifests from: ${collated_manifests}"
175+
log_info "Catalog file: ${catalog_file}"
176+
177+
# Check if collated manifests file exists
178+
if [ ! -f "${collated_manifests}" ]; then
179+
log_error "Collated manifests file not found: ${collated_manifests}"
180+
return 1
181+
fi
182+
183+
# Validate collated manifests JSON
184+
if ! jq '.' "${collated_manifests}" >/dev/null 2>&1; then
185+
log_error "Invalid JSON in collated manifests: ${collated_manifests}"
186+
return 1
187+
fi
188+
189+
# Load existing catalog or create empty structure
190+
local existing_catalog
191+
if [ -f "${catalog_file}" ]; then
192+
log_info "Loading existing catalog from: ${catalog_file}"
193+
if ! jq '.' "${catalog_file}" >/dev/null 2>&1; then
194+
log_error "Invalid JSON in existing catalog: ${catalog_file}"
195+
return 1
196+
fi
197+
existing_catalog=$(cat "${catalog_file}")
198+
else
199+
log_info "Catalog file does not exist, creating new catalog"
200+
existing_catalog="{}"
201+
fi
202+
203+
# Create temporary file for updated catalog
204+
local temp_catalog=$(mktemp)
205+
206+
# Process each kernel from collated manifests
207+
local kernel_count=0
208+
local updated_count=0
209+
local added_count=0
210+
211+
# Extract kernels array and process each kernel
212+
local kernels_json=$(jq -c '.kernels[]?' "${collated_manifests}" 2>/dev/null)
213+
214+
if [ -z "$kernels_json" ]; then
215+
log_warn "No kernels found in collated manifests"
216+
# If no kernels and catalog doesn't exist, create empty catalog
217+
if [ ! -f "${catalog_file}" ]; then
218+
echo "{}" | jq '.' > "${temp_catalog}"
219+
if [ "${ATOMIC_WRITES}" = "true" ]; then
220+
mv "${temp_catalog}" "${catalog_file}"
221+
else
222+
cp "${temp_catalog}" "${catalog_file}"
223+
rm -f "${temp_catalog}"
224+
fi
225+
log_info "Created empty catalog file"
226+
fi
227+
return 0
228+
fi
229+
230+
# Start with existing catalog
231+
local updated_catalog="$existing_catalog"
232+
233+
# Process each kernel
234+
while IFS= read -r kernel_json; do
235+
[ -z "$kernel_json" ] && continue
236+
237+
kernel_count=$((kernel_count + 1))
238+
239+
# Extract kernel information
240+
local kernel_name=$(echo "$kernel_json" | jq -r '.kernel_name // empty')
241+
local kernel_version=$(echo "$kernel_json" | jq -r '.kernel_version // empty')
242+
local language=$(echo "$kernel_json" | jq -r '.language // empty')
243+
244+
if [ -z "$kernel_name" ] || [ -z "$kernel_version" ] || [ -z "$language" ]; then
245+
log_warn "Skipping kernel with missing required fields: ${kernel_json}"
246+
continue
247+
fi
248+
249+
# Normalize language name
250+
local normalized_lang=$(normalize_language "$language")
251+
252+
# Construct paths
253+
local environment_location="${KERNEL_ROOT}/${normalized_lang}/${kernel_name}/${kernel_version}"
254+
local manifest_path="${KERNEL_ROOT}/${normalized_lang}/${kernel_name}/${kernel_version}/package_manifest.json"
255+
256+
log_debug "Processing kernel: ${normalized_lang}/${kernel_name}/${kernel_version}"
257+
258+
# Check if kernel entry already exists in catalog
259+
if echo "$updated_catalog" | jq -e --arg lang "$normalized_lang" --arg name "$kernel_name" --arg ver "$kernel_version" \
260+
'.[$lang][$name][$ver] != null' >/dev/null 2>&1; then
261+
# Update existing entry
262+
updated_catalog=$(echo "$updated_catalog" | jq --arg lang "$normalized_lang" \
263+
--arg name "$kernel_name" \
264+
--arg ver "$kernel_version" \
265+
--arg env_loc "$environment_location" \
266+
--arg manifest "$manifest_path" \
267+
'.[$lang][$name][$ver].environment_location = $env_loc |
268+
.[$lang][$name][$ver].manifest = $manifest')
269+
updated_count=$((updated_count + 1))
270+
log_debug "Updated existing catalog entry: ${normalized_lang}/${kernel_name}/${kernel_version}"
271+
else
272+
# Add new entry
273+
updated_catalog=$(echo "$updated_catalog" | jq --arg lang "$normalized_lang" \
274+
--arg name "$kernel_name" \
275+
--arg ver "$kernel_version" \
276+
--arg env_loc "$environment_location" \
277+
--arg manifest "$manifest_path" \
278+
'if .[$lang] == null then .[$lang] = {} else . end |
279+
if .[$lang][$name] == null then .[$lang][$name] = {} else . end |
280+
.[$lang][$name][$ver] = {
281+
environment_location: $env_loc,
282+
manifest: $manifest
283+
}')
284+
added_count=$((added_count + 1))
285+
log_debug "Added new catalog entry: ${normalized_lang}/${kernel_name}/${kernel_version}"
286+
fi
287+
done <<< "$kernels_json"
288+
289+
# Write updated catalog to temp file
290+
echo "$updated_catalog" | jq '.' > "${temp_catalog}"
291+
292+
if [ $? -ne 0 ]; then
293+
log_error "Failed to write updated catalog to temp file"
294+
rm -f "${temp_catalog}"
295+
return 1
296+
fi
297+
298+
# Validate the updated catalog JSON
299+
if ! jq '.' "${temp_catalog}" >/dev/null 2>&1; then
300+
log_error "Invalid JSON in updated catalog"
301+
rm -f "${temp_catalog}"
302+
return 1
303+
fi
304+
305+
# Write catalog file (atomic if enabled)
306+
if [ "${ATOMIC_WRITES}" = "true" ]; then
307+
mv "${temp_catalog}" "${catalog_file}"
308+
log_info "Catalog updated atomically: ${catalog_file}"
309+
else
310+
cp "${temp_catalog}" "${catalog_file}"
311+
rm -f "${temp_catalog}"
312+
log_info "Catalog updated: ${catalog_file}"
313+
fi
314+
315+
log_info "Catalog update completed successfully"
316+
log_info " Processed kernels: ${kernel_count}"
317+
log_info " Updated entries: ${updated_count}"
318+
log_info " Added entries: ${added_count}"
319+
320+
return 0
321+
}
322+
154323
# Main execution
155324
main() {
156325
log_info "Starting kernel indexer container"
@@ -223,6 +392,24 @@ main() {
223392
exit $EXIT_COLLATE_FAILED
224393
fi
225394

395+
# Execute catalog update phase
396+
log_info "Starting catalog update phase..."
397+
398+
if update_kernel_catalog "${collated_manifests}"; then
399+
log_info "Catalog update phase completed successfully"
400+
401+
# Validate updated catalog file
402+
local catalog_file="${KERNEL_ROOT}/icrn_kernel_catalog.json"
403+
if ! validate_collated_file "${catalog_file}" "kernel catalog"; then
404+
log_error "Catalog file validation failed"
405+
exit $EXIT_CATALOG_UPDATE_FAILED
406+
fi
407+
else
408+
local exit_code=$?
409+
log_error "Catalog update phase failed with exit code: ${exit_code}"
410+
exit $EXIT_CATALOG_UPDATE_FAILED
411+
fi
412+
226413
log_info "Kernel indexing completed successfully"
227414
exit $EXIT_SUCCESS
228415
}

0 commit comments

Comments
 (0)