-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Per Goncalves da Silva <[email protected]>
- Loading branch information
Per Goncalves da Silva
committed
Aug 24, 2024
1 parent
d2241b0
commit c706ebc
Showing
10 changed files
with
841 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
#!/usr/bin/env bash | ||
|
||
# Get the directory of the current script | ||
SCRIPT_ROOT=$(dirname "$(realpath "$0")") | ||
|
||
source "${SCRIPT_ROOT}/lib/unpack.sh" | ||
source "${SCRIPT_ROOT}/lib/collect-rbac.sh" | ||
|
||
# Set the container runtime, default to docker | ||
CONTAINER_RUNTIME=${CONTAINER_RUNTIME:-docker} | ||
|
||
function usage() { | ||
script_name=$(basename "$0") | ||
echo "Usage:" | ||
echo "./${script_name} install <package-name> <package-version> [-n namespace] [-e cluster-extension-name] [-cr cluster-role-name] [-r role-name] [-s service-account-name] [--use-defaults]" | ||
echo "./${script_name} rbac <package-name> <package-version> [-n namespace] [-e cluster-extension-name] [-cr cluster-role-name] [-r role-name] [-s service-account-name] [--use-defaults]" | ||
echo "" | ||
echo "Note: If --use-defaults is not set, the unset optional parameters will appear as template variables in the resulting manifests, i.e.:" | ||
echo "\${NAMESPACE}, \${EXTENSION_NAME}, \${CLUSTER_ROLE_NAME}, \${ROLE_NAME}, \${SERVICE_ACCOUNT_NAME}." | ||
echo "If --use-defaults is set, the defaults will be applied only to optional parameters that are not set." | ||
echo "Defaults: cluster-extension-name => <package-name>, namespace => <cluster-extension-name>-system, " | ||
echo "service-account => <package-name>-installer, cluster role => <service-account>-cluster-role," | ||
echo "role => <service-account>-installer-role." | ||
echo "NOTE: The role and cluster-role bindings always follow the format <[cluster-]role-name>-binding." | ||
} | ||
|
||
# Check for at least 3 arguments | ||
if [ "$#" -lt 3 ]; then | ||
usage | ||
exit 1 | ||
fi | ||
|
||
# Command and package details | ||
COMMAND=$1 | ||
export PACKAGE_NAME=$2 | ||
export PACKAGE_VERSION=$3 | ||
|
||
# Initialize environment variables with template defaults | ||
export NAMESPACE="\${NAMESPACE}" | ||
export EXTENSION_NAME="\${EXTENSION-NAME}" | ||
export CLUSTER_ROLE_NAME="\${CLUSTER_ROLE_NAME}" | ||
export ROLE_NAME="\${ROLE_NAME}" | ||
export SERVICE_ACCOUNT_NAME="\${SERVICE_ACCOUNT_NAME}" | ||
use_defaults=false | ||
|
||
# Parse optional arguments | ||
shift 3 | ||
while [[ $# -gt 0 ]]; do | ||
key="$1" | ||
|
||
case $key in | ||
-n) | ||
export NAMESPACE="$2" | ||
shift 2 | ||
;; | ||
-e) | ||
export EXTENSION_NAME="$2" | ||
shift 2 | ||
;; | ||
-cr) | ||
export CLUSTER_ROLE_NAME="$2" | ||
shift 2 | ||
;; | ||
-r) | ||
export ROLE_NAME="$2" | ||
shift 2 | ||
;; | ||
-s) | ||
export SERVICE_ACCOUNT_NAME="$2" | ||
shift 2 | ||
;; | ||
--use-defaults) | ||
use_defaults=true | ||
shift | ||
;; | ||
*) | ||
echo "Unknown option $1" | ||
usage | ||
exit 1 | ||
;; | ||
esac | ||
done | ||
|
||
# Apply default values only to unset parameters if --use-defaults is set | ||
if [ "$use_defaults" = true ]; then | ||
[ "$EXTENSION_NAME" == "\${EXTENSION-NAME}" ] && export EXTENSION_NAME="${PACKAGE_NAME}" | ||
[ "$NAMESPACE" == "\${NAMESPACE}" ] && export NAMESPACE="${EXTENSION_NAME}-system" | ||
[ "$SERVICE_ACCOUNT_NAME" == "\${SERVICE_ACCOUNT_NAME}" ] && export SERVICE_ACCOUNT_NAME="${PACKAGE_NAME}-installer" | ||
[ "$CLUSTER_ROLE_NAME" == "\${CLUSTER_ROLE_NAME}" ] && export CLUSTER_ROLE_NAME="${SERVICE_ACCOUNT_NAME}-cluster-role" | ||
[ "$ROLE_NAME" == "\${ROLE_NAME}" ] && export ROLE_NAME="${SERVICE_ACCOUNT_NAME}-installer-role" | ||
fi | ||
|
||
# Output the set environment variables for confirmation | ||
debug "Environment variables set:" | ||
debug "NAMESPACE=${NAMESPACE}" | ||
debug "EXTENSION_NAME=${EXTENSION_NAME}" | ||
debug "CLUSTER_ROLE_NAME=${CLUSTER_ROLE_NAME}" | ||
debug "ROLE_NAME=${ROLE_NAME}" | ||
debug "SERVICE_ACCOUNT_NAME=${SERVICE_ACCOUNT_NAME}" | ||
|
||
# Find bundle image | ||
image="$(cat - | get-bundle-image "${PACKAGE_NAME}" "${PACKAGE_VERSION}")" | ||
|
||
# Unpack and close container | ||
bundle_manifest_dir="$(unpack "$(create_container "${image}")")" | ||
|
||
# Derive rbac from bundle manifests | ||
collect_installer_rbac "${bundle_manifest_dir}" | ||
|
||
# Example output or further processing based on command | ||
case "${COMMAND}" in | ||
install) | ||
generate_install_manifests | envsubst | ||
;; | ||
rbac) | ||
generate_rbac_manifests | envsubst | ||
;; | ||
*) | ||
echo "Unknown command $command" | ||
usage | ||
exit 1 | ||
;; | ||
esac | ||
|
||
# Clean up manifest directory | ||
rm -rf "${bundle_manifest_dir}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
#!/bin/bash | ||
|
||
# Constants | ||
SERVICE_NAMESPACE="olmv1-system" | ||
SERVICE_NAME="catalogd-catalogserver" | ||
LOCAL_PORT=8001 | ||
SERVICE_PORT=443 # Assuming the service uses HTTPS on port 443 | ||
|
||
# Function to display usage | ||
usage() { | ||
echo "Usage: $0 <catalog-name>" | ||
exit 1 | ||
} | ||
|
||
# Check if catalog name is provided | ||
if [ -z "$1" ]; then | ||
usage | ||
fi | ||
|
||
CATALOG_NAME="$1" | ||
|
||
# Check if the clustercatalog resource exists | ||
echo "Checking if ClusterCatalog $CATALOG_NAME exists..." | ||
CLUSTER_CATALOG=$(kubectl get clustercatalog "$CATALOG_NAME" -o json 2>/dev/null) | ||
if [ -z "$CLUSTER_CATALOG" ]; then | ||
echo "ClusterCatalog $CATALOG_NAME does not exist." | ||
exit 1 | ||
fi | ||
|
||
# Check if the Unpacked condition is true | ||
UNPACKED_CONDITION=$(echo "$CLUSTER_CATALOG" | jq -r '.status.conditions[] | select(.type=="Unpacked") | .status') | ||
if [ "$UNPACKED_CONDITION" != "True" ]; then | ||
echo "ClusterCatalog $CATALOG_NAME is not unpacked yet." | ||
exit 1 | ||
fi | ||
|
||
# Get the contentURL | ||
CONTENT_URL=$(echo "$CLUSTER_CATALOG" | jq -r '.status.contentURL') | ||
if [ -z "$CONTENT_URL" ]; then | ||
echo "Content URL not found for ClusterCatalog $CATALOG_NAME." | ||
exit 1 | ||
fi | ||
|
||
# Start port forwarding | ||
echo "Starting kubectl port-forward to $SERVICE_NAME on port $LOCAL_PORT..." | ||
kubectl port-forward -n "$SERVICE_NAMESPACE" svc/"$SERVICE_NAME" $LOCAL_PORT:$SERVICE_PORT &>/dev/null & | ||
PORT_FORWARD_PID=$! | ||
sleep 2 # Wait for the port-forwarding to start | ||
|
||
# Modify the contentURL to hit localhost:<port> | ||
LOCAL_CONTENT_URL=$(echo "$CONTENT_URL" | sed "s|https://[^/]*|https://localhost:$LOCAL_PORT|") | ||
|
||
# Download the catalog using wget | ||
echo "Downloading catalog from $LOCAL_CONTENT_URL..." | ||
wget --no-check-certificate "$LOCAL_CONTENT_URL" -O "${CATALOG_NAME}-catalog.json" | ||
|
||
# Stop the port forwarding | ||
echo "Stopping kubectl port-forward..." | ||
kill $PORT_FORWARD_PID | ||
|
||
echo "Catalog downloaded to ${CATALOG_NAME}-catalog.json" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
source "${SCRIPT_ROOT}/lib/hash.sh" | ||
|
||
# Given package and version grabs the bundle image from stdin FBC stream | ||
function get-bundle-image(){ | ||
local package_name="${1}" | ||
local package_version="${2}" | ||
local image=$(jq -r --arg pkg "$package_name" --arg ver "$package_version" \ | ||
'select(.schema == "olm.bundle" and (.properties[] | select(.type == "olm.package" and .value.packageName == $pkg and .value.version == $ver))) | .image') | ||
|
||
if [ -z "$image" ]; then | ||
echo "No matching image found for package '$package_name' with version '$package_version'." | ||
exit 1 | ||
fi | ||
|
||
echo "${image}" | ||
} | ||
|
||
# Function to validate the bundle is supported | ||
function check-bundle-supported() { | ||
local csv="${1}" | ||
local valid=$(yq eval ' | ||
(.spec.installModes[] | select(.type == "AllNamespaces" and .supported == true)) and | ||
((.spec.webhookdefinitions == null) or (.spec.webhookdefinitions | length == 0)) and | ||
((.spec.customresourcedefinitions.required == null) or (.spec.customresourcedefinitions.required | length == 0)) | ||
' "${csv}") | ||
|
||
# Check if the result is 'true' | ||
if [ "$valid" != "true" ]; then | ||
echo "Bundles with dependencies, or that don't support AllNamespaces mode, or with webhookdefinitions, are not supported." | ||
exit 1 | ||
fi | ||
|
||
} | ||
|
||
# Function to get all resource names for a particular kind | ||
# from the manifest directory | ||
function collect_resource_names() { | ||
local manifest_dir="${1}" | ||
local kind="${2}" | ||
local resource_names=() | ||
while IFS= read -r resource_file; do | ||
name=$(yq eval -r '.metadata.name' "$resource_file") | ||
if [ -n "$name" ]; then | ||
resource_names+=("$name") | ||
fi | ||
done < <(find "${manifest_dir}" -type f -exec grep -l "^kind: ${kind}" {} \;) | ||
echo "${resource_names[@]}" | ||
} | ||
|
||
# Function that collects all the rules for all the ClusterRole manifests | ||
# shipped with the bundle | ||
function collect_manifest_cluster_role_perms() { | ||
local manifest_dir="${1}" | ||
local kind="ClusterRole" | ||
local all_cr_rules="[]" | ||
|
||
while IFS= read -r resource_file; do | ||
# Extract the entire rules array from the current file and ensure it's treated as a valid JSON array | ||
cr_rules=$(yq eval -o=json -r '.rules // []' "$resource_file") | ||
# Validate and merge the current rules array with the cumulative rules array | ||
if jq -e . >/dev/null 2>&1 <<<"$cr_rules"; then | ||
all_cr_rules=$(jq -c --argjson existing "$all_cr_rules" --argjson new "$cr_rules" '$existing + $new' <<<"$all_cr_rules") | ||
fi | ||
done < <(find "${manifest_dir}" -type f -exec grep -l "^kind: ${kind}" {} \;) | ||
echo "$all_cr_rules" | ||
} | ||
|
||
# Function that collects all the rules for all the Role manifests | ||
# shipped with the bundle | ||
function collect_manifest_role_perms() { | ||
local manifest_dir="${1}" | ||
local kind="Role" | ||
local all_cr_rules="[]" | ||
|
||
while IFS= read -r resource_file; do | ||
# Extract the entire rules array from the current file and ensure it's treated as a valid JSON array | ||
cr_rules=$(yq eval -o=json -r '.rules // []' "$resource_file") | ||
# Validate and merge the current rules array with the cumulative rules array | ||
if jq -e . >/dev/null 2>&1 <<<"$cr_rules"; then | ||
all_cr_rules=$(jq -c --argjson existing "$all_cr_rules" --argjson new "$cr_rules" '$existing + $new' <<<"$all_cr_rules") | ||
fi | ||
done < <(find "${manifest_dir}" -type f -exec grep -l "^kind: ${kind}" {} \;) | ||
echo "$all_cr_rules" | ||
} | ||
|
||
# Function to get the apiGroup for a named resource of a given kind | ||
# from the manifests dir | ||
function get_api_group() { | ||
local dir_path="$1" | ||
local kind="$2" | ||
local name="$3" | ||
|
||
# Find the file containing the specified kind and name | ||
local file=$(grep -rl "kind: $kind" "$dir_path" | xargs grep -l "name: $name") | ||
|
||
# Extract the apiGroup from the found file | ||
if [ -n "$file" ]; then | ||
local api_group=$(yq eval '.apiVersion' "$file" | awk -F'/' '{print $1}') | ||
echo "$api_group" | ||
fi | ||
} | ||
|
||
# Function to get the generated clusterrole resource names | ||
function generated_cluster_role_names() { | ||
local csvFile="${1}" | ||
local generated_cluster_role_names=() | ||
csv_name=$(yq eval -r '.metadata.name' "${csvFile}") | ||
cperms=$(yq eval -o=json -r '.spec.install.spec.clusterPermissions?' "$csvFile" | jq -c '.[] | {serviceAccountName, rules: [.rules[] | {verbs, apiGroups, resources, resourceNames, nonResourceURLs} | with_entries(select(.value != null and .value != []))]}') | ||
rbacPerms=$(yq eval -o=json -r '.spec.install.spec.permissions?' "$csvFile" | jq -c '.[] | {serviceAccountName, rules: [.rules[] | {verbs, apiGroups, resources, resourceNames, nonResourceURLs} | with_entries(select(.value != null and .value != []))]}') | ||
allPerms=("${cperms[@]}" "${rbacPerms[@]}") | ||
for perm in ${allPerms[@]}; do | ||
local sa=$(echo $perm | yq eval -r '.serviceAccountName') | ||
local generated_name=$(generate_name "${csv_name}-${sa}" "${perm}") | ||
generated_cluster_role_names+=("${generated_name}") | ||
done | ||
echo "${generated_cluster_role_names[@]}" | ||
} |
Oops, something went wrong.