Skip to content
Open
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
19 changes: 16 additions & 3 deletions .github/build/test.mk
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
##@ Testing

RESOURCE_TYPE_ROOT ?=$(shell pwd)
ENVIRONMENT ?= default
RECIPE_TYPE ?= all

.PHONY: build
build: ## Build all resource types and recipes
Expand Down Expand Up @@ -45,16 +47,27 @@ ifndef RECIPE_PATH
endif
@./.github/scripts/build-terraform-recipe.sh "$(RECIPE_PATH)"

.PHONY: register-recipe
register-recipe: ## Register a single recipe (requires RECIPE_PATH parameter)
ifndef RECIPE_PATH
$(error RECIPE_PATH parameter is required. Usage: make register-recipe RECIPE_PATH=<path-to-recipe-directory>)
endif
@./.github/scripts/register-recipe.sh "$(RECIPE_PATH)"

.PHONY: register
register: ## Register built recipes (set ENVIRONMENT and/or RECIPE_TYPE to override defaults)
@./.github/scripts/register-all-recipes.sh "$(RESOURCE_TYPE_ROOT)" "$(ENVIRONMENT)" "$(RECIPE_TYPE)"

.PHONY: test-recipe
test-recipe: ## Test a single recipe by registering and deploying it (requires RECIPE_PATH parameter)
test-recipe: ## Test a single recipe (assumes already registered, requires RECIPE_PATH parameter)
ifndef RECIPE_PATH
$(error RECIPE_PATH parameter is required. Usage: make test-recipe RECIPE_PATH=<path-to-recipe-directory>)
endif
@./.github/scripts/test-recipe.sh "$(RECIPE_PATH)"

.PHONY: test
test: ## Run all recipe tests
@./.github/scripts/test-all-recipes.sh "$(RESOURCE_TYPE_ROOT)"
test: ## Run recipe tests (assumes already registered)
@./.github/scripts/test-all-recipes.sh "$(RESOURCE_TYPE_ROOT)" "$(ENVIRONMENT)" "$(RECIPE_TYPE)"

.PHONY: list-resource-types
list-resource-types: ## List resource type folders under the specified root
Expand Down
41 changes: 41 additions & 0 deletions .github/scripts/create-cluster.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ validate_command() {
echo "Validating required dependencies..."
validate_command "k3d"
validate_command "oras"
validate_command "helm"

echo "Setting up k3d cluster..."
k3d cluster create \
Expand All @@ -47,4 +48,44 @@ k3d cluster create \
echo "Installing Radius on Kubernetes..."
rad install kubernetes --set rp.publicEndpointOverride=localhost:8081 --skip-contour-install --set dashboard.enabled=false

echo "Installing Dapr on Kubernetes..."
helm repo add dapr https://dapr.github.io/helm-charts --force-update >/dev/null 2>&1
helm repo update >/dev/null 2>&1
helm upgrade --install dapr dapr/dapr \
--namespace dapr-system \
--create-namespace \
--wait \
--set global.ha.enabled=false

echo "Configuring RBAC for Radius dynamic-rp service account (HorizontalPodAutoscaler support)..."
cat <<'EOF' | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: radius-hpa-manager
rules:
- apiGroups: ["autoscaling"]
resources: ["horizontalpodautoscalers"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
EOF

cat <<'EOF' | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: radius-hpa-manager
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: radius-hpa-manager
subjects:
- kind: ServiceAccount
name: dynamic-rp
namespace: radius-system
EOF

echo "Restarting Radius dynamic-rp deployment to pick up new permissions..."
kubectl rollout restart deployment dynamic-rp -n radius-system
kubectl rollout status deployment dynamic-rp -n radius-system --timeout=120s

echo "✅ Radius installation completed successfully"
40 changes: 26 additions & 14 deletions .github/scripts/list-recipe-folders.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
set -euo pipefail

ROOT_DIR="${1:-$(pwd)}"
FILTER_TYPE="${2:-all}"
FILTER_TYPE="$(echo "$FILTER_TYPE" | tr '[:upper:]' '[:lower:]')"

if [[ ! -d "$ROOT_DIR" ]]; then
echo "Error: Root directory '$ROOT_DIR' does not exist" >&2
Expand All @@ -40,26 +42,36 @@ fi
# Convert ROOT_DIR to an absolute path
ROOT_DIR="$(cd "$ROOT_DIR" && pwd)"

declare -A RECIPE_DIRS=()
# Validate filter type
case "$FILTER_TYPE" in
all|bicep|terraform)
;;
*)
echo "Error: Unsupported recipe type filter '$FILTER_TYPE'. Expected 'bicep', 'terraform', or 'all'." >&2
exit 1
;;
esac

