Skip to content

Commit a9f46e7

Browse files
committed
Add support for multi-zone support + incline whole script
Signed-off-by: see-quick <maros.orsak159@gmail.com>
1 parent 2d58695 commit a9f46e7

6 files changed

Lines changed: 552 additions & 8 deletions

File tree

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
.idea
2+
docs
23
FEATURES.md
34

45
# Test artifacts
5-
test/.bats/
6+
test/.bats/
7+
8+
# Build artifacts
9+
dist/

README.md

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,31 @@ Inspired by [StrimKKhaos](https://github.com/see-quick/StrimKKhaos).
1414

1515
## Installation
1616

17-
Download the latest version:
17+
Download from the latest [GitHub release](https://github.com/see-quick/kind-script/releases):
1818

1919
```bash
20-
curl -sSLO https://github.com/see-quick/kind-script/raw/main/kind-cluster.sh
20+
curl -sSLO https://github.com/see-quick/kind-script/releases/latest/download/kind-cluster.sh
2121
chmod +x kind-cluster.sh
2222
```
2323

2424
Or pin to a specific version:
2525

2626
```bash
27-
curl -sSLO https://github.com/see-quick/kind-script/raw/v1.0.0/kind-cluster.sh
27+
curl -sSLO https://github.com/see-quick/kind-script/releases/download/v1.0.0/kind-cluster.sh
2828
chmod +x kind-cluster.sh
2929
```
3030

31+
### Building from source
32+
33+
Clone the repo and run the build script to produce a single-file distribution:
34+
35+
```bash
36+
git clone https://github.com/see-quick/kind-script.git
37+
cd kind-script
38+
./build.sh
39+
# Output: dist/kind-cluster.sh
40+
```
41+
3142
## Quick Start
3243

3344
```bash
@@ -59,10 +70,42 @@ chmod +x kind-cluster.sh
5970
--registry-port PORT Registry port (default: 5001)
6071
--no-registry Disable local registry
6172
--no-cloud-provider Disable LoadBalancer support
73+
--zones N Number of zones to simulate
74+
--nodes-per-zone N Worker nodes per zone (default: 1)
6275
--force Force recreate existing cluster
6376
--debug Enable debug output
6477
```
6578

79+
## Multi-Zone Simulation
80+
81+
Simulate Kubernetes availability zones by distributing nodes across zones with standard topology labels.
82+
83+
```bash
84+
# 3 zones, 1 worker per zone (3 CPs + 3 workers = 6 nodes)
85+
./kind-cluster.sh create --zones 3
86+
87+
# 2 zones, 3 workers per zone (2 CPs + 6 workers = 8 nodes)
88+
./kind-cluster.sh create --zones 2 --nodes-per-zone 3
89+
90+
# Via environment variables
91+
ZONES=3 NODES_PER_ZONE=2 ./kind-cluster.sh create
92+
```
93+
94+
When `--zones` is specified:
95+
- One control-plane node is created per zone
96+
- Worker nodes are distributed round-robin across zones
97+
- `--workers` and `--control-planes` flags are ignored with a warning
98+
- Each node gets labels: `topology.kubernetes.io/zone=zoneN` and `rack-key=zoneN`
99+
100+
Check zone distribution with `status`:
101+
102+
```bash
103+
./kind-cluster.sh status
104+
# Zones:
105+
# zone0: kind-control-plane, kind-worker, kind-worker4
106+
# zone1: kind-control-plane2, kind-worker2, kind-worker5
107+
```
108+
66109
## Examples
67110

68111
```bash
@@ -91,6 +134,8 @@ CONTROL_NODES=3 WORKER_NODES=5 ./kind-cluster.sh create
91134
| `IP_FAMILY` | ipv4 | IP family |
92135
| `DOCKER_CMD` | docker | Container runtime |
93136
| `REGISTRY_PORT` | 5001 | Registry port |
137+
| `ZONES` | 0 | Number of zones |
138+
| `NODES_PER_ZONE` | 1 | Workers per zone |
94139

95140
## Using the Local Registry
96141

build.sh

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
#!/usr/bin/env bash
2+
# =============================================================================
3+
# build.sh - Bundle kind-cluster.sh and lib files into a single distribution
4+
# =============================================================================
5+
6+
set -euo pipefail
7+
8+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9+
readonly SCRIPT_DIR
10+
11+
OUTPUT_DIR="${SCRIPT_DIR}/dist"
12+
OUTPUT_FILE="${OUTPUT_DIR}/kind-cluster.sh"
13+
14+
# =============================================================================
15+
# Utility Functions
16+
# =============================================================================
17+
18+
info() {
19+
echo "[INFO] $*" >&2
20+
}
21+
22+
err() {
23+
echo "[ERROR] $*" >&2
24+
}
25+
26+
# =============================================================================
27+
# Build Logic
28+
# =============================================================================
29+
30+
build_bundle() {
31+
local main_script="${SCRIPT_DIR}/kind-cluster.sh"
32+
local lib_dir="${SCRIPT_DIR}/lib"
33+
34+
# Validate input files exist
35+
if [[ ! -f "${main_script}" ]]; then
36+
err "Main script not found: ${main_script}"
37+
exit 1
38+
fi
39+
40+
if [[ ! -d "${lib_dir}" ]]; then
41+
err "Library directory not found: ${lib_dir}"
42+
exit 1
43+
fi
44+
45+
# Create output directory
46+
mkdir -p "${OUTPUT_DIR}"
47+
48+
info "Building bundled script..."
49+
info " Input: ${main_script}"
50+
info " Output: ${OUTPUT_FILE}"
51+
52+
# Start writing to output file
53+
: > "${OUTPUT_FILE}" # Truncate/create file
54+
55+
local in_script_dir_block=false
56+
local line_num=0
57+
58+
# Process main script line by line
59+
while IFS= read -r line; do
60+
line_num=$((line_num + 1))
61+
62+
# Track SCRIPT_DIR block (assignment + readonly)
63+
if [[ "${line}" =~ ^SCRIPT_DIR= ]]; then
64+
in_script_dir_block=true
65+
continue # Skip this line
66+
fi
67+
68+
if [[ "${in_script_dir_block}" == "true" ]] && [[ "${line}" =~ ^readonly[[:space:]]+SCRIPT_DIR ]]; then
69+
in_script_dir_block=false
70+
continue # Skip this line
71+
fi
72+
73+
# Skip shellcheck source directives for lib files
74+
if [[ "${line}" =~ ^#[[:space:]]*shellcheck[[:space:]]+source=./lib/ ]]; then
75+
continue
76+
fi
77+
78+
# Inline library files when we hit a source line
79+
if [[ "${line}" =~ ^source[[:space:]]+.*SCRIPT_DIR.*/lib/(.+)\.sh ]]; then
80+
local lib_file="${BASH_REMATCH[1]}.sh"
81+
local lib_path="${lib_dir}/${lib_file}"
82+
83+
if [[ ! -f "${lib_path}" ]]; then
84+
err "Library file not found: ${lib_path}"
85+
exit 1
86+
fi
87+
88+
info " Inlining: lib/${lib_file}"
89+
90+
# Add a comment marker
91+
echo "" >> "${OUTPUT_FILE}"
92+
echo "# ==============================================================================" >> "${OUTPUT_FILE}"
93+
echo "# Inlined from lib/${lib_file}" >> "${OUTPUT_FILE}"
94+
echo "# ==============================================================================" >> "${OUTPUT_FILE}"
95+
96+
# Process library file
97+
local in_lib=false
98+
while IFS= read -r lib_line; do
99+
# Skip shebang
100+
if [[ "${lib_line}" =~ ^#!/ ]]; then
101+
continue
102+
fi
103+
104+
# Skip sourcing guard (both lines)
105+
if [[ "${lib_line}" =~ ^\[\[[[:space:]]-n[[:space:]]+.*_LOADED.*return[[:space:]]+0 ]]; then
106+
continue
107+
fi
108+
if [[ "${lib_line}" =~ ^readonly[[:space:]]+_.*_LOADED=1 ]]; then
109+
continue
110+
fi
111+
112+
# Skip _*_LIB_DIR assignments
113+
if [[ "${lib_line}" =~ ^_.*_LIB_DIR= ]]; then
114+
continue
115+
fi
116+
117+
# Skip shellcheck directives for common.sh
118+
if [[ "${lib_line}" =~ ^#[[:space:]]*shellcheck[[:space:]]+source=./common.sh ]]; then
119+
continue
120+
fi
121+
122+
# Skip source lines to common.sh
123+
if [[ "${lib_line}" =~ ^source[[:space:]]+.*_LIB_DIR.*/common.sh ]]; then
124+
continue
125+
fi
126+
127+
# Write the line
128+
echo "${lib_line}" >> "${OUTPUT_FILE}"
129+
done < "${lib_path}"
130+
131+
echo "" >> "${OUTPUT_FILE}"
132+
continue
133+
fi
134+
135+
# Write the line from main script
136+
echo "${line}" >> "${OUTPUT_FILE}"
137+
done < "${main_script}"
138+
139+
# Make executable
140+
chmod +x "${OUTPUT_FILE}"
141+
142+
# Get file size
143+
local file_size
144+
if [[ "$(uname)" == "Darwin" ]]; then
145+
file_size=$(stat -f%z "${OUTPUT_FILE}")
146+
else
147+
file_size=$(stat -c%s "${OUTPUT_FILE}")
148+
fi
149+
150+
info "Build complete!"
151+
info " Output: ${OUTPUT_FILE}"
152+
info " Size: ${file_size} bytes"
153+
}
154+
155+
# =============================================================================
156+
# Main Entry Point
157+
# =============================================================================
158+
159+
main() {
160+
build_bundle
161+
}
162+
163+
main "$@"

0 commit comments

Comments
 (0)