From e9ec94e38e8ef4a799bc70c888102d9b57d706bf Mon Sep 17 00:00:00 2001 From: Daniel Beres Date: Wed, 18 Feb 2026 14:06:37 +0100 Subject: [PATCH 1/4] feat: add SONiC CLOS network lab Signed-off-by: Daniel Beres --- test/emulation/clos/README.md | 115 ++++++++++++++++++++++++++ test/emulation/clos/clos.clab.yml | 29 +++++++ test/emulation/clos/clos_topology.svg | 4 + test/emulation/clos/deploy.sh | 67 +++++++++++++++ test/emulation/clos/destroy.sh | 42 ++++++++++ test/emulation/clos/init_setup.sh | 24 ++++++ 6 files changed, 281 insertions(+) create mode 100644 test/emulation/clos/README.md create mode 100644 test/emulation/clos/clos.clab.yml create mode 100755 test/emulation/clos/clos_topology.svg create mode 100755 test/emulation/clos/deploy.sh create mode 100755 test/emulation/clos/destroy.sh create mode 100755 test/emulation/clos/init_setup.sh diff --git a/test/emulation/clos/README.md b/test/emulation/clos/README.md new file mode 100644 index 0000000..2921038 --- /dev/null +++ b/test/emulation/clos/README.md @@ -0,0 +1,115 @@ +# SONiC Lab Topology (CLOS) + +A containerized network lab environment running SONiC switches in a CLOS topology, orchestrated on Kubernetes using Clabernetes. + +## Overview + +This project sets up a complete network topology with: +- **2 Spine switches** (SONiC VMs) +- **2 Leaf switches** (SONiC VMs) +- **2 Client nodes** (Linux multitool containers) + +The topology implements a standard data center CLOS architecture. + +### Topology Diagram + +![CLOS Topology](clos_topology.svg) + +## Prerequisites + +The following tools must be installed on the host: + +- **kind** - Kubernetes in Docker (for local Kubernetes cluster) +- **kubectl** - Kubernetes command-line tool +- **sshpass** - SSH password automation utility + +## Project Structure + +``` +clos/ +├── clos.clab.yml - Network topology definition (YAML) +├── deploy.sh - Deployment automation script +├── init_setup.sh - Node initialization and agent setup +├── destroy.sh - Infrastructure cleanup script +└── README.md - This file +``` + +## Dependencies + + +### Software Packages +``` +docker - Container runtime +kubernetes - Container orchestration +helm - Package manager +kubectl - Kubernetes CLI +sshpass - SSH password utility +jq - JSON processor +``` + +### Kubernetes Services +- Clabernetes - Deployed via Helm in `c9s` namespace +- kube-vip - RBAC and manifests applied to cluster +- kube-vip Cloud Controller - Deployed in `kube-vip` namespace + + +## Configuration Details + +### IP Management +- kube-vip External IP Range: `172.18.1.10 - 172.18.1.250` +- Services exposed via kube-vip ARP mode on eth0 + +## Setup Steps + +### 1. Prerequisites +Ensure all dependencies are installed and Kubernetes cluster is ready: + +### 2. Initialize Kind Cluster +Run the initialization setup from the root level Makefile by: +```bash +make setup-test-e2e +``` + +### 3. Deploy the Lab Environment +Deploy the full topology to Kubernetes: +```bash +./deploy.sh +``` + +**What it does**: +- Installs Clabernetes via Helm in `c9s` namespace +- Applies kube-vip RBAC policies +- Deploys kube-vip cloud controller +- Creates kube-vip configmap with IP range +- Deploys kube-vip ARP daemonset +- Converts containerlab topology to Kubernetes resources +- Applies topology configuration to cluster +- Waits for services to be ready (180 seconds) +- Configure DNS, Pulls and starts Sonic Agenton port 57400 for each SONiC node via SSH +- Displays external IPs for all services + +### 4. Access the Lab +After successful deployment, retrieve external IPs: +```bash +# View all services with external IPs +kubectl get -n c9s-clos svc + +# SSH into a specific SONiC node (default credentials: admin/admin) +ssh admin@ + +# Example +ssh admin@172.18.1.15 +``` + +### 5. Cleanup +Tear down the entire lab environment: +```bash +./destroy.sh +``` + +**What it does**: +- Deletes the `c9s-clos` namespace (all topology resources) +- Deletes the `c9s` namespace (Clabernetes) +- Removes kube-vip configmap, daemonset, and cloud controller +- Cleans up kube-vip RBAC resources +- Removes all related Kubernetes objects diff --git a/test/emulation/clos/clos.clab.yml b/test/emulation/clos/clos.clab.yml new file mode 100644 index 0000000..bf6bbfb --- /dev/null +++ b/test/emulation/clos/clos.clab.yml @@ -0,0 +1,29 @@ +name: clos + +topology: + nodes: + sonic-spine1: + kind: sonic-vm + image: dberes/sonic-vs:latest + sonic-spine2: + kind: sonic-vm + image: dberes/sonic-vs:latest + sonic-leaf1: + kind: sonic-vm + image: dberes/sonic-vs:latest + sonic-leaf2: + kind: sonic-vm + image: dberes/sonic-vs:latest + client1: + kind: linux + image: ghcr.io/hellt/network-multitool:latest + client2: + kind: linux + image: ghcr.io/hellt/network-multitool:latest + links: + - endpoints: ["sonic-spine1:eth1", "sonic-leaf1:eth1"] + - endpoints: ["sonic-spine1:eth2", "sonic-leaf2:eth1"] + - endpoints: ["sonic-spine2:eth1", "sonic-leaf1:eth2"] + - endpoints: ["sonic-spine2:eth2", "sonic-leaf2:eth2"] + - endpoints: ["sonic-leaf1:eth3", "client1:eth1"] + - endpoints: ["sonic-leaf2:eth3", "client2:eth1"] diff --git a/test/emulation/clos/clos_topology.svg b/test/emulation/clos/clos_topology.svg new file mode 100755 index 0000000..d9c8fdc --- /dev/null +++ b/test/emulation/clos/clos_topology.svg @@ -0,0 +1,4 @@ + + + +
Leaf1
Leaf2
Spine2
Spine1
Client1
Client2
\ No newline at end of file diff --git a/test/emulation/clos/deploy.sh b/test/emulation/clos/deploy.sh new file mode 100755 index 0000000..452dbab --- /dev/null +++ b/test/emulation/clos/deploy.sh @@ -0,0 +1,67 @@ +#!/bin/bash +set -eu +HELM="docker run --network host -ti --rm -v $(pwd):/apps -w /apps \ + -v $HOME/.kube:/root/.kube -v $HOME/.helm:/root/.helm \ + -v $HOME/.config/helm:/root/.config/helm \ + -v $HOME/.cache/helm:/root/.cache/helm \ + alpine/helm:3.12.3" + +CLABVERTER="sudo docker run --user $(id -u) -v $(pwd):/clabernetes/work --rm ghcr.io/srl-labs/clabernetes/clabverter" + +$HELM upgrade --install --create-namespace --namespace c9s \ + clabernetes oci://ghcr.io/srl-labs/clabernetes/clabernetes + +kubectl apply -f https://kube-vip.io/manifests/rbac.yaml +kubectl apply -f https://raw.githubusercontent.com/kube-vip/kube-vip-cloud-provider/main/manifest/kube-vip-cloud-controller.yaml +kubectl create configmap --namespace kube-system kubevip \ + --from-literal range-global=172.18.1.10-172.18.1.250 || true + +#set up the kube-vip CLI +KVVERSION=$(curl -sL https://api.github.com/repos/kube-vip/kube-vip/releases | \ + jq -r ".[0].name") +KUBEVIP="docker run --network host \ + --rm ghcr.io/kube-vip/kube-vip:$KVVERSION" +#install kube-vip load balancer daemonset in ARP mode +$KUBEVIP manifest daemonset --services --inCluster --arp --interface eth0 | \ +kubectl apply -f - + + +echo "Checking for configuration changes..." +CONFIG=$($CLABVERTER --stdout --naming non-prefixed) + +if echo "$CONFIG" | kubectl diff -f - > /dev/null 2>&1; then + echo "No changes detected, skipping apply and wait" +else + echo "Changes detected, applying configuration..." + echo "$CONFIG" | kubectl apply -f - + + # Wait for services to be ready + echo "Waiting for services to be ready..." + sleep 180 + + # Run script on each sonic node + echo "Provisioning SONiC nodes..." + for service in $(kubectl get -n c9s-clos svc -o jsonpath='{.items[*].metadata.name}' 2>/dev/null | tr ' ' '\n' | grep '^sonic-'); do + h=$(kubectl get -n c9s-clos svc "$service" -o jsonpath='{.status.loadBalancer.ingress[0].ip}' 2>/dev/null) + if [ ! -z "$h" ]; then + echo "Running init_setup.sh on $h" + sshpass -p 'admin' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null admin@"$h" 'bash -s' < init_setup.sh || true + fi + done + +fi + + +echo "" +echo "==========================================" +echo "SONiC Lab Topology - External IPs" +echo "==========================================" +for service in $(kubectl get -n c9s-clos svc -o jsonpath='{.items[*].metadata.name}' 2>/dev/null | tr ' ' '\n'); do + ip=$(kubectl get -n c9s-clos svc "$service" -o jsonpath='{.status.loadBalancer.ingress[0].ip}' 2>/dev/null) + if [ -n "$ip" ]; then + echo "$service -> $ip" + fi +done + +echo "" +echo "Script ended successfully" diff --git a/test/emulation/clos/destroy.sh b/test/emulation/clos/destroy.sh new file mode 100755 index 0000000..cda0b02 --- /dev/null +++ b/test/emulation/clos/destroy.sh @@ -0,0 +1,42 @@ +#!/bin/bash +set -eux + +echo "Starting destruction of SONiC lab infrastructure..." + +# Delete the c9s-clos namespace (contains all topology resources) +echo "Deleting c9s-clos namespace..." +kubectl delete namespace c9s-clos --ignore-not-found=true +sleep 10 + +# Delete the c9s namespace (contains clabernetes) +echo "Deleting c9s namespace..." +kubectl delete namespace c9s --ignore-not-found=true +sleep 10 + +# Remove kube-vip configmap +echo "Removing kube-vip configmap..." +kubectl delete configmap -n kube-system kubevip --ignore-not-found=true + +# Remove kube-vip daemonset +echo "Removing kube-vip daemonset..." +kubectl delete daemonset -n kube-system kube-vip-ds --ignore-not-found=true + +# Remove kube-vip cloud controller +echo "Removing kube-vip cloud controller deployment..." +kubectl delete deployment -n kube-vip kube-vip-cloud-provider --ignore-not-found=true + +# Remove kube-vip namespace if empty +echo "Cleaning up kube-vip namespace..." +kubectl delete namespace kube-vip --ignore-not-found=true + +# Remove RBAC resources for kube-vip +echo "Removing kube-vip RBAC resources..." +kubectl delete clusterrole system:kube-vip-role --ignore-not-found=true +kubectl delete clusterrole system:kube-vip-cloud-controller-role --ignore-not-found=true +kubectl delete clusterrolebinding system:kube-vip-binding --ignore-not-found=true +kubectl delete clusterrolebinding system:kube-vip-cloud-controller-binding --ignore-not-found=true +kubectl delete serviceaccount -n kube-system kube-vip --ignore-not-found=true +kubectl delete serviceaccount -n kube-vip kube-vip-cloud-controller --ignore-not-found=true + +echo "Destruction complete!" +echo "All SONiC lab resources have been removed." diff --git a/test/emulation/clos/init_setup.sh b/test/emulation/clos/init_setup.sh new file mode 100755 index 0000000..a9cc976 --- /dev/null +++ b/test/emulation/clos/init_setup.sh @@ -0,0 +1,24 @@ +#!/bin/bash +set -euo pipefail + +IMAGE="ghcr.io/ironcore-dev/sonic-agent:sha-966298d" + +echo "Configuring DNS..." +if [ -d "/etc/resolvconf/resolv.conf.d" ]; then + echo "nameserver 8.8.8.8" | sudo tee /etc/resolvconf/resolv.conf.d/head + sudo /sbin/resolvconf --enable-updates + sudo /sbin/resolvconf -u + sudo /sbin/resolvconf --disable-updates +else + echo "Warning: resolvconf not found, skipping DNS configuration" +fi +echo "Removing old agent container if it exists..." +docker rm -f switch-operator-agent 2>/dev/null || true + +echo "Pulling agent image..." +docker pull "$IMAGE" + +echo "Starting agent container..." +docker run --pull always -d --name switch-operator-agent --entrypoint /switch-agent-server --network host --restart unless-stopped "$IMAGE" -port 57400 + +echo "Agent setup completed successfully" From a0dbcbf76708f165be3b04496cfec18e6a02a18d Mon Sep 17 00:00:00 2001 From: Daniel Beres Date: Thu, 19 Feb 2026 11:17:28 +0100 Subject: [PATCH 2/4] feat: fix the license issue in the CLOS directory Signed-off-by: Daniel Beres --- REUSE.toml | 1 + test/emulation/clos/deploy.sh | 4 ++++ test/emulation/clos/destroy.sh | 4 ++++ test/emulation/clos/init_setup.sh | 4 ++++ 4 files changed, 13 insertions(+) diff --git a/REUSE.toml b/REUSE.toml index 050b702..9a67a48 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -26,6 +26,7 @@ SPDX-PackageDownloadLocation = "https://github.com/ironcore-dev/sonic-operator" "README.md", "internal/agent/hack/**", "internal/agent/proto/**", + "test/emulation/**", ] precedence = "aggregate" SPDX-FileCopyrightText = "2025 SAP SE or an SAP affiliate company and IronCore contributors" diff --git a/test/emulation/clos/deploy.sh b/test/emulation/clos/deploy.sh index 452dbab..c408bcc 100755 --- a/test/emulation/clos/deploy.sh +++ b/test/emulation/clos/deploy.sh @@ -1,4 +1,8 @@ #!/bin/bash + +# SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and IronCore contributors +# SPDX-License-Identifier: Apache-2.0 + set -eu HELM="docker run --network host -ti --rm -v $(pwd):/apps -w /apps \ -v $HOME/.kube:/root/.kube -v $HOME/.helm:/root/.helm \ diff --git a/test/emulation/clos/destroy.sh b/test/emulation/clos/destroy.sh index cda0b02..e2266d4 100755 --- a/test/emulation/clos/destroy.sh +++ b/test/emulation/clos/destroy.sh @@ -1,4 +1,8 @@ #!/bin/bash + +# SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and IronCore contributors +# SPDX-License-Identifier: Apache-2.0 + set -eux echo "Starting destruction of SONiC lab infrastructure..." diff --git a/test/emulation/clos/init_setup.sh b/test/emulation/clos/init_setup.sh index a9cc976..d9fb0cf 100755 --- a/test/emulation/clos/init_setup.sh +++ b/test/emulation/clos/init_setup.sh @@ -1,4 +1,8 @@ #!/bin/bash + +# SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and IronCore contributors +# SPDX-License-Identifier: Apache-2.0 + set -euo pipefail IMAGE="ghcr.io/ironcore-dev/sonic-agent:sha-966298d" From bb91b8459096deae50663e620f2e550ad081936c Mon Sep 17 00:00:00 2001 From: Daniel Beres Date: Tue, 17 Mar 2026 13:53:16 +0100 Subject: [PATCH 3/4] feat: add redeploy.sh to the CLOS directory, separate logic from the makefile, automatically create Custom Resources Signed-off-by: Daniel Beres --- test/emulation/clos/deploy.sh | 75 +++++++++++++++++++++++++-- test/emulation/clos/destroy.sh | 11 +++- test/emulation/clos/init_setup.sh | 4 +- test/emulation/clos/redeploy_agent.sh | 66 +++++++++++++++++++++++ 4 files changed, 150 insertions(+), 6 deletions(-) create mode 100755 test/emulation/clos/redeploy_agent.sh diff --git a/test/emulation/clos/deploy.sh b/test/emulation/clos/deploy.sh index c408bcc..7e54a4d 100755 --- a/test/emulation/clos/deploy.sh +++ b/test/emulation/clos/deploy.sh @@ -4,6 +4,30 @@ # SPDX-License-Identifier: Apache-2.0 set -eu + +# Setup Kind cluster for e2e tests if it does not exist +KIND_CLUSTER="clos-lab-kind" +echo "Setting up Kind cluster for tests..." +if ! command -v kind &> /dev/null; then + echo "Kind is not installed. Please install Kind manually." + exit 1 +fi + +if kind get clusters 2>/dev/null | grep -q "^${KIND_CLUSTER}$"; then + echo "Kind cluster '${KIND_CLUSTER}' already exists. Skipping creation." +else + echo "Creating Kind cluster '${KIND_CLUSTER}'..." + kind create cluster --name "${KIND_CLUSTER}" +fi + +# Go to git repo root +pushd "$(git rev-parse --show-toplevel)" || exit 1 + +echo "Installing CRDs..." +make install +# Return to original directory +popd || exit 1 + HELM="docker run --network host -ti --rm -v $(pwd):/apps -w /apps \ -v $HOME/.kube:/root/.kube -v $HOME/.helm:/root/.helm \ -v $HOME/.config/helm:/root/.config/helm \ @@ -41,15 +65,37 @@ else # Wait for services to be ready echo "Waiting for services to be ready..." - sleep 180 + kubectl wait --namespace c9s --for=condition=ready --timeout=300s pods --all + kubectl wait --namespace c9s-clos --for=condition=ready --timeout=300s pods --all + # Run script on each sonic node echo "Provisioning SONiC nodes..." - for service in $(kubectl get -n c9s-clos svc -o jsonpath='{.items[*].metadata.name}' 2>/dev/null | tr ' ' '\n' | grep '^sonic-'); do + for service in $(kubectl get -n c9s-clos svc -o jsonpath='{.items[*].metadata.name}' 2>/dev/null | tr ' ' '\n' | grep '^sonic-' | grep -v '\-vx$'); do + until IP=$(kubectl get svc "$service" -n c9s-clos -o jsonpath='{.status.loadBalancer.ingress[0].ip}') && [ -n "$IP" ]; do + echo "Waiting for external IP..." + sleep 1 + done + h=$(kubectl get -n c9s-clos svc "$service" -o jsonpath='{.status.loadBalancer.ingress[0].ip}' 2>/dev/null) if [ ! -z "$h" ]; then echo "Running init_setup.sh on $h" - sshpass -p 'admin' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null admin@"$h" 'bash -s' < init_setup.sh || true + max_attempts=36 # 36 attempts with 10 seconds sleep = 6 minutes total wait time + attempt=1 + while [ $attempt -le $max_attempts ]; do + if sshpass -p 'admin' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null admin@"$h" 'bash -s' < init_setup.sh; then + echo "Successfully provisioned $h" + break + else + if [ $attempt -lt $max_attempts ]; then + echo "Provisioning attempt $attempt of $max_attempts failed for $h. Retrying in 10 seconds..." + sleep 10 + else + echo "Failed to provision $h after $max_attempts attempts" + fi + fi + ((attempt++)) + done fi done @@ -60,11 +106,32 @@ echo "" echo "==========================================" echo "SONiC Lab Topology - External IPs" echo "==========================================" -for service in $(kubectl get -n c9s-clos svc -o jsonpath='{.items[*].metadata.name}' 2>/dev/null | tr ' ' '\n'); do +for service in $(kubectl get -n c9s-clos svc -o jsonpath='{.items[*].metadata.name}' 2>/dev/null | tr ' ' '\n'| grep -v '\-vx$'); do ip=$(kubectl get -n c9s-clos svc "$service" -o jsonpath='{.status.loadBalancer.ingress[0].ip}' 2>/dev/null) if [ -n "$ip" ]; then echo "$service -> $ip" + + if [[ "$service" == *sonic* ]]; then + cat < /dev/null; then + kind delete cluster --name "${KIND_CLUSTER}" 2>/dev/null || true +else + echo "Kind is not installed, skipping cluster cleanup." +fi diff --git a/test/emulation/clos/init_setup.sh b/test/emulation/clos/init_setup.sh index d9fb0cf..09358b8 100755 --- a/test/emulation/clos/init_setup.sh +++ b/test/emulation/clos/init_setup.sh @@ -23,6 +23,8 @@ echo "Pulling agent image..." docker pull "$IMAGE" echo "Starting agent container..." -docker run --pull always -d --name switch-operator-agent --entrypoint /switch-agent-server --network host --restart unless-stopped "$IMAGE" -port 57400 +docker run --pull always -d --name switch-operator-agent --entrypoint /switch-agent-server --network host --restart unless-stopped -v /var/run/dbus:/var/run/dbus:rw "$IMAGE" -port 57400 echo "Agent setup completed successfully" + + diff --git a/test/emulation/clos/redeploy_agent.sh b/test/emulation/clos/redeploy_agent.sh new file mode 100755 index 0000000..82058ed --- /dev/null +++ b/test/emulation/clos/redeploy_agent.sh @@ -0,0 +1,66 @@ +#!/bin/bash +set -x + +# ---- CONFIG ---- +# Use a consistent container name. 'switch-operator-agent' is used in other scripts like init_setup.sh +CONTAINER_NAME="switch-operator-agent" +IMAGE_NAME="sonic-agent" +IMAGE_TAG="local" +IMAGE_SPEC="${IMAGE_NAME}:${IMAGE_TAG}" + +# Use a temporary file for the image archive and ensure it's cleaned up on exit. +IMAGE_ARCHIVE=$(mktemp) +trap 'rm -f -- "$IMAGE_ARCHIVE"' EXIT + +PROJECT_ROOT=$(git rev-parse --show-toplevel) + +# ---- BUILD IMAGE ---- +echo "Building image ${IMAGE_SPEC} from project root ${PROJECT_ROOT}..." +docker build -f "${PROJECT_ROOT}/Dockerfile" \ + --target sonic-agent \ + -t "${IMAGE_SPEC}" \ + "${PROJECT_ROOT}" + +echo "Saving image to temporary archive ${IMAGE_ARCHIVE}..." +docker save "${IMAGE_SPEC}" -o "${IMAGE_ARCHIVE}" + +# ---- DEPLOY TO VMS ---- +echo "Deploying agent to SONiC nodes..." +for service in $(kubectl get -n c9s-clos svc -o jsonpath='{.items[*].metadata.name}' 2>/dev/null | tr ' ' '\n' | grep '^sonic-'); do + h=$(kubectl get -n c9s-clos svc "$service" -o jsonpath='{.status.loadBalancer.ingress[0].ip}' 2>/dev/null) + if [ -z "$h" ]; then + continue + fi + + echo "Deploying to node ${h}..." + + # Copy the image archive + sshpass -p 'admin' scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "${IMAGE_ARCHIVE}" "admin@${h}:/tmp/image.tar" + + # Execute remote commands to load image and restart container. + # Pass variables as arguments to the remote script for safety and clarity. + sshpass -p 'admin' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "admin@${h}" bash -s -- "${CONTAINER_NAME}" "${IMAGE_SPEC}" <<'EOF' + set -eux + + REMOTE_CONTAINER_NAME="$1" + REMOTE_IMAGE_SPEC="$2" + + echo "Loading docker image on remote host..." + docker load < /tmp/image.tar + + echo "Stopping and removing old container '${REMOTE_CONTAINER_NAME}' if it exists..." + docker rm -f "${REMOTE_CONTAINER_NAME}" || true + + echo "Starting new container '${REMOTE_CONTAINER_NAME}' with image '${REMOTE_IMAGE_SPEC}'..." + docker run -d --user 0 \ + --name "${REMOTE_CONTAINER_NAME}" \ + --entrypoint /switch-agent-server \ + --network host \ + --restart unless-stopped \ + -v /var/run/dbus:/var/run/dbus:rw \ + "${REMOTE_IMAGE_SPEC}" \ + -port 57400 +EOF +done + +echo "Redeployment script finished successfully." From 9e917ef1c055496d607929a8c6807e58ad1ed0ea Mon Sep 17 00:00:00 2001 From: Daniel Beres Date: Tue, 17 Mar 2026 14:16:54 +0100 Subject: [PATCH 4/4] feat: update README.md for clos emulation Signed-off-by: Daniel Beres --- test/emulation/clos/README.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/test/emulation/clos/README.md b/test/emulation/clos/README.md index 2921038..d6d21f0 100644 --- a/test/emulation/clos/README.md +++ b/test/emulation/clos/README.md @@ -64,19 +64,15 @@ jq - JSON processor ### 1. Prerequisites Ensure all dependencies are installed and Kubernetes cluster is ready: -### 2. Initialize Kind Cluster -Run the initialization setup from the root level Makefile by: -```bash -make setup-test-e2e -``` - -### 3. Deploy the Lab Environment +### 2. Deploy the Lab Environment Deploy the full topology to Kubernetes: ```bash ./deploy.sh ``` **What it does**: +- Creates Kind Cluster `clos-lab-kind` +- Install CRDs - Installs Clabernetes via Helm in `c9s` namespace - Applies kube-vip RBAC policies - Deploys kube-vip cloud controller @@ -86,6 +82,7 @@ Deploy the full topology to Kubernetes: - Applies topology configuration to cluster - Waits for services to be ready (180 seconds) - Configure DNS, Pulls and starts Sonic Agenton port 57400 for each SONiC node via SSH +- Creates CRs for the switches - Displays external IPs for all services ### 4. Access the Lab