Skip to content

Commit ae17648

Browse files
authored
Merge branch 'main' into feature-GraphvizHook
2 parents a394fd2 + f37df6f commit ae17648

2 files changed

Lines changed: 113 additions & 6 deletions

File tree

.github/workflows/test_eessi_container_script.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ jobs:
1717
- help
1818
- listrepos_default
1919
- listrepos_custom
20+
- no_cvmfs_mounts
2021
- run
2122
- shell
2223
- container
@@ -70,6 +71,14 @@ jobs:
7071
./eessi_container.sh --verbose --list-repos | tee ${outfile2}
7172
grep "EESSI/20AB.CD" ${outfile2}
7273
74+
# test use of --repository None
75+
elif [[ ${{matrix.SCRIPT_TEST}} == 'no_cvmfs_mounts' ]]; then
76+
outfile=out_nocvmfs.txt
77+
./eessi_container.sh --verbose --repository None --mode run mount | tee ${outfile}
78+
# make sure that there are no CVMFS mounts in the container, i.e. mount does not have any lines line:
79+
# cvmfs2 on /cvmfs/...
80+
! grep "^cvmfs" ${outfile}
81+
7382
# test use of --mode run
7483
elif [[ ${{matrix.SCRIPT_TEST}} == 'run' ]]; then
7584
outfile=out_run.txt

eessi_container.sh

