Skip to content

Commit d6559f1

Browse files
authored
fix: resolve podman compatibility issues (#512)
Signed-off-by: Nathan Nguyen <[email protected]>
1 parent c27aec9 commit d6559f1

File tree

1 file changed

+173
-57
lines changed

1 file changed

+173
-57
lines changed

scripts/release_scripts/run_macaron.sh

Lines changed: 173 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ if [[ "${BASH_VERSINFO[0]}" -lt "4" ]]; then
4343
log_warning "Using bash version >=4 is recommended."
4444
fi
4545

46+
# Determine the Macaron image tag.
4647
if [[ -z ${MACARON_IMAGE_TAG:-} ]]; then
4748
MACARON_IMAGE_TAG="latest"
4849
fi
@@ -104,8 +105,14 @@ function to_absolute_path() {
104105
# With the `set -e` option turned on, this function exits the script with
105106
# return code 1 if the directory does not exist.
106107
function assert_dir_exists() {
107-
if [[ ! -d "$1" ]]; then
108-
log_err "Directory $1 of argument $2 does not exist."
108+
path=$1
109+
arg_name=$2
110+
if [[ ! -d "$path" ]]; then
111+
if [[ -z "${arg_name:-}" ]]; then
112+
log_err "Directory $path does not exist."
113+
else
114+
log_err "Directory $path of argument $arg_name does not exist."
115+
fi
109116
return 1
110117
fi
111118
}
@@ -140,6 +147,114 @@ function assert_path_exists() {
140147
fi
141148
}
142149

150+
# Create a directory if it does not exist.
151+
# Arguments:
152+
# $1: The directory to create.
153+
function create_dir_if_not_exists() {
154+
dir=$1
155+
if [ ! -d "$dir" ]; then
156+
mkdir --parents "$dir"
157+
fi
158+
}
159+
160+
# Add a directory to the list of volume mounts stored in the ``mounts`` global variable.
161+
# Note: Do not use this function directly for mounting directories.
162+
# Use one among these instead: `mount_dir_ro`, `mount_dir_rw_allow_create`, or
163+
# `mount_dir_rw_forbid_create` instead.
164+
#
165+
# Arguments:
166+
# $1: The macaron argument from which the directory is passed into this script.
167+
# $2: The path to the directory on the host.
168+
# $3: The path to the directory inside the container.
169+
# $4: Mount option. Note: this MUST be either `ro,Z` for readonly volume mounts,
170+
# or `rw,Z` otherwise.
171+
function _mount_dir() {
172+
arg_name=$1
173+
dir_on_host=$2
174+
dir_in_container=$3
175+
mount_option=$4
176+
177+
dir_on_host=$(to_absolute_path "$dir_on_host")
178+
mounts+=("-v" "${dir_on_host}:${dir_in_container}:${mount_option}")
179+
}
180+
181+
# Add a directory to the list of volume mounts stored in the ``mounts`` global variable,
182+
# with the `ro,Z` mount option.
183+
# If the mounted directory does not exist on the host, this function errors
184+
# and exits the script.
185+
#
186+
# Arguments:
187+
# $1: The macaron argument from which the directory is passed into this script.
188+
# $2: The path to the directory on the host.
189+
# $3: The path to the directory inside the container.
190+
function mount_dir_ro() {
191+
arg_name=$1
192+
dir_on_host=$2
193+
dir_in_container=$3
194+
195+
assert_dir_exists "$dir_on_host" "$arg_name"
196+
_mount_dir "$arg_name" "$dir_on_host" "$dir_in_container" "ro,Z"
197+
}
198+
199+
# Add a directory to the list of volume mounts stored in the ``mounts`` global variable,
200+
# with the `rw,Z` mount option.
201+
# If the mounted directory does not exist on the host, this function creates
202+
# that directory before mounting.
203+
# Note: This function ensures compatibility with podman, as podman does not
204+
# create the directory on host if it does not exist and instead errors on mount.
205+
#
206+
# Arguments:
207+
# $1: The macaron argument from which the directory is passed into this script.
208+
# $2: The path to the directory on the host.
209+
# $3: The path to the directory inside the container.
210+
function mount_dir_rw_allow_create() {
211+
arg_name=$1
212+
dir_on_host=$2
213+
dir_in_container=$3
214+
215+
create_dir_if_not_exists "$dir_on_host"
216+
_mount_dir "$arg_name" "$dir_on_host" "$dir_in_container" "rw,Z"
217+
}
218+
219+
# Add a directory to the list of volume mounts stored in the ``mounts`` global variable,
220+
# with the `rw,Z` mount option.
221+
# If the mounted directory does not exist on the host, this function errors and
222+
# exits the script.
223+
# Note: This function ensures compatibility with podman, as podman does not
224+
# create the directory on host if it does not exist and instead errors on mount.
225+
#
226+
# Arguments:
227+
# $1: The macaron argument from which the directory is passed into this script.
228+
# $2: The path to the directory on the host.
229+
# $3: The path to the directory inside the container.
230+
function mount_dir_rw_forbid_create() {
231+
arg_name=$1
232+
dir_on_host=$2
233+
dir_in_container=$3
234+
235+
assert_dir_exists "$dir_on_host" "$arg_name"
236+
_mount_dir "$arg_name" "$dir_on_host" "$dir_in_container" "rw,Z"
237+
}
238+
239+
# Add a file to the list of volume mounts stored in the ``mounts`` global variable.
240+
#
241+
# Arguments:
242+
# $1: The macaron argument from which the file is passed into this script.
243+
# $2: The path to the file on the host.
244+
# $3: The path to the file inside the container.
245+
# $4: Mount option. Note: this MUST be either `ro,Z` for readonly volumes,
246+
# or `rw,Z` otherwise.
247+
function mount_file() {
248+
arg_name=$1
249+
file_on_host=$2
250+
file_in_container=$3
251+
mount_option=$4
252+
253+
assert_file_exists "$file_on_host" "$arg_name"
254+
file_on_host=$(to_absolute_path "$file_on_host")
255+
mounts+=("-v" "${file_on_host}:${file_in_container}:${mount_option}")
256+
}
257+
143258
# Parse main arguments.
144259
while [[ $# -gt 0 ]]; do
145260
case $1 in
@@ -222,130 +337,124 @@ fi
222337
# Determine the output path to be mounted into ${MACARON_WORKSPACE}/output/
223338
if [[ -n "${arg_output:-}" ]]; then
224339
output="${arg_output}"
225-
assert_dir_exists "${output}" "-o/--output"
226340
argv_main+=("--output" "${MACARON_WORKSPACE}/output/")
227341
else
228342
output=$(pwd)/output
229343
echo "Setting default output directory to ${output}."
230344
fi
231345

232-
output="$(to_absolute_path "${output}")"
233-
# Mounting the necessary .m2 and .gradle directories.
346+
# Mount the necessary .m2 and .gradle directories.
234347
m2_dir="${output}/.m2"
235348
gradle_dir="${output}/.gradle"
236-
mounts+=("-v" "${output}:${MACARON_WORKSPACE}/output:rw,Z")
237-
mounts+=("-v" "${m2_dir}:${MACARON_WORKSPACE}/.m2:rw,Z")
238-
mounts+=("-v" "${gradle_dir}:${MACARON_WORKSPACE}/.gradle:rw,Z")
349+
350+
mount_dir_rw_allow_create "" "$output" "${MACARON_WORKSPACE}/output"
351+
mount_dir_rw_allow_create "" "$m2_dir" "${MACARON_WORKSPACE}/.m2"
352+
mount_dir_rw_allow_create "" "$gradle_dir" "${MACARON_WORKSPACE}/.gradle"
239353

240354
# Determine the local repos path to be mounted into ${MACARON_WORKSPACE}/output/git_repos/local_repos/
241355
if [[ -n "${arg_local_repos_path:-}" ]]; then
242-
local_repos_path="${arg_local_repos_path}"
243-
assert_dir_exists "${local_repos_path}" "-lr/--local-repos-path"
244-
argv_main+=("--local-repos-path" "${MACARON_WORKSPACE}/output/git_repos/local_repos/")
356+
local_repo_path_in_container="${MACARON_WORKSPACE}/output/git_repos/local_repos"
245357

246-
local_repos_path="$(to_absolute_path "${local_repos_path}")"
247-
mounts+=("-v" "${local_repos_path}:${MACARON_WORKSPACE}/output/git_repos/local_repos/:rw,Z")
358+
argv_main+=("--local-repos-path" "$local_repo_path_in_container")
359+
mount_dir_rw_allow_create "-lr/--local-repos-path" "$arg_local_repos_path" "$local_repo_path_in_container"
248360
fi
249361

250362
# Determine the defaults path to be mounted into ${MACARON_WORKSPACE}/defaults/${file_name}
251363
if [[ -n "${arg_defaults_path:-}" ]]; then
252364
defaults_path="${arg_defaults_path}"
253-
assert_file_exists "${defaults_path}" "-dp/--defaults-path"
254-
file_name="$(basename "${defaults_path}")"
255-
argv_main+=("--defaults-path" "${MACARON_WORKSPACE}/defaults/${file_name}")
365+
file_name="$(basename "${arg_defaults_path}")"
366+
defaults_path_in_container="${MACARON_WORKSPACE}/defaults/${file_name}"
256367

257-
defaults_path="$(to_absolute_path "${defaults_path}")"
258-
mounts+=("-v" "${defaults_path}:${MACARON_WORKSPACE}/defaults/${file_name}:ro")
368+
argv_main+=("--defaults-path" "$defaults_path_in_container")
369+
mount_file "-dp/--defaults-path" "$defaults_path" "$defaults_path_in_container" "ro,Z"
259370
fi
260371

261372
# Determine the policy path to be mounted into ${MACARON_WORKSPACE}/policy/${file_name}
262373
if [[ -n "${arg_policy:-}" ]]; then
263-
policy="${arg_policy}"
264-
assert_file_exists "${policy}" "-po/--policy"
265-
file_name="$(basename "${policy}")"
266-
argv_main+=("--policy" "${MACARON_WORKSPACE}/policy/${file_name}")
374+
policy_file="${arg_policy}"
375+
file_name="$(basename "${policy_file}")"
376+
policy_file_in_container="${MACARON_WORKSPACE}/policy/${file_name}"
267377

268-
policy="$(to_absolute_path "${policy}")"
269-
mounts+=("-v" "${policy}:${MACARON_WORKSPACE}/policy/${file_name}:ro")
378+
argv_main+=("--policy" "$policy_file_in_container")
379+
mount_file "-po/--policy" "$policy_file" "$policy_file_in_container" "ro,Z"
270380
fi
271381

272382
# MACARON entrypoint - Analyze command argvs
273383
# Determine the template path to be mounted into ${MACARON_WORKSPACE}/template/${file_name}
274384
if [[ -n "${arg_template_path:-}" ]]; then
275385
template_path="${arg_template_path}"
276-
assert_file_exists "${template_path}" "-g/--template-path"
277386
file_name="$(basename "${template_path}")"
278-
argv_command+=("--template-path" "${MACARON_WORKSPACE}/template/${file_name}")
387+
template_path_in_container="${MACARON_WORKSPACE}/template/${file_name}"
279388

280-
template_path="$(to_absolute_path "${template_path}")"
281-
mounts+=("-v" "${template_path}:${MACARON_WORKSPACE}/template/${file_name}:ro")
389+
argv_command+=("--template-path" "$template_path_in_container")
390+
mount_file "-g/--template-path" "$template_path" "$template_path_in_container" "ro,Z"
282391
fi
283392

284393
# Determine the config path to be mounted into ${MACARON_WORKSPACE}/config/${file_name}
285394
if [[ -n "${arg_config_path:-}" ]]; then
286395
config_path="${arg_config_path}"
287-
assert_file_exists "${config_path}" "-c/--config-path"
288396
file_name="$(basename "${config_path}")"
289-
argv_command+=("--config-path" "${MACARON_WORKSPACE}/config/${file_name}")
397+
config_path_in_container="${MACARON_WORKSPACE}/config/${file_name}"
290398

291-
config_path="$(to_absolute_path "${config_path}")"
292-
mounts+=("-v" "${config_path}:${MACARON_WORKSPACE}/config/${file_name}:ro")
399+
argv_command+=("--config-path" "$config_path_in_container")
400+
mount_file "-c/--config-path" "$config_path" "$config_path_in_container" "ro,Z"
293401
fi
294402

295403
# Determine the sbom path to be mounted into ${MACARON_WORKSPACE}/sbom/${file_name}
296404
if [[ -n "${arg_sbom_path:-}" ]]; then
297405
sbom_path="${arg_sbom_path}"
298-
assert_file_exists "${sbom_path}" "-sbom/--sbom-path"
299406
file_name="$(basename "${sbom_path}")"
300-
argv_command+=("--sbom-path" "${MACARON_WORKSPACE}/sbom/${file_name}")
407+
sbom_path_in_container="${MACARON_WORKSPACE}/sbom/${file_name}"
301408

302-
sbom_path="$(to_absolute_path "${sbom_path}")"
303-
mounts+=("-v" "${sbom_path}:${MACARON_WORKSPACE}/sbom/${file_name}:ro")
409+
argv_command+=("--sbom-path" "$sbom_path_in_container")
410+
mount_file "-sbom/--sbom-path" "$sbom_path" "$sbom_path_in_container" "ro,Z"
304411
fi
305412

306-
# Determine the provenance expectation path to be mounted into ${MACARON_WORKSPACE}/prov_expectations/${file_name}
413+
# Determine the provenance expectation path to be mounted into ${MACARON_WORKSPACE}/prov_expectations/${pe_name} where pe_name can either be a directory or a file
307414
if [[ -n "${arg_prov_exp:-}" ]]; then
308-
prov_exp="${arg_prov_exp}"
309-
assert_path_exists "${prov_exp}" "-pe/--provenance-expectation"
310-
pe_name="$(basename "${prov_exp}")"
311-
argv_command+=("--provenance-expectation" "${MACARON_WORKSPACE}/prov_expectations/${pe_name}")
312-
313-
prov_exp="$(to_absolute_path "${prov_exp}")"
314-
mounts+=("-v" "${prov_exp}:${MACARON_WORKSPACE}/prov_expectations/${pe_name}:ro")
415+
prov_exp_path="${arg_prov_exp}"
416+
assert_path_exists "${prov_exp_path}" "-pe/--provenance-expectation"
417+
prov_exp_name="$(basename "${prov_exp_path}")"
418+
prov_exp_path_in_container=${MACARON_WORKSPACE}/prov_expectations/${prov_exp_name}
419+
argv_command+=("--provenance-expectation" "$prov_exp_path_in_container")
420+
421+
if [ -d "$prov_exp_path" ]; then
422+
mount_dir_ro "-pe/--provenance-expectation" "$prov_exp_path" "$prov_exp_path_in_container"
423+
elif [ -f "$prov_exp_path" ]; then
424+
mount_file "-pe/--provenance-expectation" "$prov_exp_path" "$prov_exp_path_in_container" "ro,Z"
425+
fi
315426
fi
316427

317428
# MACARON entrypoint - verify-policy command argvs
318429
# This is for macaron verify-policy command.
319430
# Determine the database path to be mounted into ${MACARON_WORKSPACE}/database/macaron.db
320431
if [[ -n "${arg_database:-}" ]]; then
321-
database="${arg_database}"
322-
assert_file_exists "${database}" "-d/--database"
323-
file_name="$(basename "${database}")"
324-
argv_command+=("--database" "${MACARON_WORKSPACE}/database/${file_name}")
432+
database_path="${arg_database}"
433+
file_name="$(basename "${database_path}")"
434+
database_path_in_container="${MACARON_WORKSPACE}/database/${file_name}"
325435

326-
database="$(to_absolute_path "${database}")"
327-
mounts+=("-v" "${database}:${MACARON_WORKSPACE}/database/${file_name}:rw,Z")
436+
argv_command+=("--database" "$database_path_in_container")
437+
mount_file "-d/--database" "$database_path" "$database_path_in_container" "rw,Z"
328438
fi
329439

330440
# Determine the Datalog policy to be verified by verify-policy command.
331441
if [[ -n "${arg_datalog_policy_file:-}" ]]; then
332442
datalog_policy_file="${arg_datalog_policy_file}"
333-
assert_file_exists "${datalog_policy_file}" "-f/--file"
334443
file_name="$(basename "${datalog_policy_file}")"
335-
argv_command+=("--file" "${MACARON_WORKSPACE}/policy/${file_name}")
444+
datalog_policy_file_in_container="${MACARON_WORKSPACE}/policy/${file_name}"
336445

337-
datalog_policy_file="$(to_absolute_path "${datalog_policy_file}")"
338-
mounts+=("-v" "${datalog_policy_file}:${MACARON_WORKSPACE}/policy/${file_name}:ro")
446+
argv_command+=("--file" "$datalog_policy_file_in_container")
447+
mount_file "-f/--file" "$datalog_policy_file" "$datalog_policy_file_in_container" "ro,Z"
339448
fi
340449

341450
# Determine that ~/.gradle/gradle.properties exists to be mounted into ${MACARON_WORKSPACE}/gradle.properties
342451
if [[ -f "$HOME/.gradle/gradle.properties" ]]; then
343-
mounts+=("-v" "$HOME/.gradle/gradle.properties":"${MACARON_WORKSPACE}/gradle.properties:ro")
452+
mounts+=("-v" "$HOME/.gradle/gradle.properties":"${MACARON_WORKSPACE}/gradle.properties:ro,Z")
344453
fi
345454

346455
# Determine that ~/.m2/settings.xml exists to be mounted into ${MACARON_WORKSPACE}/settings.xml
347456
if [[ -f "$HOME/.m2/settings.xml" ]]; then
348-
mounts+=("-v" "$HOME/.m2/settings.xml":"${MACARON_WORKSPACE}/settings.xml:ro")
457+
mounts+=("-v" "$HOME/.m2/settings.xml":"${MACARON_WORKSPACE}/settings.xml:ro,Z")
349458
fi
350459

351460
# Set up proxy.
@@ -419,8 +528,15 @@ if [[ -n ${MCN_DEBUG_ARGS:-} ]]; then
419528
exit 0
420529
fi
421530

531+
# By default
532+
# - docker maps the host user $UID to a user with the same $UID in the container.
533+
# - podman maps the host user $UID to the root user in the container.
534+
# To make podman behave similarly to docker, we need to set the following env var.
535+
# Reference: https://docs.podman.io/en/v4.4/markdown/options/userns.container.html.
536+
export PODMAN_USERNS=keep-id
537+
422538
docker run \
423-
--pull ${DOCKER_PULL} \
539+
--pull "${DOCKER_PULL}" \
424540
--network=host \
425541
--rm -i "${tty[@]}" \
426542
-e "USER_UID=${USER_UID}" \

0 commit comments

Comments
 (0)