Skip to content
Draft
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
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,11 @@ test-scale-dnspolicy: kube-burner ## Run DNSPolicy scale tests.
cd scale_test/dnspolicy && $(KUBE_BURNER) init -c ${KUBEBURNER_WORKLOAD} --log-level debug


# Include local environment setup modules
# Load variables first, then all other modules
include ./make/vars.mk
include $(filter-out ./make/vars.mk,$(wildcard ./make/*.mk))

##@ Build Dependencies

## Location to install dependencies to
Expand Down
53 changes: 53 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,59 @@ make poetry
> - [Kuadrant Helm Charts](https://github.com/Kuadrant/helm-charts) for any Kubernetes cluster
> - [Deploying Kuadrant via OLM](https://github.com/Kuadrant/helm-charts-olm/blob/main/README.md) for OpenShift (recommended as it also deploys testing tools)

## Local Kind Cluster Setup

For local development and testing, you can set up a complete Kuadrant environment using Kind (Kubernetes in Docker).

### Prerequisites
* [Kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation)
* [Helm](https://helm.sh/docs/intro/install/)
* [jq](https://jqlang.github.io/jq/download/) (JSON processor)
* **Red Hat Registry credentials** (optional but recommended for testing tools)
- Username: Your Red Hat account username
- Password: Your Red Hat registry token (from [console.redhat.com/openshift/downloads](https://console.redhat.com/openshift/downloads))
- **Note:** Without these credentials, testing tools (Keycloak, Mockserver, etc.) won't be deployed, but core Kuadrant functionality will still work

### Quick Start

Set up a complete local environment with one command:

```bash
# Optional: Red Hat registry credentials (for testing tools like Keycloak)
# (if not provided, tools won't be deployed but core functionality will work)
export RH_REGISTRY_USERNAME=<your-username>
export RH_REGISTRY_PASSWORD=<your-token>

# Optional: AWS credentials for DNS testing
# (if not provided, the secret won't be created and DNS tests will be skipped)
export AWS_ACCESS_KEY_ID=<your-aws-key>
export AWS_SECRET_ACCESS_KEY=<your-aws-secret>
export AWS_REGION=us-east-1
export AWS_BASE_DOMAIN=test.example.com

# Run the setup (defaults to Istio gateway)
make local-setup

# Or specify EnvoyGateway
GATEWAYAPI_PROVIDER=envoygateway make local-setup
```

This will:
1. Create a Kind cluster named `kuadrant-local`
2. Install metrics-server and MetalLB (LoadBalancer support)
3. Install Gateway API CRDs
4. Install cert-manager and create a self-signed ClusterIssuer
5. Install Istio or EnvoyGateway (based on `GATEWAYAPI_PROVIDER`)
6. Create test namespaces (`kuadrant`, `kuadrant2`)
7. Create AWS credentials secret (only if AWS credentials are provided)
8. Deploy Kuadrant Operator and Kuadrant CR
9. Deploy testing tools (only if RH_REGISTRY credentials are provided) - Keycloak, Mockserver, etc.

**Cleanup:**
```bash
make local-cleanup # Delete the Kind cluster
```

## Configuration

The Kuadrant testsuite uses [Dynaconf](https://www.dynaconf.com/) for configuration.
Expand Down
86 changes: 86 additions & 0 deletions make/dependencies.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@

##@ Core Dependencies

.PHONY: install-metrics-server
install-metrics-server: ## Install metrics-server
@echo "Installing metrics-server..."
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
kubectl patch deployment metrics-server -n kube-system --type=json -p '[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-insecure-tls"}]'
@echo "metrics-server installed"

.PHONY: install-metallb
install-metallb: ## Install MetalLB for LoadBalancer services
@echo "Installing MetalLB $(METALLB_VERSION)..."
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/$(METALLB_VERSION)/config/manifests/metallb-native.yaml
kubectl wait --namespace metallb-system --for=condition=Available deployment/controller --timeout=$(METALLB_TIMEOUT)
kubectl wait --namespace metallb-system --for=condition=ready pod --selector=component=controller --timeout=$(METALLB_TIMEOUT)
@echo "Configuring MetalLB IP pool..."
@printf '%s\n' \
'apiVersion: metallb.io/v1beta1' \
'kind: IPAddressPool' \
'metadata:' \
' name: default' \
' namespace: metallb-system' \
'spec:' \
' addresses:' \
' - 172.18.255.200-172.18.255.250' \
| kubectl apply -f -
@printf '%s\n' \
'apiVersion: metallb.io/v1beta1' \
'kind: L2Advertisement' \
'metadata:' \
' name: default' \
' namespace: metallb-system' \
| kubectl apply -f -
@echo "MetalLB installed with IP pool 172.18.255.200-172.18.255.250"

.PHONY: gateway-api-install
gateway-api-install: ## Install Gateway API CRDs
@echo "Installing Gateway API $(GATEWAY_API_VERSION)..."
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/$(GATEWAY_API_VERSION)/standard-install.yaml
@echo "Gateway API CRDs installed"

.PHONY: install-cert-manager
install-cert-manager: ## Install cert-manager
@echo "Installing cert-manager $(CERT_MANAGER_VERSION)..."
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/$(CERT_MANAGER_VERSION)/cert-manager.yaml
kubectl wait --namespace cert-manager --for=condition=Available deployment/cert-manager --timeout=$(CERT_MANAGER_TIMEOUT)
kubectl wait --namespace cert-manager --for=condition=Available deployment/cert-manager-webhook --timeout=$(CERT_MANAGER_TIMEOUT)
kubectl wait --namespace cert-manager --for=condition=ready pod --selector=app.kubernetes.io/name=webhook --timeout=$(CERT_MANAGER_TIMEOUT)
@echo "cert-manager installed"

.PHONY: create-cluster-issuer
create-cluster-issuer: ## Create self-signed ClusterIssuer for TLS testing
@echo "Creating self-signed ClusterIssuer..."
@printf '%s\n' \
'apiVersion: cert-manager.io/v1' \
'kind: ClusterIssuer' \
'metadata:' \
' name: kuadrant-qe-issuer' \
'spec:' \
' selfSigned: {}' \
| kubectl apply -f -
@echo "ClusterIssuer 'kuadrant-qe-issuer' created"

.PHONY: create-aws-credentials
create-aws-credentials: ## Create AWS credentials secret for DNS testing (only if credentials provided)
@if [ -n "$(AWS_ACCESS_KEY_ID)" ] && [ -n "$(AWS_SECRET_ACCESS_KEY)" ] && [ -n "$(AWS_REGION)" ] && [ -n "$(AWS_BASE_DOMAIN)" ]; then \
echo "Creating AWS credentials secret..."; \
printf '%s\n' \
'apiVersion: v1' \
'kind: Secret' \
'metadata:' \
' name: aws-credentials' \
' namespace: kuadrant' \
' annotations:' \
' base_domain: $(AWS_BASE_DOMAIN)' \
'stringData:' \
' AWS_ACCESS_KEY_ID: $(AWS_ACCESS_KEY_ID)' \
' AWS_REGION: $(AWS_REGION)' \
' AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY)' \
'type: kuadrant.io/aws' \
| kubectl apply -f -; \
echo "AWS credentials secret created in kuadrant namespace"; \
else \
echo "⏭️ Skipping AWS credentials secret (requires AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, and AWS_BASE_DOMAIN)"; \
fi
11 changes: 11 additions & 0 deletions make/envoygateway.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

##@ EnvoyGateway

.PHONY: envoygateway-install
envoygateway-install: ## Install EnvoyGateway
@echo "Installing EnvoyGateway..."
helm install eg oci://docker.io/envoyproxy/gateway-helm --version $(ENVOYGATEWAY_VERSION) \
--create-namespace \
--namespace envoy-gateway-system \
--wait
@echo "EnvoyGateway installed"
30 changes: 30 additions & 0 deletions make/istio.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

##@ Istio

.PHONY: istio-install
istio-install: ## Install Istio via SAIL operator
@echo "Installing Sail Operator $(SAIL_OPERATOR_VERSION)..."
helm repo add sail-operator https://istio-ecosystem.github.io/sail-operator --force-update
helm install sail-operator \
--create-namespace \
--namespace istio-system \
--wait \
--timeout=$(HELM_TIMEOUT) \
sail-operator/sail-operator \
--version $(SAIL_OPERATOR_VERSION)
@echo "Creating Istio CR..."
@printf '%s\n' \
'apiVersion: sailoperator.io/v1' \
'kind: Istio' \
'metadata:' \
' name: default' \
'spec:' \
' namespace: istio-system' \
' updateStrategy:' \
' type: InPlace' \
' values:' \
' pilot:' \
' autoscaleMin: 2' \
' version: $(ISTIO_VERSION)' \
| kubectl apply -f -
@echo "Istio $(ISTIO_VERSION) installed via SAIL"
12 changes: 12 additions & 0 deletions make/kind.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

##@ Kind Cluster

.PHONY: kind-create-cluster
kind-create-cluster: ## Create kind cluster
@echo "Creating kind cluster '$(KIND_CLUSTER_NAME)'..."
@kind create cluster --name $(KIND_CLUSTER_NAME) || echo "Cluster already exists"

.PHONY: kind-delete-cluster
kind-delete-cluster: ## Delete kind cluster
@echo "Deleting kind cluster '$(KIND_CLUSTER_NAME)'..."
@kind delete cluster --name $(KIND_CLUSTER_NAME) || true
87 changes: 87 additions & 0 deletions make/kuadrant.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@

##@ Kuadrant

.PHONY: create-test-namespaces
create-test-namespaces: ## Create namespaces for testing
@echo "Creating test namespaces..."
kubectl create namespace kuadrant || true
kubectl create namespace kuadrant2 || true
@echo "Test namespaces created"

.PHONY: deploy-kuadrant-operator
deploy-kuadrant-operator: ## Deploy Kuadrant Operator (via Helm by default, or custom image)
ifneq ($(KUADRANT_OPERATOR_IMAGE),)
@echo "Installing Kuadrant Operator from custom image: $(KUADRANT_OPERATOR_IMAGE)"
$(MAKE) deploy-kuadrant-operator-local
else
@echo "Installing Kuadrant Operator $(KUADRANT_OPERATOR_VERSION) from Helm..."
helm repo add kuadrant https://kuadrant.io/helm-charts/ --force-update
$(if $(filter latest,$(KUADRANT_OPERATOR_VERSION)), \
helm install kuadrant-operator kuadrant/kuadrant-operator --create-namespace --namespace $(KUADRANT_NAMESPACE), \
helm install kuadrant-operator kuadrant/kuadrant-operator --version $(KUADRANT_OPERATOR_VERSION) --create-namespace --namespace $(KUADRANT_NAMESPACE))
kubectl -n $(KUADRANT_NAMESPACE) wait --timeout=$(KUBECTL_TIMEOUT) --for=condition=Available deployments --all
$(MAKE) patch-kuadrant-operator-env
@echo "Kuadrant Operator $(KUADRANT_OPERATOR_VERSION) installed"
endif

.PHONY: deploy-kuadrant-operator-local
deploy-kuadrant-operator-local: ## Deploy Kuadrant Operator from local build/image
@if [ -z "$(KUADRANT_OPERATOR_IMAGE)" ]; then \
echo "ERROR: KUADRANT_OPERATOR_IMAGE not set"; \
echo "Set KUADRANT_OPERATOR_IMAGE=your-image:tag"; \
exit 1; \
fi
@echo "Loading image into kind cluster..."
kind load docker-image $(KUADRANT_OPERATOR_IMAGE) --name $(KIND_CLUSTER_NAME)
@echo "Deploying operator with image $(KUADRANT_OPERATOR_IMAGE)..."
kubectl create namespace $(KUADRANT_NAMESPACE) || true
kubectl apply -k https://github.com/kuadrant/kuadrant-operator/config/crd
@if [ ! -d "/tmp/kuadrant-operator-deploy" ]; then \
cd /tmp && git clone --depth=1 https://github.com/kuadrant/kuadrant-operator.git kuadrant-operator-deploy; \
else \
cd /tmp/kuadrant-operator-deploy && git pull; \
fi
cd /tmp/kuadrant-operator-deploy/config/manager && \
kustomize edit set image controller=$(KUADRANT_OPERATOR_IMAGE) && \
kustomize build ../deploy | kubectl apply --server-side -f -
kubectl -n $(KUADRANT_NAMESPACE) wait --timeout=$(KUBECTL_TIMEOUT) --for=condition=Available deployments --all
$(MAKE) patch-kuadrant-operator-env
@echo "Kuadrant Operator deployed from image $(KUADRANT_OPERATOR_IMAGE)"

.PHONY: patch-kuadrant-operator-env
patch-kuadrant-operator-env: ## Patch Kuadrant Operator deployment with custom env vars
ifneq ($(KUADRANT_OPERATOR_ENV_VARS),)
@echo "Patching Kuadrant Operator with environment variables..."
@EXISTING_ENV=$$(kubectl get deployment kuadrant-operator-controller-manager -n $(KUADRANT_NAMESPACE) -o jsonpath='{.spec.template.spec.containers[0].env}'); \
NEW_ENV='['; \
IFS=',' read -ra PAIRS <<< "$(KUADRANT_OPERATOR_ENV_VARS)"; \
for i in "$${!PAIRS[@]}"; do \
PAIR="$${PAIRS[$$i]}"; \
NAME=$$(echo "$$PAIR" | cut -d'=' -f1); \
VALUE=$$(echo "$$PAIR" | cut -d'=' -f2-); \
[ $$i -gt 0 ] && NEW_ENV="$$NEW_ENV,"; \
NEW_ENV="$$NEW_ENV{\"name\":\"$$NAME\",\"value\":\"$$VALUE\"}"; \
done; \
NEW_ENV="$$NEW_ENV]"; \
MERGED_ENV=$$(echo "$$EXISTING_ENV$$NEW_ENV" | jq -s '.[0] + .[1] | unique_by(.name)'); \
kubectl patch deployment kuadrant-operator-controller-manager -n $(KUADRANT_NAMESPACE) \
--type=json -p="[{\"op\":\"replace\",\"path\":\"/spec/template/spec/containers/0/env\",\"value\":$$MERGED_ENV}]"; \
kubectl -n $(KUADRANT_NAMESPACE) rollout status deployment/kuadrant-operator-controller-manager --timeout=$(KUBECTL_TIMEOUT)
@echo "Kuadrant Operator patched with env vars"
else
@echo "No custom env vars specified (KUADRANT_OPERATOR_ENV_VARS not set)"
endif

.PHONY: deploy-kuadrant-cr
deploy-kuadrant-cr: ## Deploy Kuadrant CR
@echo "Creating Kuadrant CR..."
@printf '%s\n' \
'apiVersion: kuadrant.io/v1beta1' \
'kind: Kuadrant' \
'metadata:' \
' name: kuadrant-sample' \
' namespace: $(KUADRANT_NAMESPACE)' \
'spec: {}' \
| kubectl apply -f -
kubectl wait kuadrant/kuadrant-sample --for=condition=Ready=True -n $(KUADRANT_NAMESPACE) --timeout=$(KUADRANT_CR_TIMEOUT)
@echo "Kuadrant CR ready"
34 changes: 34 additions & 0 deletions make/local-setup.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

##@ Local Environment Setup

.PHONY: local-setup
local-setup: ## Complete local environment setup (kind cluster + all dependencies)
@# Validate GATEWAYAPI_PROVIDER
@if [ "$(GATEWAYAPI_PROVIDER)" != "istio" ] && [ "$(GATEWAYAPI_PROVIDER)" != "envoygateway" ]; then \
echo "ERROR: Invalid GATEWAYAPI_PROVIDER='$(GATEWAYAPI_PROVIDER)'"; \
echo "Valid values: istio, envoygateway"; \
exit 1; \
fi
$(MAKE) kind-delete-cluster
$(MAKE) kind-create-cluster
$(MAKE) install-metrics-server
$(MAKE) install-metallb
$(MAKE) gateway-api-install
$(MAKE) install-cert-manager
$(MAKE) create-cluster-issuer
$(MAKE) $(GATEWAYAPI_PROVIDER)-install
$(MAKE) create-test-namespaces
$(MAKE) create-aws-credentials
$(MAKE) deploy-kuadrant-operator
$(MAKE) deploy-kuadrant-cr
$(MAKE) deploy-testsuite-tools
@echo ""
@echo "Local environment setup complete!"
@echo " Cluster: $(KIND_CLUSTER_NAME)"
@echo " Gateway Provider: $(GATEWAYAPI_PROVIDER)"
@echo ""
@echo "Run tests with: make kuadrant"

.PHONY: local-cleanup
local-cleanup: ## Delete local kind cluster
$(MAKE) kind-delete-cluster
29 changes: 29 additions & 0 deletions make/tools.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

##@ Testsuite Tools

.PHONY: deploy-testsuite-tools
deploy-testsuite-tools: ## Deploy testsuite tools (Keycloak, etc.) - requires RH_REGISTRY credentials
@if [ -n "$(RH_REGISTRY_USERNAME)" ] && [ -n "$(RH_REGISTRY_PASSWORD)" ]; then \
echo "Deploying testsuite tools..."; \
kubectl create namespace tools || true; \
echo "Creating Red Hat registry secret..."; \
kubectl -n tools create secret docker-registry redhat-registry-secret \
--docker-server=registry.redhat.io \
--docker-username="$(RH_REGISTRY_USERNAME)" \
--docker-password="$(RH_REGISTRY_PASSWORD)" \
--dry-run=client -o yaml | kubectl apply -f -; \
kubectl -n tools patch serviceaccount default \
-p '{"imagePullSecrets": [{"name": "redhat-registry-secret"}]}'; \
helm repo add kuadrant-olm https://kuadrant.io/helm-charts-olm --force-update; \
helm repo update; \
helm install \
--set=tools.keycloak.keycloakProvider=deployment \
--set=tools.coredns.enable=false \
--debug \
--wait \
--timeout=$(TOOLS_TIMEOUT) \
tools kuadrant-olm/tools-instances; \
echo "Testsuite tools deployed"; \
else \
echo "⏭️ Skipping testsuite tools deployment (requires RH_REGISTRY_USERNAME and RH_REGISTRY_PASSWORD)"; \
fi
Loading
Loading