Lines changed: 104 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ display_help() {
9898
echo " -r | --repository CFG - configuration file or identifier defining the"
9999
echo " repository to use; can be given multiple times;"
100100
echo " CFG may include suffixes ',access={ro,rw},mode={bind,fuse}' to"
101-
echo " overwrite the global access and/or mount mode for this repository"
101+
echo " overwrite the global access and/or mount mode for this repository;"
102+
echo " use 'None' to not mount any repositories"
102103
echo " [default: software.eessi.io via CVMFS config available"
103104
echo " via default container, see --container]"
104105
echo " -u | --resume DIR/TGZ - resume a previous run from a directory or tarball,"
@@ -123,6 +124,74 @@ display_help() {
123124
echo " '--' to let eessi_container.sh stop parsing arguments."
124125
}
125126

127+
# function to parse and check bind paths
128+
# returns:
129+
# 0 if target found with matching source (no conflict)
130+
# 1 if target found with different source (conflict)
131+
# 2 if target not found
132+
check_bind_paths_for_target() {
133+
local search_target="$1"
134+
local search_src="$2"
135+
local bind_paths="$3" # typically used to pass value of $BIND_PATHS
136+
137+
# handle empty BIND_PATHS
138+
if [[ -z "${bind_paths}" ]]; then
139+
return 2
140+
fi
141+
142+
# split by comma and process each entry
143+
IFS=',' read -ra BIND_ENTRIES <<< "${bind_paths}"
144+
145+
for entry in "${BIND_ENTRIES[@]}"; do
146+
# skip empty entries
147+
[[ -z "${entry}" ]] && continue
148+
149+
local bind_src bind_target
150+
151+
# split entry by ':'
152+
IFS=':' read -ra PARTS <<< "${entry}"
153+
154+
bind_src="${PARTS[0]}"
155+
156+
if [[ ${#PARTS[@]} -ge 2 ]]; then
157+
bind_target="${PARTS[1]}"
158+
else
159+
# no target given, use src
160+
bind_target=${bind_src}
161+
fi
162+
163+
# trim any possible whitespace
164+
bind_src=$(echo "${bind_src}" | xargs)
165+
bind_target=$(echo "${bind_target}" | xargs)
166+
167+
[[ ${VERBOSE} -eq 1 ]] && echo "Parsed bind entry: src='${bind_src}' target='${bind_target}'"
168+
169+
# check if this entry matches our target
170+
if [[ "${bind_target}" == "${search_target}" ]]; then
171+
# found target -> need to compare normalised sources
172+
# try to normalise source paths, but don't fail if they don't exist (yet)
173+
174+
bind_src_normalised=$(readlink -f "${bind_src}" 2>/dev/null)
175+
search_src_normalised=$(readlink -f "${search_src}" 2>/dev/null)
176+
177+
# decide which path to use - normalised or original
178+
local bind_src_compare="${bind_src_normalised:-${bind_src}}"
179+
local search_src_compare="${search_src_normalised:-${search_src}}"
180+
181+
[[ ${VERBOSE} -eq 1 ]] && echo "Comparing: '${bind_src_compare}' vs '${search_src_compare}'"
182+
183+
if [[ "${bind_src_compare}" == "${search_src_compare}" ]]; then
184+
return 0 # found target with same source (all good)
185+
else
186+
echo "${bind_src}" # return the conflicting source for error message
187+
return 1 # found target with different source (conflict)
188+
fi
189+
fi
190+
done
191+
192+
return 2 # target not found in bind paths
193+
}
194+
126195
# set defaults for command line arguments
127196
ACCESS="ro"
128197
CONTAINER="docker://ghcr.io/eessi/build-node:debian12"
@@ -285,6 +354,14 @@ if [[ ${#REPOSITORIES[@]} -eq 0 ]]; then
285354
REPOSITORIES+=(${eessi_default_cvmfs_repo})
286355
fi
287356

357+
# if the first element of REPOSITORIES is "none" (case-insensitive),
358+
# make sure it is an empty list from here on, i.e. no repositories will be mounted
359+
if [[ ${REPOSITORIES[0],,} == "none" ]]; then
360+
REPOSITORIES=()
361+
# also prevent the cvmfs-config repo from being mounted
362+
EESSI_DO_NOT_MOUNT_CVMFS_CONFIG_CERN_CH=1
363+
fi
364+
288365
# 1. check if argument values are valid
289366
# (arg -a|--access) check if ACCESS is supported
290367
# use the value as global setting, suffix to --repository can specify an access mode per repository
@@ -719,17 +796,38 @@ if [[ ! -z ${http_proxy} ]]; then
719796
HTTP_PROXY_IPV4=$(get_ipv4_address ${PROXY_HOST})
720797
[[ ${VERBOSE} -eq 1 ]] && echo "HTTP_PROXY_IPV4='${HTTP_PROXY_IPV4}'"
721798
echo "CVMFS_HTTP_PROXY=\"${http_proxy}|http://${HTTP_PROXY_IPV4}:${PROXY_PORT}\"" \
722-
>> ${EESSI_TMPDIR}/repos_cfg/default.local
799+
>> ${EESSI_TMPDIR}/repos_cfg/default.local
723800
[[ ${VERBOSE} -eq 1 ]] && echo "contents of default.local"
724801
[[ ${VERBOSE} -eq 1 ]] && cat ${EESSI_TMPDIR}/repos_cfg/default.local
725802

726803
# if default.local is not BIND mounted into container, add it to BIND_PATHS
727804
src=${EESSI_TMPDIR}/repos_cfg/default.local
728805
target=/etc/cvmfs/default.local
729-
if [[ ${BIND_PATHS} =~ "${target}" ]]; then
730-
fatal_error "BIND target in '${src}:${target}' is already in paths to be bind mounted into the container ('${BIND_PATHS}')" ${REPOSITORY_ERROR_EXITCODE}
731-
fi
732-
BIND_PATHS="${BIND_PATHS},${src}:${target}"
806+
807+
# check if target already exists in BIND_PATHS, and, if so, if sources are
808+
# the same
809+
conflict_src=$(check_bind_paths_for_target "${target}" "${src}" "${BIND_PATHS}")
810+
check_result=$?
811+
812+
case ${check_result} in
813+
0)
814+
# target already bound with same source - no action needed
815+
[[ ${VERBOSE} -eq 1 ]] && echo "Bind mount already configured: ${src}:${target}"
816+
;;
817+
1)
818+
# target already bound with different source - conflict!
819+
fatal_error "BIND target '${target}' conflict: already bound from '${conflict_src}', cannot bind from '${src}'" ${REPOSITORY_ERROR_EXITCODE}
820+
;;
821+
2)
822+
# target not found - safe to add
823+
if [[ -z ${BIND_PATH} ]]; then
824+
BIND_PATHS="${src}:${target}"
825+
else
826+
BIND_PATHS="${BIND_PATHS},${src}:${target}"
827+
fi
828+
[[ ${VERBOSE} -eq 1 ]] && echo "Added bind mount: ${src}:${target}"
829+
;;
830+
esac
733831
fi
734832

735833
# 4. set up vars and dirs specific to a scenario

0 commit comments

Comments
 (0)