⚠️ Split Helm chart into operator and providers charts with optional dependency #17
Workflow file for this run
This file contains hidden or 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
| name: Smoke Test | |
| on: | |
| pull_request: | |
| branches: | |
| - main | |
| - 'release-*' | |
| push: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| smoke-test: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: 'go.mod' | |
| - name: Install kubectl | |
| run: | | |
| curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" | |
| chmod +x kubectl | |
| sudo mv kubectl /usr/local/bin/ | |
| - name: Install Helm | |
| run: | | |
| curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash | |
| - name: Build Docker image | |
| run: | | |
| # Build the operator image with a specific tag for smoke test | |
| CONTROLLER_IMG=cluster-api-operator TAG=smoke-test make docker-build | |
| echo "Built image: cluster-api-operator-amd64:smoke-test" | |
| # Tag the image for easier reference | |
| docker tag cluster-api-operator-amd64:smoke-test cluster-api-operator:smoke-test | |
| - name: Build charts | |
| run: | | |
| make release-chart | |
| # Extract HELM_CHART_TAG from Makefile | |
| HELM_CHART_TAG=$(make -s -f Makefile -p | grep '^HELM_CHART_TAG :=' | cut -d' ' -f3) | |
| echo "HELM_CHART_TAG=$HELM_CHART_TAG" >> $GITHUB_ENV | |
| echo "Detected HELM_CHART_TAG: $HELM_CHART_TAG" | |
| - name: Create kind cluster | |
| run: | | |
| chmod +x ./hack/ensure-kind.sh | |
| ./hack/ensure-kind.sh | |
| # Create kind cluster with Docker socket mount for CAPD | |
| cat <<EOF > /tmp/kind-config.yaml | |
| kind: Cluster | |
| apiVersion: kind.x-k8s.io/v1alpha4 | |
| nodes: | |
| - role: control-plane | |
| extraMounts: | |
| - hostPath: /var/run/docker.sock | |
| containerPath: /var/run/docker.sock | |
| EOF | |
| kind create cluster --name capi-operator-smoke-test --config /tmp/kind-config.yaml --wait 5m | |
| kubectl cluster-info --context kind-capi-operator-smoke-test | |
| - name: Load Docker image to kind | |
| run: | | |
| # Load the built image into kind cluster | |
| kind load docker-image cluster-api-operator:smoke-test --name capi-operator-smoke-test | |
| echo "Loaded image cluster-api-operator:smoke-test into kind cluster" | |
| - name: Add Helm repositories | |
| run: | | |
| helm repo add jetstack https://charts.jetstack.io | |
| helm repo update | |
| - name: Install cert-manager | |
| run: | | |
| helm install cert-manager jetstack/cert-manager \ | |
| --namespace cert-manager \ | |
| --create-namespace \ | |
| --set installCRDs=true \ | |
| --wait \ | |
| --timeout 5m | |
| - name: Install Cluster API Operator | |
| run: | | |
| # Use exact chart filename based on HELM_CHART_TAG | |
| CHART_PACKAGE="out/package/cluster-api-operator-${HELM_CHART_TAG}.tgz" | |
| echo "Using chart package: $CHART_PACKAGE" | |
| # Verify the file exists | |
| if [ ! -f "$CHART_PACKAGE" ]; then | |
| echo "Error: Chart package not found: $CHART_PACKAGE" | |
| ls -la out/package/ | |
| exit 1 | |
| fi | |
| helm install capi-operator "$CHART_PACKAGE" \ | |
| --create-namespace \ | |
| -n capi-operator-system \ | |
| --set image.manager.repository=cluster-api-operator \ | |
| --set image.manager.tag=smoke-test \ | |
| --set image.manager.pullPolicy=IfNotPresent \ | |
| --wait \ | |
| --timeout 90s | |
| - name: Wait for CAPI Operator to be ready | |
| run: | | |
| kubectl wait --for=condition=Available --timeout=300s -n capi-operator-system deployment/capi-operator-cluster-api-operator | |
| - name: Deploy providers using cluster-api-operator-providers chart | |
| run: | | |
| # Create values file for providers | |
| cat <<EOF > /tmp/providers-values.yaml | |
| core: | |
| cluster-api: | |
| namespace: capi-system | |
| bootstrap: | |
| kubeadm: | |
| namespace: capi-kubeadm-bootstrap-system | |
| controlPlane: | |
| kubeadm: | |
| namespace: capi-kubeadm-control-plane-system | |
| infrastructure: | |
| docker: | |
| namespace: capd-system | |
| EOF | |
| # Use exact providers chart filename based on HELM_CHART_TAG | |
| PROVIDERS_CHART_PACKAGE="out/package/cluster-api-operator-providers-${HELM_CHART_TAG}.tgz" | |
| echo "Using providers chart package: $PROVIDERS_CHART_PACKAGE" | |
| # Verify the file exists | |
| if [ ! -f "$PROVIDERS_CHART_PACKAGE" ]; then | |
| echo "Error: Providers chart package not found: $PROVIDERS_CHART_PACKAGE" | |
| ls -la out/package/ | |
| exit 1 | |
| fi | |
| helm install capi-providers "$PROVIDERS_CHART_PACKAGE" \ | |
| -f /tmp/providers-values.yaml \ | |
| --wait \ | |
| --timeout 3m | |
| - name: Wait for providers to be ready | |
| run: | | |
| echo "=== Waiting for Core Provider to be ready ===" | |
| kubectl wait --for=condition=Ready --timeout=300s -n capi-system coreprovider/cluster-api || true | |
| echo -e "\n=== Waiting for Bootstrap Provider to be ready ===" | |
| kubectl wait --for=condition=Ready --timeout=300s -n capi-kubeadm-bootstrap-system bootstrapprovider/kubeadm || true | |
| echo -e "\n=== Waiting for Control Plane Provider to be ready ===" | |
| kubectl wait --for=condition=Ready --timeout=300s -n capi-kubeadm-control-plane-system controlplaneprovider/kubeadm || true | |
| echo -e "\n=== Waiting for Infrastructure Provider to be ready ===" | |
| kubectl wait --for=condition=Ready --timeout=300s -n capd-system infrastructureprovider/docker || true | |
| # Additional wait for deployments | |
| echo -e "\n=== Waiting for provider deployments ===" | |
| kubectl wait --for=condition=Available --timeout=300s -n capi-system deployment/capi-controller-manager || true | |
| kubectl wait --for=condition=Available --timeout=300s -n capi-kubeadm-bootstrap-system deployment/capi-kubeadm-bootstrap-controller-manager || true | |
| kubectl wait --for=condition=Available --timeout=300s -n capi-kubeadm-control-plane-system deployment/capi-kubeadm-control-plane-controller-manager || true | |
| kubectl wait --for=condition=Available --timeout=300s -n capd-system deployment/capd-controller-manager || true | |
| # Wait for webhooks to be ready | |
| echo -e "\n=== Waiting for webhook services ===" | |
| kubectl wait --for=jsonpath='{.status.loadBalancer}' --timeout=300s -n capi-kubeadm-bootstrap-system service/capi-kubeadm-bootstrap-webhook-service || true | |
| kubectl wait --for=jsonpath='{.status.loadBalancer}' --timeout=300s -n capi-kubeadm-control-plane-system service/capi-kubeadm-control-plane-webhook-service || true | |
| - name: Verify installation | |
| run: | | |
| echo "=== Cluster API Operator Status ===" | |
| kubectl get pods -n capi-operator-system | |
| echo -e "\n=== Core Provider Status ===" | |
| kubectl get coreprovider -A -o wide | |
| kubectl describe coreprovider -n capi-system cluster-api || true | |
| echo -e "\n=== Bootstrap Provider Status ===" | |
| kubectl get bootstrapprovider -A -o wide | |
| kubectl describe bootstrapprovider -n capi-kubeadm-bootstrap-system kubeadm || true | |
| echo -e "\n=== Control Plane Provider Status ===" | |
| kubectl get controlplaneprovider -A -o wide | |
| kubectl describe controlplaneprovider -n capi-kubeadm-control-plane-system kubeadm || true | |
| echo -e "\n=== Infrastructure Provider Status ===" | |
| kubectl get infrastructureprovider -A -o wide | |
| kubectl describe infrastructureprovider -n capd-system docker || true | |
| echo -e "\n=== All Pods ===" | |
| kubectl get pods -A | grep -E "(capi-|capd-)" | |
| echo -e "\n=== Webhook Services ===" | |
| kubectl get svc -A | grep webhook | |
| echo -e "\n=== Webhook Certificates ===" | |
| kubectl get certificate,certificaterequest -A | grep -E "(capi-|capd-)" | |
| echo -e "\n=== CRDs ===" | |
| kubectl get crds | grep -E "(cluster.x-k8s.io|operator.cluster.x-k8s.io)" | |
| - name: Check provider health | |
| run: | | |
| # Check if core provider is ready | |
| CORE_READY=$(kubectl get coreprovider -n capi-system cluster-api -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}') | |
| if [ "$CORE_READY" != "True" ]; then | |
| echo "Core provider is not ready" | |
| kubectl get coreprovider -n capi-system cluster-api -o yaml | |
| exit 1 | |
| fi | |
| # Check if bootstrap provider is ready | |
| BOOTSTRAP_READY=$(kubectl get bootstrapprovider -n capi-kubeadm-bootstrap-system kubeadm -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}') | |
| if [ "$BOOTSTRAP_READY" != "True" ]; then | |
| echo "Bootstrap provider is not ready" | |
| kubectl get bootstrapprovider -n capi-kubeadm-bootstrap-system kubeadm -o yaml | |
| exit 1 | |
| fi | |
| # Check if control plane provider is ready | |
| CONTROLPLANE_READY=$(kubectl get controlplaneprovider -n capi-kubeadm-control-plane-system kubeadm -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}') | |
| if [ "$CONTROLPLANE_READY" != "True" ]; then | |
| echo "Control plane provider is not ready" | |
| kubectl get controlplaneprovider -n capi-kubeadm-control-plane-system kubeadm -o yaml | |
| exit 1 | |
| fi | |
| # Check if infrastructure provider is ready | |
| INFRA_READY=$(kubectl get infrastructureprovider -n capd-system docker -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}') | |
| if [ "$INFRA_READY" != "True" ]; then | |
| echo "Infrastructure provider is not ready" | |
| kubectl get infrastructureprovider -n capd-system docker -o yaml | |
| exit 1 | |
| fi | |
| echo "All providers are ready!" | |
| # Additional webhook readiness check | |
| echo -e "\n=== Checking webhook endpoints ===" | |
| kubectl get endpoints -A | grep webhook | |
| - name: Download cluster manifest | |
| run: | | |
| echo "=== Downloading cluster manifest ===" | |
| curl -L https://raw.githubusercontent.com/kubernetes-sigs/cluster-api/refs/heads/main/test/infrastructure/docker/examples/simple-cluster.yaml -o simple-cluster.yaml | |
| # Show the manifest for debugging | |
| echo "=== Cluster manifest ===" | |
| cat simple-cluster.yaml | |
| - name: Create workload cluster | |
| run: | | |
| echo "=== Pre-creation diagnostics ===" | |
| echo "Checking webhook services..." | |
| kubectl get svc -A | grep webhook | |
| echo -e "\nChecking webhook endpoints..." | |
| kubectl get endpoints -A | grep webhook | |
| echo -e "\nChecking webhook certificates..." | |
| kubectl get secret -A | grep webhook-service-cert | |
| echo -e "\n=== Creating workload cluster ===" | |
| kubectl apply -f simple-cluster.yaml | |
| echo -e "\n=== Cluster resources created ===" | |
| kubectl get cluster,dockercluster,kubeadmcontrolplane,machinedeployment -A | |
| - name: Wait for cluster to be ready | |
| run: | | |
| echo "=== Waiting for cluster to be provisioned ===" | |
| kubectl wait --for=condition=Ready --timeout=600s cluster/capi-quickstart | |
| echo "=== Waiting for control plane to be initialized ===" | |
| kubectl wait --for=condition=Ready --timeout=600s kubeadmcontrolplane -l cluster.x-k8s.io/cluster-name=capi-quickstart | |
| echo "=== Waiting for first control plane node ===" | |
| kubectl wait --for=jsonpath='{.status.readyReplicas}'=1 --timeout=600s kubeadmcontrolplane -l cluster.x-k8s.io/cluster-name=capi-quickstart | |
| echo "=== Cluster status ===" | |
| kubectl get cluster capi-quickstart -o wide | |
| kubectl get machines -l cluster.x-k8s.io/cluster-name=capi-quickstart | |
| - name: Get workload cluster kubeconfig | |
| run: | | |
| echo "=== Getting workload cluster kubeconfig ===" | |
| # For Docker provider, use kind to get kubeconfig | |
| kind get kubeconfig --name capi-quickstart > capi-quickstart.kubeconfig | |
| echo "=== Testing kubeconfig ===" | |
| kubectl --kubeconfig=capi-quickstart.kubeconfig cluster-info | |
| - name: Verify kubectl commands work on workload cluster | |
| run: | | |
| echo "=== Testing kubectl get po on workload cluster ===" | |
| kubectl --kubeconfig=capi-quickstart.kubeconfig get po -A | |
| echo -e "\n=== Testing kubectl get nodes ===" | |
| kubectl --kubeconfig=capi-quickstart.kubeconfig get nodes | |
| echo -e "\n=== Waiting for system pods to be ready ===" | |
| kubectl --kubeconfig=capi-quickstart.kubeconfig wait --for=condition=Ready --timeout=300s pods -n kube-system -l k8s-app=kube-proxy | |
| kubectl --kubeconfig=capi-quickstart.kubeconfig wait --for=condition=Ready --timeout=300s pods -n kube-system -l component=kube-apiserver | |
| kubectl --kubeconfig=capi-quickstart.kubeconfig wait --for=condition=Ready --timeout=300s pods -n kube-system -l component=kube-controller-manager | |
| kubectl --kubeconfig=capi-quickstart.kubeconfig wait --for=condition=Ready --timeout=300s pods -n kube-system -l component=kube-scheduler | |
| - name: Deploy and test sample application | |
| run: | | |
| echo "=== Deploying nginx test application ===" | |
| kubectl --kubeconfig=capi-quickstart.kubeconfig create deployment nginx --image=nginx:alpine --replicas=2 | |
| echo "=== Waiting for deployment to be ready ===" | |
| kubectl --kubeconfig=capi-quickstart.kubeconfig wait --for=condition=Available --timeout=120s deployment/nginx | |
| echo "=== Verifying pods are running ===" | |
| kubectl --kubeconfig=capi-quickstart.kubeconfig get po -l app=nginx | |
| echo "=== Creating a service ===" | |
| kubectl --kubeconfig=capi-quickstart.kubeconfig expose deployment nginx --port=80 --type=ClusterIP | |
| echo "=== Verifying service ===" | |
| kubectl --kubeconfig=capi-quickstart.kubeconfig get svc nginx | |
| - name: Verify cluster functionality | |
| run: | | |
| echo "=== Final cluster verification ===" | |
| echo "Cluster nodes:" | |
| kubectl --kubeconfig=capi-quickstart.kubeconfig get nodes -o wide | |
| echo -e "\nAll pods:" | |
| kubectl --kubeconfig=capi-quickstart.kubeconfig get po -A | |
| echo -e "\nAll services:" | |
| kubectl --kubeconfig=capi-quickstart.kubeconfig get svc -A | |
| echo -e "\nCluster info:" | |
| kubectl --kubeconfig=capi-quickstart.kubeconfig cluster-info | |
| - name: Collect debug information on failure | |
| if: failure() | |
| run: | | |
| echo "=== Events ===" | |
| kubectl get events -A --sort-by='.lastTimestamp' | tail -50 | |
| echo -e "\n=== CAPI Operator Logs ===" | |
| kubectl logs -n capi-operator-system deployment/capi-operator-cluster-api-operator --tail=100 || true | |
| echo -e "\n=== Core Provider Logs ===" | |
| kubectl logs -n capi-system deployment/capi-controller-manager --tail=100 || true | |
| echo -e "\n=== Bootstrap Provider Logs ===" | |
| kubectl logs -n capi-kubeadm-bootstrap-system deployment/capi-kubeadm-bootstrap-controller-manager --tail=100 || true | |
| echo -e "\n=== Control Plane Provider Logs ===" | |
| kubectl logs -n capi-kubeadm-control-plane-system deployment/capi-kubeadm-control-plane-controller-manager --tail=100 || true | |
| echo -e "\n=== Infrastructure Provider Logs ===" | |
| kubectl logs -n capd-system deployment/capd-controller-manager --tail=100 || true | |
| echo -e "\n=== Webhook Services and Endpoints ===" | |
| kubectl get svc,endpoints -A | grep webhook || true | |
| echo -e "\n=== Webhook Certificates ===" | |
| kubectl get certificate,certificaterequest,secret -A | grep -E "(webhook|serving-cert)" || true | |
| echo -e "\n=== Cluster Resources ===" | |
| kubectl get cluster,dockercluster,kubeadmcontrolplane,machine,dockermachine -A -o wide || true | |
| echo -e "\n=== Describe Cluster ===" | |
| kubectl describe cluster capi-quickstart || true | |
| echo -e "\n=== Describe Machines ===" | |
| kubectl describe machines -l cluster.x-k8s.io/cluster-name=capi-quickstart || true | |
| echo -e "\n=== Docker Containers ===" | |
| docker ps -a | grep -E "(smoke-test|kind)" || true | |
| echo -e "\n=== Kind Clusters ===" | |
| kind get clusters || true | |
| echo -e "\n=== Describe Failed Pods ===" | |
| kubectl get pods -A | grep -v Running | grep -v Completed | tail -n +2 | while read namespace name ready status restarts age; do | |
| echo "Describing pod $name in namespace $namespace" | |
| kubectl describe pod -n $namespace $name | |
| echo "---" | |
| done | |
| - name: Clean up | |
| if: always() | |
| run: | | |
| echo "=== Cleaning up kind clusters ===" | |
| # List all kind clusters before cleanup | |
| echo "Current kind clusters:" | |
| kind get clusters || true | |
| # Delete workload cluster | |
| echo "Deleting workload cluster: capi-quickstart" | |
| kind delete cluster --name capi-quickstart || true | |
| # Delete management cluster | |
| echo "Deleting management cluster: capi-operator-smoke-test" | |
| kind delete cluster --name capi-operator-smoke-test || true | |
| # Verify all clusters are deleted | |
| echo "Remaining kind clusters:" | |
| kind get clusters || true |