Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"files": "^.secrets.baseline$",
"lines": null
},
"generated_at": "2025-11-23T00:19:45Z",
"generated_at": "2025-11-26T21:55:36Z",
"plugins_used": [
{
"name": "AWSKeyDetector"
Expand Down Expand Up @@ -82,7 +82,7 @@
"hashed_secret": "1de54cf4c9c5e2b8b9aef885aebefb5c1be33332",
"is_secret": false,
"is_verified": false,
"line_number": 136,
"line_number": 207,
"type": "Secret Keyword",
"verified_result": null
}
Expand Down
71 changes: 71 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,77 @@ check_required_bins git jq

<!------------------------------------------------>

<details>
<summary>install_jq</summary>

Installs jq binary.

**Environment Variables:**
- `VERBOSE`: If set to true, print verbose output (optional, defaults to false)

**Arguments:**
- `$1`: version of jq to install (optional, defaults to latest). Example format of valid version is "1.8.1"
- `$2`: location to install jq to (optional, defaults to /usr/local/bin)
- `$3`: if set to true, skips installation if jq is already detected (optional, defaults to true)
- `$4`: the exact url to download jq from (optional, defaults to https://github.com/jqlang/jq/releases/latest/download/jq-${os}-${arch})

**Returns:**
- `0` - Success (jq installed successfully)
- `1` - Failure (installation failed)
- `2` - Failure (incorrect usage of function)

**Usage:**
```bash
install_jq "latest" "/usr/local/bin" "true"
```

<!------------------------------------------------>

</details>
<details>
<summary>is_boolean</summary>

Determine if value is a boolean.

**Arguments:**
- `$1`: value to check (required)

**Returns:**
- `0` - Success (value is a boolean - true, True, false or False)
- `1` - Failure (value is not a boolean)
- `2` - Failure (incorrect usage of function)

**Usage:**
```bash
is_boolean "true"
```
</details>

<!------------------------------------------------>

<details>
<summary>return_mac_architecture</summary>

Returns the architecture of the MacOS.

**Arguments:** n/a

**Returns:**
- `0` - Success
- `"amd64"` - if the OS is macOS and the CPU is Intel
- `"arm64"` - if the OS is macOS and the CPU is Apple Silicon
- `2` - Failure (Did not detect MacOS)

**Usage:**
```bash
arch=$(return_mac_architecture)
```
</details>

<!------------------------------------------------>

<!------------------------------------------------>

## [ibmcloud/iam](ibmcloud/iam.sh)
<details>
<summary>generate_iam_bearer_token</summary>
Expand Down
220 changes: 219 additions & 1 deletion common/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,9 @@ check_required_bins() {
done

if (( ${#missing[@]} )); then
echo "Missing binaries: ${missing[*]}" >&2
if [ "${verbose}" = true ]; then
echo "Missing binaries: ${missing[*]}" >&2
fi
return ${RETURN_CODE_ERROR}
fi

Expand All @@ -184,11 +186,178 @@ check_required_bins() {
return ${RETURN_CODE_SUCCESS}
}

#===============================================================
# FUNCTION: is_boolean
# DESCRIPTION: Determine is value is a boolean.
#
# ARGUMENTS:
# - $1: value to check (required)
#
# RETURNS:
# 0 - Success (value is a boolean - true, True, false or False)
# 1 - Failure (value is not a boolean)
# 2 - Failure (incorrect usage of function)
#
# USAGE: is_boolean <value>
#===============================================================
is_boolean() {

# Validate an arg has been provided
if [ $# -ne 1 ]; then
echo "Error: is_boolean requires exactly 1 argument, but $# were provided" >&2
echo "Usage: is_boolean <value>" >&2
exit ${RETURN_CODE_ERROR_INCORRECT_USAGE}
fi

if [[ $1 =~ ^([Tt]rue|[Ff]alse)$ ]]; then
return ${RETURN_CODE_SUCCESS}
else
return ${RETURN_CODE_ERROR}
fi
}

#===============================================================
# FUNCTION: return_mac_architecture
# DESCRIPTION: Returns the architecture of the MacOS
#
# RETURNS:
# 0 - Success
# - "amd64" - if the OS is macOS and the CPU is Intel
# - "arm64" - if the OS is macOS and the CPU is Apple Silicon
# 2 - Failure (Did not detect MacOS)
#
# USAGE: return_mac_architecture
#===============================================================
return_mac_architecture() {

local arch="arm64"
local cpu
if [[ ${OSTYPE} == 'darwin'* ]]; then
cpu="$(sysctl -a | grep machdep.cpu.brand_string)"
if [[ "${cpu}" == 'machdep.cpu.brand_string: Intel'* ]]; then
# macOS on Intel architecture
arch="amd64"
fi
else
echo "Unsupported OS: ${OSTYPE}" >&2
return ${RETURN_CODE_ERROR_INCORRECT_USAGE}
fi
echo ${arch}
}

#===============================================================
# FUNCTION: install_jq
# DESCRIPTION: Installs jq binary
#
# ENVIRONMENT VARIABLES:
# - VERBOSE: If set to true, print verbose output (optional, defaults to false)
#
# ARGUMENTS:
# - $1: version of jq to install (optional, defaults to latest). Example format of valid version is "1.8.1".
# - $2: location to install jq to (optional, defaults to /usr/local/bin)
# - $3: if set to true, skips installation if jq is already detected (optional, defaults to true)
# - $4: the exact url to download jq from (optional, defaults to https://github.com/jqlang/jq/releases/latest/download/jq-${os}-${arch})
#
# RETURNS:
# 0 - Success (jq installation successful)
# 1 - Failure (jq installation failed)
# 2 - Failure (incorrect usage of function)
#
# USAGE: install_jq "latest" "/usr/local/bin" "true"
#===============================================================
install_jq() {

local version=${1:-"latest"} # default to latest if not specified
local location=${2:-"/usr/local/bin"}
local skip_if_detected=${3:-"true"}
local link_to_binary=${4:-""}
local verbose=${VERBOSE:-false}

# Validate $3 arg is boolean
if ! is_boolean "${skip_if_detected}"; then
echo "Unsupported value detected for the 3rd argument. Only 'true' or 'false' is supported. Found: ${skip_if_detected}." >&2
return ${RETURN_CODE_ERROR_INCORRECT_USAGE}
fi

# return 0 if jq already installed and skip_if_detected is true
if [ "${skip_if_detected}" == "true" ]; then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

I guess skip_if_detected logic doesn't seem to work as expected.
if jq is not detected it should install, right?
But this logic doesn't seem to do that, it displays Missing binaries: jq and exits the script.

if check_required_bins jq; then
if [ "${verbose}" = true ]; then
echo "Found jq already installed. Taking no action."
fi
return ${RETURN_CODE_SUCCESS}
fi
fi
# ensure curl is installed
check_required_bins curl || return $?

# strip "v" prefix if it exists in version
if [[ "${version}" == "v"* ]]; then
version="${version#v}"
fi

# if no link to binary passed, determine the download link based on detected os and arch
if [ -z "${link_to_binary}" ]; then
# determine the OS and architecture
local os="linux"
local arch="amd64"
if [[ ${OSTYPE} == 'darwin'* ]]; then
arch=$(return_mac_architecture)
fi
# determine download link to binary
link_to_binary="https://github.com/jqlang/jq/releases/download/jq-${version}/jq-${os}-${arch}"
if [ "${version}" = "latest" ]; then
link_to_binary="https://github.com/jqlang/jq/releases/latest/download/jq-${os}-${arch}"
fi
fi
if [ "${verbose}" = true ]; then
echo "Using download link: ${link_to_binary}"
fi

# use sudo if needed
local arg=""
if ! [ -w "${location}" ]; then
echo "No write permission to ${location}. Using sudo..."
arg=sudo
fi

# remove if already exists
${arg} rm -f "${location}/jq"

# download binary
set +e
if ! ${arg} curl --silent \
--connect-timeout 5 \
--max-time 10 \
--retry 3 \
--retry-delay 2 \
--retry-connrefused \
--fail \
--show-error \
--location \
--output "${location}/jq" \
"${link_to_binary}"
then
echo "Failed to download ${link_to_binary}"
return ${RETURN_CODE_ERROR}
fi
set -e

# make executable
${arg} chmod +x "${location}/jq"

if [ "${verbose}" = true ]; then
echo "Successfully completed installation to ${location}/jq"
fi
return ${RETURN_CODE_SUCCESS}
}

#===============================================================
# UNIT TESTS
#===============================================================

_test() {
local make_api_calls="${MAKE_API_CALLS:-false}"
printf "%s\n\n" "Running tests.."

# check_env_vars
Expand Down Expand Up @@ -223,6 +392,55 @@ _test() {
assert_fail "${rc}"
printf "%s\n\n" "✅ PASS"

# is_boolean
# -----------------------------------
# - Test valid booleans
for i in "true" "false" "True" "False"; do
printf "%s\n" "Running 'is_boolean $i'"
rc=${RETURN_CODE_SUCCESS}
is_boolean $i >/dev/null 2>&1 || rc=$?
assert_pass "${rc}"
printf "%s\n\n" "✅ PASS"
done

# - Test non valid boolean
printf "%s\n" "Running 'is_boolean not_a_boolean'"
rc=${RETURN_CODE_SUCCESS}
is_boolean not_a_boolean >/dev/null 2>&1 || rc=$?
assert_fail "${rc}"
printf "%s\n\n" "✅ PASS"

# install_jq
# -----------------------------------
if [ "${make_api_calls}" = true ]; then
# Check if jq already exists on $PATH
local jq_installed=true
check_required_bins jq || jq_installed=false

# - Test installing jq using defaults (when it does not already exist)
if [ ${jq_installed} = false ]; then
printf "%s\n" "Running 'install_jq' (when jq does not already exists)"
rc=${RETURN_CODE_SUCCESS}
install_jq >/dev/null 2>&1 || rc=$?
assert_pass "${rc}"
printf "%s\n\n" "✅ PASS"
fi

# - Test installing it when jq already exists with default args (should be skipped)
printf "%s\n" "Running 'install_jq' (when jq already exists - install will be skipped)"
rc=${RETURN_CODE_SUCCESS}
install_jq >/dev/null 2>&1 || rc=$?
assert_pass "${rc}"
printf "%s\n\n" "✅ PASS"

# - Test installing exact version to /tmp even if jq already detected on $PATH
printf "%s\n" "Running 'install_jq 1.8.1 /tmp false'"
rc=${RETURN_CODE_SUCCESS}
install_jq "1.8.1" "/tmp" "false" >/dev/null 2>&1 || rc=$?
assert_pass "${rc}"
printf "%s\n\n" "✅ PASS"
fi

# -----------------------------------
echo "✅ All tests passed!"
}
Expand Down