Skip to content

Commit

Permalink
add runtime test capability
Browse files Browse the repository at this point in the history
  • Loading branch information
gilesknap committed Sep 22, 2023
1 parent a58654c commit 00c961a
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 7 deletions.
9 changes: 7 additions & 2 deletions .github/workflows/buiild.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Build and publish image to ghcr.io/epics-containers
name: Check that ibek-support support modules will build in a container

on:
push:
Expand Down Expand Up @@ -45,6 +45,11 @@ jobs:
if: runner.os == 'macos'
uses: docker-practice/actions-setup-docker@fd7ecdac7caf8e2c541a48c9bcc280aae59a8461

# Dockerfiles expect the repo to be in a subdirectory as its normally a submodule
# and it gets IOC the scripts from that super-module
- name: Move IOC
run: mv _test_ioc ../ioc

- name: Log in to GitHub Docker Registry
uses: docker/login-action@v1
with:
Expand All @@ -57,4 +62,4 @@ jobs:
ARCH: ${{ matrix.architecture }}
PLATFORM: ${{ matrix.platform }}
CACHE: ${{ env.CACHE }}
run: tests/_test_support_build.sh
run: .submodule/tests/_test_support_build.sh
32 changes: 32 additions & 0 deletions _test_ioc/config/st.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# EXAMPLE IOC Instance to demonstrate the ADSimDetector Generic IOC

cd "$(TOP)"

dbLoadDatabase "dbd/ioc.dbd"
ioc_registerRecordDeviceDriver(pdbbase)

# simDetectorConfig(portName, maxSizeX, maxSizeY, dataType, maxBuffers, maxMemory)
simDetectorConfig("EXAMPLE.CAM", 2560, 2160, 1, 50, 0)

# NDPvaConfigure(portName, queueSize, blockingCallbacks, NDArrayPort, NDArrayAddr, pvName, maxMemory, priority, stackSize)
NDPvaConfigure("EXAMPLE.PVA", 2, 0, "EXAMPLE.CAM", 0, "EXAMPLE:IMAGE", 0, 0, 0)

# NDFileHDF5Configure(portName, queueSize, blockingCallbacks, NDArrayPort, NDArrayAddr)
NDFileHDF5Configure("EXAMPLE.HDF", 2, 0, "EXAMPLE.CAM", 0)

startPVAServer

# instantiate Database records for Sim Detector
dbLoadRecords (simDetector.template, "P=EXAMPLE, R=:CAM:, PORT=EXAMPLE.CAM, TIMEOUT=1, ADDR=0")
dbLoadRecords (NDPva.template, "P=EXAMPLE, R=:PVA:, PORT=EXAMPLE.PVA, ADDR=0, TIMEOUT=1, NDARRAY_PORT=EXAMPLE.CAM, NDARRAY_ADR=0, ENABLED=1")
dbLoadRecords (NDFileHDF5.template, "P=EXAMPLE, R=:HDF:, PORT=EXAMPLE.HDF, ADDR=0, TIMEOUT=1, XMLSIZE=2048, NDARRAY_PORT=EXAMPLE.CAM, NDARRAY_ADDR=0, ENABLED=1, SCANRATE=I/O Intr")

# also make Database records for DEVIOCSTATS
dbLoadRecords(iocAdminSoft.db, "IOC=EXAMPLE")
dbLoadRecords(iocAdminScanMon.db, "IOC=EXAMPLE")

# start IOC shell
iocInit

# poke some records
dbpf "EXAMPLE:CAM:AcquirePeriod", "0.1"
40 changes: 40 additions & 0 deletions _test_ioc/liveness.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/bash
TOP=/repos/epics/ioc
cd ${TOP}
CONFIG_DIR=${TOP}/config

set -ex

CONFIG_DIR=/repos/epics/ioc/config
THIS_SCRIPT=$(realpath ${0})
override=${CONFIG_DIR}/liveness.sh

if [[ -f ${override} && ${override} != ${THIS_SCRIPT} ]]; then
exec bash ${override}
fi

if [[ ${K8S_IOC_LIVENESS_ENABLED} != 'true' ]]; then
exit 0
fi

# use devIOCStats UPTIME as the default liveness PV
# but allow override from the environment
K8S_IOC_PV=${K8S_IOC_PV:-"${IOC_PREFIX}:UPTIME"}

# use default CA PORT or override from the environment
K8S_IOC_PORT=${K8S_IOC_PORT:-5064}

export EPICS_CA_ADDR_LIST=${K8S_IOC_ADDRESS}
export EPICS_CA_SERVER_PORT=${K8S_IOC_PORT}

# verify that the IOC is running
if caget ${K8S_IOC_PV} ; then
exit 0
else
# send the error message to the container's main process stdout
echo "Liveness check failed for ${IOC_NAME}" > /proc/1/fd/1
echo "Failing PV: ${K8S_IOC_PV}" > /proc/1/fd/2
echo "Address list: ${EPICS_CA_ADDR_LIST}" > /proc/1/fd/2
echo "CA Port: ${EPICS_CA_SERVER_PORT}" > /proc/1/fd/2
exit 1
fi
112 changes: 112 additions & 0 deletions _test_ioc/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#!/bin/bash