find_recipe_dirs() {
local -a find_expression=("$@")
# Use a regular array and sort/uniq instead of associative array for bash 3.x compatibility
RECIPE_DIRS=()

# Find Bicep recipe directories (directories containing .bicep files under recipes/)
if [[ "$FILTER_TYPE" == "all" || "$FILTER_TYPE" == "bicep" ]]; then
while IFS= read -r -d '' matched_path; do
local dir
dir="$(dirname "$matched_path")"
RECIPE_DIRS["$dir"]=1
done < <(find "$ROOT_DIR" "${find_expression[@]}" -print0 2>/dev/null)
}

# Collect Bicep recipe directories (directories containing .bicep files under recipes/)
find_recipe_dirs -type f -path "*/recipes/*/*.bicep"
RECIPE_DIRS+=("$(dirname "$matched_path")")
done < <(find "$ROOT_DIR" -type f -path "*/recipes/*/*.bicep" -print0 2>/dev/null)
fi

# Collect Terraform recipe directories (directories containing main.tf under recipes/terraform)
find_recipe_dirs -type f -path "*/recipes/*/terraform/main.tf"
# Find Terraform recipe directories (directories containing main.tf under recipes/terraform)
if [[ "$FILTER_TYPE" == "all" || "$FILTER_TYPE" == "terraform" ]]; then
while IFS= read -r -d '' matched_path; do
RECIPE_DIRS+=("$(dirname "$matched_path")")
done < <(find "$ROOT_DIR" -type f -path "*/recipes/*/terraform/main.tf" -print0 2>/dev/null)
fi

