2023-06-16 20:29:50 +00:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
# Copyright (c) HashiCorp, Inc.
|
2023-08-11 13:12:13 +00:00
|
|
|
# SPDX-License-Identifier: BUSL-1.1
|
2023-06-16 20:29:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
readonly SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})"
|
|
|
|
readonly SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
|
|
|
|
readonly SOURCE_DIR="$(dirname "$(dirname "${SCRIPT_DIR}")")"
|
|
|
|
readonly FN_DIR="$(dirname "${SCRIPT_DIR}")/functions"
|
|
|
|
|
|
|
|
source "${SCRIPT_DIR}/functions.sh"
|
|
|
|
|
|
|
|
|
|
|
|
set -uo pipefail
|
|
|
|
|
|
|
|
usage() {
|
|
|
|
cat <<-EOF
|
|
|
|
Usage: ${SCRIPT_NAME} <module root> [<allowed relative package path>...]
|
|
|
|
|
|
|
|
Description:
|
|
|
|
Verifies that only the specified packages may be imported from the given module
|
|
|
|
|
|
|
|
Options:
|
|
|
|
-h | --help Print this help text.
|
|
|
|
EOF
|
|
|
|
}
|
|
|
|
|
|
|
|
function err_usage {
|
|
|
|
err "$1"
|
|
|
|
err ""
|
|
|
|
err "$(usage)"
|
|
|
|
}
|
|
|
|
|
|
|
|
function main {
|
|
|
|
local module_root=""
|
|
|
|
declare -a allowed_packages=()
|
|
|
|
while test $# -gt 0
|
|
|
|
do
|
|
|
|
case "$1" in
|
|
|
|
-h | --help )
|
|
|
|
usage
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
* )
|
|
|
|
if test -z "$module_root"
|
|
|
|
then
|
|
|
|
module_root="$1"
|
|
|
|
else
|
2023-09-26 20:21:47 +00:00
|
|
|
allowed_packages+=("$1")
|
2023-06-16 20:29:50 +00:00
|
|
|
fi
|
|
|
|
shift
|
|
|
|
esac
|
|
|
|
done
|
|
|
|
|
|
|
|
# If we could guarantee this ran with bash 4.2+ then the final argument could
|
|
|
|
# be just ${allowed_packages[@]}. However that with older versions of bash
|
|
|
|
# in combination with set -u causes bash to emit errors about using unbound
|
|
|
|
# variables when no allowed packages have been specified (i.e. the module should
|
|
|
|
# generally be disallowed with no exceptions). This syntax is very strange
|
|
|
|
# but seems to be the prescribed workaround I found.
|
|
|
|
check_imports "$module_root" ${allowed_packages[@]+"${allowed_packages[@]}"}
|
|
|
|
return $?
|
|
|
|
}
|
|
|
|
|
|
|
|
function check_imports {
|
|
|
|
local module_root="$1"
|
|
|
|
shift
|
|
|
|
local allowed_packages="$@"
|
|
|
|
|
|
|
|
module_imports=$( go list -test -f '{{join .TestImports "\n"}}' ./... | grep "$module_root" | sort | uniq)
|
|
|
|
module_test_imports=$( go list -test -f '{{join .TestImports "\n"}}' ./... | grep "$module_root" | sort | uniq)
|
|
|
|
|
|
|
|
any_error=0
|
|
|
|
|
|
|
|
for imp in $module_imports
|
|
|
|
do
|
|
|
|
is_import_allowed "$imp" "$module_root" $allowed_packages
|
|
|
|
allowed=$?
|
|
|
|
|
|
|
|
if test $any_error -ne 1
|
|
|
|
then
|
|
|
|
any_error=$allowed
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
|
|
|
|
if test $any_error -eq 1
|
|
|
|
then
|
|
|
|
echo "Only the following direct imports are allowed from module $module_root:"
|
|
|
|
for pkg in $allowed_packages
|
|
|
|
do
|
|
|
|
echo " * $pkg"
|
|
|
|
done
|
|
|
|
fi
|
|
|
|
|
|
|
|
return $any_error
|
|
|
|
}
|
|
|
|
|
|
|
|
function is_import_allowed {
|
|
|
|
local pkg_import=$1
|
|
|
|
shift
|
|
|
|
local module_root=$1
|
|
|
|
shift
|
|
|
|
local allowed_packages="$@"
|
|
|
|
|
|
|
|
# check if the import path is a part of the module we are restricting imports for
|
|
|
|
if test "$( go list -f '{{.Module.Path}}' $pkg_import)" != "$module_root"
|
|
|
|
then
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
|
|
|
|
for pkg in $allowed_packages
|
|
|
|
do
|
|
|
|
if test "${module_root}/$pkg" == "$pkg_import"
|
|
|
|
then
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
|
|
|
|
err "Import of package $pkg_import is not allowed"
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
main "$@"
|
|
|
|
exit $?
|