#
# The epics-containers IOC startup script.
#
# This script is used to start an EPICS IOC in a Kubernetes pod. Implementers
# of generic IOCs are free to replace this script with their own. But
# this script as is should work for most IOCs.
#
# When a generic IOC runs in a kubernetes pod it is expected to have
# a config folder that defines the IOC instance.
# The helm chart for the generic IOC will mount the config folder
# as a configMap and this turns a generic IOC into aspecific IOC instance.
#
# Here we support the following set of options for the contents of
# the config folder:
#
# 1. start.sh ******************************************************************
# If the config folder contains a start.sh script it will be executed.
# This allows the instance implementer to provide a conmpletely custom
# startup script.
#
# 2. ioc.yaml *************************************************************
# If the config folder contains an ioc.yaml file we invoke the ibek tool to
# generate the startup script and database. Then launch with the generated
# startup script.
#
# 3. st.cmd + ioc.subst *********************************************************
# If the config folder contains a st.cmd script and a ioc.subst file then
# optionally generate ioc.db from the ioc.subst file and use the st.cmd script
# as the IOC startup script. Note that the expanded database file will
# be generated in /tmp/ioc.db
#
# 4. empty config folder *******************************************************
# If the config folder is empty then this IOC will launch the example in
# ./example folder
#
# RTEMS IOCS - RTEMS IOC startup files can be generated using 2,3,4 above. For
# RTEMS we do not execute the ioc inside of the pod. Instead we:
# - copy the IOC directory to the RTEMS mount point
# - send a reboot command to the RTEMS crate
# - start a telnet session to the RTEMS IOC console
#

set -x -e

# environment setup ************************************************************

TOP=$(realpath $(dirname $0))
cd ${TOP}
CONFIG_DIR=${TOP}/config

# add module paths to environment for use in ioc startup script
source ${SUPPORT}/configure/RELEASE.shell

# override startup script
override=${CONFIG_DIR}/start.sh
# source YAML for IOC Builder for EPICS on Kubernetes (ibek)
ibek_src=${CONFIG_DIR}/ioc.yaml
# Startup script for EPICS IOC generated by ibek
ioc_startup=${CONFIG_DIR}/st.cmd
# expanded database file
epics_db=/tmp/ioc.db


# 1. start.sh ******************************************************************

if [ -f ${override} ]; then
exec ${override}

# 2. ioc.yaml ******************************************************************

elif [ -f ${ibek_src} ]; then
# Database generation script generated by ibek
db_src=/tmp/make_db.sh
final_ioc_startup=/tmp/st.cmd

# get ibek the support yaml files this ioc's support modules
defs=/ctools/*/*.ibek.support.yaml
ibek build-startup ${ibek_src} ${defs} --out ${final_ioc_startup} --db-out ${db_src}

# build expanded database using the db_src shell script
if [ -f ${db_src} ]; then
bash ${db_src} > ${epics_db}
fi

# 3. st.cmd + ioc.substitutions ************************************************

elif [ -f ${ioc_startup} ] ; then
if [ -f ${CONFIG_DIR}/ioc.substitutions ]; then
# generate ioc.db from ioc.substitutions, including all templates from SUPPORT
includes=$(for i in ${SUPPORT}/*/db; do echo -n "-I $i "; done)
msi ${includes} -S ${CONFIG_DIR}/ioc.substitutions -o ${epics_db}
fi
final_ioc_startup=${ioc_startup}

# 4. empty config folder *******************************************************

else
final_ioc_startup=${TOP}/example/st.cmd
fi

# Launch the IOC ***************************************************************

if [[ ${TARGET_ARCHITECTURE} == "rtems" ]] ; then
echo "RTEMS IOC startup - copying IOC to RTEMS mount point ..."
cp -r ${IOC} ${K8S_IOC_ROOT}
sleep 100
else
# Execute the IOC binary and pass the startup script as an argument
exec ${IOC}/bin/linux-x86_64/ioc ${final_ioc_startup}
fi
16 changes: 16 additions & 0 deletions _test_ioc/stop.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

TOP=/repos/epics/ioc
cd ${TOP}
CONFIG_DIR=${TOP}/config

override=${CONFIG_DIR}/stop.sh

if [[ -f ${override} ]]; then
exec bash ${override}
elif [[ ${RTEMS_VME_AUTO_REBOOT} == 'true' ]] ; then
# This is a placeholder for a script that is called when the pod is stopped.
# Placing your own stop.sh in the config directory will override this script.
fi


3 changes: 3 additions & 0 deletions tests/Verify.asyn.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

echo "HELLO WORLD"
3 changes: 3 additions & 0 deletions tests/Verify.busy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

echo TODO add tests for busy support module
14 changes: 9 additions & 5 deletions tests/_test_support_build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
# CACHE: the directory to use for caching
# PLATFORM: the platform to build for (linux/amd64 or linux/arm64)

THIS_FOLDER=$(dirname $(readlink -f $0))
set -xe

THIS_FOLDER=$(dirname ${0})
# ibek-support is normally a submodule of the Docker Context so we need to
# pass the container context as the folder above the ibek-support folder
CONTEXT=$(realpath ${THIS_FOLDER}/../..)

set -xe

BASE_VERSION="23.9.2"

ARCH=${ARCH:-linux}
Expand Down Expand Up @@ -61,7 +61,7 @@ do_build() {
--build-arg BASE=${BASE_VERSION}
--build-arg REGISTRY=ghcr.io/epics-containers
--target ${TARGET}
--layers
--load
-t test_image_only
-f ${DOCKERFILE}
"
Expand Down Expand Up @@ -100,8 +100,12 @@ for dockerfile in ${THIS_FOLDER}/Dockerfile*; do
# The above check is sufficient to show that the generic IOC will load and
# run and that all the necessary runtime libraries are in place.
#
# for more detailed testing add a Verify.xxx script where xxx is the
# for more detailed testing add a Verify.xxx.sh script where xxx is the
# the same as the suffix on the Dockerfile. See Verify.asyn for an example.
VERIFY=Verify."${dockerfile#*.}"
if [[ -f ${THIS_FOLDER}/${VERIFY} ]] ; then
$THIS_FOLDER/${VERIFY} test_me
fi

$docker stop -t0 test_me

Expand Down

0 comments on commit 00c961a

Please sign in to comment.