if [[ ${#RECIPE_DIRS[@]} -eq 0 ]]; then
exit 0
fi

printf '%s\n' "${!RECIPE_DIRS[@]}" | sort
# Remove duplicates and sort
printf '%s\n' "${RECIPE_DIRS[@]}" | sort -u
102 changes: 102 additions & 0 deletions .github/scripts/register-all-recipes.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/bin/bash

# ------------------------------------------------------------
# Copyright 2025 The Radius Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ------------------------------------------------------------

# =============================================================================
# Register all Radius recipes in the repository by calling register-recipe.sh
# for each discovered recipe directory. This should be run after building all
# recipes but before testing them.
#
# Usage: ./register-all-recipes.sh [repo-root] [environment] [recipe-type]
# Example: ./register-all-recipes.sh . bicep-test bicep
# Example: ./register-all-recipes.sh . terraform-test terraform
# =============================================================================

set -euo pipefail

REPO_ROOT="${1:-$(pwd)}"
ENVIRONMENT="${2:-default}"
RECIPE_TYPE="${3:-all}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

echo "==> Finding $RECIPE_TYPE recipes in $REPO_ROOT for environment $ENVIRONMENT"

# Use while read loop for better compatibility (mapfile requires bash 4+)
RECIPE_DIRS=()
while IFS= read -r line; do
# Filter by recipe type if specified
if [[ "$RECIPE_TYPE" == "all" ]]; then
RECIPE_DIRS+=("$line")
elif [[ "$RECIPE_TYPE" == "bicep" ]] && [[ "$line" == *"/bicep" ]] && ls "$line"/*.bicep &>/dev/null; then
RECIPE_DIRS+=("$line")
elif [[ "$RECIPE_TYPE" == "terraform" ]] && [[ "$line" == *"/terraform" ]] && [[ -f "$line/main.tf" ]]; then
RECIPE_DIRS+=("$line")
fi
done < <("$SCRIPT_DIR"/list-recipe-folders.sh "$REPO_ROOT" "$RECIPE_TYPE")

if [[ ${#RECIPE_DIRS[@]} -eq 0 ]]; then
echo "==> No $RECIPE_TYPE recipes found"
exit 0
fi

echo "==> Found ${#RECIPE_DIRS[@]} $RECIPE_TYPE recipe(s) to register"

FAILED_RECIPES=()
PASSED_RECIPES=()

# Register each recipe
for recipe_dir in "${RECIPE_DIRS[@]}"; do
# Convert to relative path for cleaner output
RELATIVE_PATH="${recipe_dir#$REPO_ROOT/}"
echo ""
echo "================================================"
echo "Registering: $RELATIVE_PATH"
echo "================================================"

if ./.github/scripts/register-recipe.sh "$recipe_dir" "$ENVIRONMENT"; then
PASSED_RECIPES+=("$RELATIVE_PATH")
else
FAILED_RECIPES+=("$RELATIVE_PATH")
fi
done

# Print summary
echo ""
echo "================================================"
echo "Registration Summary"
echo "================================================"
echo "Passed: ${#PASSED_RECIPES[@]}"
echo "Failed: ${#FAILED_RECIPES[@]}"

if [[ ${#FAILED_RECIPES[@]} -gt 0 ]]; then
echo ""
echo "Failed recipe registrations:"
for recipe in "${FAILED_RECIPES[@]}"; do
echo " - $recipe"
done
exit 1
fi

echo ""
echo "==> All recipes registered successfully!"

# Log all registered recipes
echo ""
echo "================================================"
echo "Currently Registered Recipes"
echo "================================================"
rad recipe list --environment "$ENVIRONMENT" || echo "Warning: Could not list registered recipes"
107 changes: 107 additions & 0 deletions .github/scripts/register-recipe.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/bin/bash

# ------------------------------------------------------------
# Copyright 2025 The Radius Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ------------------------------------------------------------

# =============================================================================
# Register a single Radius recipe. Automatically detects whether the recipe
# is Bicep or Terraform and registers it with the appropriate template path.
#
# Usage: ./register-recipe.sh <path-to-recipe-directory>
# Example: ./register-recipe.sh Security/secrets/recipes/kubernetes/bicep
# =============================================================================

set -euo pipefail

RECIPE_PATH="${1:-}"

if [[ -z "$RECIPE_PATH" ]]; then
echo "Error: Recipe path is required"
echo "Usage: $0 <path-to-recipe-directory>"
exit 1
fi

if [[ ! -d "$RECIPE_PATH" ]]; then
echo "Error: Recipe directory not found: $RECIPE_PATH"
exit 1
fi

# Normalize path: convert absolute to relative for consistency
RECIPE_PATH="$(realpath --relative-to="$(pwd)" "$RECIPE_PATH" 2>/dev/null || echo "$RECIPE_PATH")"
RECIPE_PATH="${RECIPE_PATH#./}"

# Detect recipe type based on file presence
if [[ -f "$RECIPE_PATH/main.tf" ]]; then
RECIPE_TYPE="terraform"
TEMPLATE_KIND="terraform"
elif ls "$RECIPE_PATH"/*.bicep &>/dev/null; then
RECIPE_TYPE="bicep"
TEMPLATE_KIND="bicep"
else
echo "Error: Could not detect recipe type in $RECIPE_PATH"
exit 1
fi

echo "==> Registering $RECIPE_TYPE recipe at $RECIPE_PATH"

# Extract resource type from path (e.g., Security/secrets -> Radius.Security/secrets)
RESOURCE_TYPE_PATH=$(echo "$RECIPE_PATH" | sed -E 's|/recipes/.*||')
CATEGORY=$(basename "$(dirname "$RESOURCE_TYPE_PATH")")
RESOURCE_NAME=$(basename "$RESOURCE_TYPE_PATH")
RESOURCE_TYPE="Radius.$CATEGORY/$RESOURCE_NAME"

echo "==> Resource type: $RESOURCE_TYPE"

# Determine template path based on recipe type
if [[ "$RECIPE_TYPE" == "bicep" ]]; then
# For Bicep, use OCI registry path (match build-bicep-recipe.sh format)
# Path format: localhost:5000/radius-recipes/{category}/{resourcename}/{platform}/{language}/{recipe-filename}
# Find the .bicep file in the recipe directory
BICEP_FILE=$(ls "$RECIPE_PATH"/*.bicep 2>/dev/null | head -n 1)
RECIPE_FILENAME=$(basename "$BICEP_FILE" .bicep)
RECIPE_NAME="$RECIPE_FILENAME"

# Extract platform and language from path (e.g., recipes/kubernetes/bicep -> kubernetes/bicep)
RECIPES_SUBPATH="${RECIPE_PATH#*recipes/}"

# Build OCI path (use reciperegistry for in-cluster access)
# Note: Build script pushes to localhost:5000 (which is port-forwarded to reciperegistry)
# But Radius running in-cluster needs to pull from reciperegistry:5000
CATEGORY_LOWER=$(echo "$CATEGORY" | tr '[:upper:]' '[:lower:]')
RESOURCE_LOWER=$(echo "$RESOURCE_NAME" | tr '[:upper:]' '[:lower:]')
TEMPLATE_PATH="reciperegistry:5000/radius-recipes/${CATEGORY_LOWER}/${RESOURCE_LOWER}/${RECIPES_SUBPATH}/${RECIPE_FILENAME}:latest"
elif [[ "$RECIPE_TYPE" == "terraform" ]]; then
# For Terraform, use HTTP module server with format: resourcename-platform.zip
PLATFORM=$(basename "$(dirname "$RECIPE_PATH")")
RECIPE_NAME="${RESOURCE_NAME}-${PLATFORM}"
TEMPLATE_PATH="http://tf-module-server.radius-test-tf-module-server.svc.cluster.local/${RECIPE_NAME}.zip"
fi

echo "==> Registering recipe: $RECIPE_NAME"
echo "==> Template path: $TEMPLATE_PATH"

rad recipe register default \
--environment default \
--resource-type "$RESOURCE_TYPE" \
--template-kind "$TEMPLATE_KIND" \
--template-path "$TEMPLATE_PATH" \
--plain-http

echo "==> Recipe registered successfully"

# Log the registered recipe details
echo "==> Verifying registration..."
rad recipe show default --resource-type "$RESOURCE_TYPE" --environment default || echo "Warning: Could not verify recipe registration"
Loading