feat: persistent custom labels

This commit is contained in:
2025-10-15 22:23:00 +02:00
parent 1a74d1fe90
commit 7063b1ab16
9 changed files with 320 additions and 1 deletions

214
ctl.sh
View File

@@ -15,6 +15,9 @@ source .env
## ota all <target> - OTA update all nodes in cluster
## cluster members - List cluster members
## node wifi <ssid> <password> [ip] - Configure WiFi on node
## node label set <key=value> [ip] - Set a label on node
## node label delete <key> [ip] - Delete a label from node
## node status [ip] - Get node status and information
## monitor - Monitor serial output
##
## Examples:
@@ -22,6 +25,11 @@ source .env
## ./ctl.sh flash d1_mini
## ./ctl.sh node wifi "MyNetwork" "MyPassword"
## ./ctl.sh node wifi "MyNetwork" "MyPassword" 192.168.1.100
## ./ctl.sh node label set "environment=production"
## ./ctl.sh node label set "location=office" 192.168.1.100
## ./ctl.sh node label delete "environment"
## ./ctl.sh node status
## ./ctl.sh node status 192.168.1.100
function info {
sed -n 's/^##//p' ctl.sh
@@ -161,6 +169,212 @@ function node {
return 1
fi
}
function label {
function set {
if [ $# -lt 1 ]; then
echo "Usage: $0 node label set <key=value> [node_ip]"
echo " key=value: Label key and value in format 'key=value'"
echo " node_ip: Optional IP address (defaults to API_NODE from .env)"
return 1
fi
local key_value="$1"
local node_ip="${2:-$API_NODE}"
# Parse key=value format
if [[ ! "$key_value" =~ ^[^=]+=.+$ ]]; then
echo "Error: Label must be in format 'key=value'"
echo "Example: environment=production"
return 1
fi
local key="${key_value%%=*}"
local value="${key_value#*=}"
echo "Setting label '$key=$value' on node $node_ip..."
# First get current labels
current_labels=$(curl -s "http://$node_ip/api/node/status" | jq -r '.labels // {}')
# Add/update the new label
updated_labels=$(echo "$current_labels" | jq --arg key "$key" --arg value "$value" '. + {($key): $value}')
# Send updated labels to the node
response=$(curl -s -w "\n%{http_code}" -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "labels=$updated_labels" \
"http://$node_ip/api/node/config" 2>/dev/null || echo -e "\n000")
# Extract HTTP status code and response body
http_code=$(echo "$response" | tail -n1)
response_body=$(echo "$response" | head -n -1)
# Check if curl succeeded
if [ "$http_code" = "000" ] || [ -z "$response_body" ]; then
echo "Error: Failed to connect to node at $node_ip"
echo "Please check:"
echo " - Node is powered on and connected to network"
echo " - IP address is correct"
echo " - Node is running Spore firmware"
return 1
fi
# Check HTTP status code
if [ "$http_code" != "200" ]; then
echo "Error: HTTP $http_code - Server error"
echo "Response: $response_body"
return 1
fi
# Parse and display the response
status=$(echo "$response_body" | jq -r '.status // "unknown"')
message=$(echo "$response_body" | jq -r '.message // "No message"')
echo "Status: $status"
echo "Message: $message"
# Return appropriate exit code
if [ "$status" = "success" ]; then
echo "Label '$key=$value' set successfully!"
return 0
else
echo "Failed to set label!"
return 1
fi
}
function delete {
if [ $# -lt 1 ]; then
echo "Usage: $0 node label delete <key> [node_ip]"
echo " key: Label key to delete"
echo " node_ip: Optional IP address (defaults to API_NODE from .env)"
return 1
fi
local key="$1"
local node_ip="${2:-$API_NODE}"
echo "Deleting label '$key' from node $node_ip..."
# First get current labels
current_labels=$(curl -s "http://$node_ip/api/node/status" | jq -r '.labels // {}')
# Check if key exists
if [ "$(echo "$current_labels" | jq -r --arg key "$key" 'has($key)')" != "true" ]; then
echo "Warning: Label '$key' does not exist on node"
return 0
fi
# Remove the key
updated_labels=$(echo "$current_labels" | jq --arg key "$key" 'del(.[$key])')
# Send updated labels to the node
response=$(curl -s -w "\n%{http_code}" -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "labels=$updated_labels" \
"http://$node_ip/api/node/config" 2>/dev/null || echo -e "\n000")
# Extract HTTP status code and response body
http_code=$(echo "$response" | tail -n1)
response_body=$(echo "$response" | head -n -1)
# Check if curl succeeded
if [ "$http_code" = "000" ] || [ -z "$response_body" ]; then
echo "Error: Failed to connect to node at $node_ip"
echo "Please check:"
echo " - Node is powered on and connected to network"
echo " - IP address is correct"
echo " - Node is running Spore firmware"
return 1
fi
# Check HTTP status code
if [ "$http_code" != "200" ]; then
echo "Error: HTTP $http_code - Server error"
echo "Response: $response_body"
return 1
fi
# Parse and display the response
status=$(echo "$response_body" | jq -r '.status // "unknown"')
message=$(echo "$response_body" | jq -r '.message // "No message"')
echo "Status: $status"
echo "Message: $message"
# Return appropriate exit code
if [ "$status" = "success" ]; then
echo "Label '$key' deleted successfully!"
return 0
else
echo "Failed to delete label!"
return 1
fi
}
${@:-info}
}
function status {
local node_ip="${1:-$API_NODE}"
echo "Getting status for node $node_ip..."
# Get node status
response=$(curl -s -w "\n%{http_code}" "http://$node_ip/api/node/status" 2>/dev/null || echo -e "\n000")
# Extract HTTP status code and response body
http_code=$(echo "$response" | tail -n1)
response_body=$(echo "$response" | head -n -1)
# Check if curl succeeded
if [ "$http_code" = "000" ] || [ -z "$response_body" ]; then
echo "Error: Failed to connect to node at $node_ip"
echo "Please check:"
echo " - Node is powered on and connected to network"
echo " - IP address is correct"
echo " - Node is running Spore firmware"
return 1
fi
# Check HTTP status code
if [ "$http_code" != "200" ]; then
echo "Error: HTTP $http_code - Server error"
echo "Response: $response_body"
return 1
fi
# Parse and display the response in a nice format
echo ""
echo "=== Node Status ==="
echo "Hostname: $(echo "$response_body" | jq -r '.hostname // "N/A"')"
echo "IP Address: $node_ip"
echo "Free Heap: $(echo "$response_body" | jq -r '.freeHeap // "N/A"') bytes"
echo "Chip ID: $(echo "$response_body" | jq -r '.chipId // "N/A"')"
echo "SDK Version: $(echo "$response_body" | jq -r '.sdkVersion // "N/A"')"
echo "CPU Frequency: $(echo "$response_body" | jq -r '.cpuFreqMHz // "N/A"') MHz"
echo "Flash Size: $(echo "$response_body" | jq -r '.flashChipSize // "N/A"') bytes"
# Display labels if present
labels=$(echo "$response_body" | jq -r '.labels // {}')
if [ "$labels" != "{}" ] && [ "$labels" != "null" ]; then
echo ""
echo "=== Labels ==="
echo "$labels" | jq -r 'to_entries[] | "\(.key): \(.value)"'
else
echo ""
echo "=== Labels ==="
echo "No labels set"
fi
echo ""
echo "=== Raw JSON Response ==="
echo "$response_body" | jq '.'
return 0
}
${@:-info}
}