816 lines
23 KiB
Plaintext
816 lines
23 KiB
Plaintext
|
|
#!/usr/bin/env nu
|
||
|
|
|
||
|
|
# Taskserv Creation Helper Tool
|
||
|
|
# Modern Nushell-compatible tool for creating taskservs with guided setup
|
||
|
|
|
||
|
|
use ../core/nulib/taskservs/discover.nu *
|
||
|
|
|
||
|
|
# Main command dispatcher
|
||
|
|
def main [
|
||
|
|
command?: string # Command: create, interactive, template, discover, help
|
||
|
|
name?: string # Taskserv name (for create command)
|
||
|
|
--category: string # Taskserv category
|
||
|
|
--port: int = 8080 # Default port
|
||
|
|
--description: string = "" # Service description
|
||
|
|
--author: string = "Developer" # Author name
|
||
|
|
--template: string = "basic" # Template type
|
||
|
|
--output: string = "provisioning/extensions" # Output directory
|
||
|
|
] {
|
||
|
|
match $command {
|
||
|
|
"create" => {
|
||
|
|
if ($name | is-empty) {
|
||
|
|
error make { msg: "Taskserv name is required for create command" }
|
||
|
|
}
|
||
|
|
create_taskserv $name $category $port $description $author $output
|
||
|
|
}
|
||
|
|
"interactive" | null => {
|
||
|
|
interactive_create
|
||
|
|
}
|
||
|
|
"template" => {
|
||
|
|
if ($name | is-empty) {
|
||
|
|
create_workspace_template
|
||
|
|
} else {
|
||
|
|
create_workspace_template $name
|
||
|
|
}
|
||
|
|
}
|
||
|
|
"discover" => {
|
||
|
|
show_discovery_info
|
||
|
|
}
|
||
|
|
"help" => {
|
||
|
|
show_help
|
||
|
|
}
|
||
|
|
_ => {
|
||
|
|
print $"Unknown command: ($command)"
|
||
|
|
show_help
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# Interactive taskserv creation
|
||
|
|
def interactive_create [] {
|
||
|
|
print "🚀 Interactive Taskserv Creator"
|
||
|
|
print ""
|
||
|
|
|
||
|
|
# Get basic information
|
||
|
|
let name = input "📝 Enter taskserv name (kebab-case, e.g., 'my-api'):"
|
||
|
|
|
||
|
|
if ($name | is-empty) or ($name | str contains " ") {
|
||
|
|
error make { msg: "Taskserv name must be kebab-case without spaces" }
|
||
|
|
}
|
||
|
|
|
||
|
|
# Select category
|
||
|
|
let categories = [
|
||
|
|
"container-runtime"
|
||
|
|
"databases"
|
||
|
|
"development"
|
||
|
|
"infrastructure"
|
||
|
|
"kubernetes"
|
||
|
|
"networking"
|
||
|
|
"storage"
|
||
|
|
]
|
||
|
|
|
||
|
|
print ""
|
||
|
|
print "📂 Available categories:"
|
||
|
|
for i in 0..($categories | length) {
|
||
|
|
let cat = ($categories | get $i)
|
||
|
|
print $" ($i + 1). ($cat)"
|
||
|
|
}
|
||
|
|
|
||
|
|
let category_choice = input "Select category (1-7):"
|
||
|
|
let category_index = (($category_choice | into int) - 1)
|
||
|
|
|
||
|
|
if $category_index < 0 or $category_index >= ($categories | length) {
|
||
|
|
error make { msg: "Invalid category selection" }
|
||
|
|
}
|
||
|
|
|
||
|
|
let category = ($categories | get $category_index)
|
||
|
|
|
||
|
|
# Get additional info
|
||
|
|
let description = input $"📄 Enter description for ($name) (optional):"
|
||
|
|
let author = input "👤 Enter author name (optional):" --default "Developer"
|
||
|
|
|
||
|
|
# Service type specific questions
|
||
|
|
let port = match $category {
|
||
|
|
"databases" => {
|
||
|
|
let db_ports = {
|
||
|
|
"postgres": 5432,
|
||
|
|
"redis": 6379,
|
||
|
|
"mysql": 3306,
|
||
|
|
"mongodb": 27017
|
||
|
|
}
|
||
|
|
if ($name | str contains "postgres") { 5432 }
|
||
|
|
else if ($name | str contains "redis") { 6379 }
|
||
|
|
else if ($name | str contains "mysql") { 3306 }
|
||
|
|
else if ($name | str contains "mongo") { 27017 }
|
||
|
|
else { 5432 }
|
||
|
|
}
|
||
|
|
"development" => {
|
||
|
|
if ($name | str contains "api") or ($name | str contains "web") { 8080 }
|
||
|
|
else { 3000 }
|
||
|
|
}
|
||
|
|
_ => 8080
|
||
|
|
}
|
||
|
|
|
||
|
|
let port_input = input $"🔌 Enter port number (default: ($port)):"
|
||
|
|
let final_port = if ($port_input | is-empty) { $port } else { $port_input | into int }
|
||
|
|
|
||
|
|
print ""
|
||
|
|
print "📋 Creating taskserv with:"
|
||
|
|
print $" Name: ($name)"
|
||
|
|
print $" Category: ($category)"
|
||
|
|
print $" Port: ($final_port)"
|
||
|
|
print $" Description: ($description)"
|
||
|
|
print $" Author: ($author)"
|
||
|
|
print ""
|
||
|
|
|
||
|
|
let confirm = input "✅ Proceed with creation? (y/N):"
|
||
|
|
if not ($confirm | str downcase | str starts-with "y") {
|
||
|
|
print "❌ Creation cancelled"
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
create_taskserv $name $category $final_port $description $author "provisioning/extensions"
|
||
|
|
}
|
||
|
|
|
||
|
|
# Create taskserv with parameters
|
||
|
|
def create_taskserv [
|
||
|
|
name: string
|
||
|
|
category: string
|
||
|
|
port: int
|
||
|
|
description: string
|
||
|
|
author: string
|
||
|
|
output_dir: string
|
||
|
|
] {
|
||
|
|
print $"🛠️ Creating taskserv: ($name)"
|
||
|
|
|
||
|
|
# Validate name format
|
||
|
|
if ($name | str contains " ") or ($name | str contains "_") or ($name != ($name | str downcase)) {
|
||
|
|
error make { msg: "Name must be kebab-case (lowercase with hyphens)" }
|
||
|
|
}
|
||
|
|
|
||
|
|
# Create directory structure
|
||
|
|
let taskserv_path = ($output_dir | path join "taskservs" $category $name)
|
||
|
|
let kcl_path = ($taskserv_path | path join "kcl")
|
||
|
|
let default_path = ($taskserv_path | path join "default")
|
||
|
|
|
||
|
|
print $"📁 Creating directories..."
|
||
|
|
mkdir $kcl_path
|
||
|
|
mkdir $default_path
|
||
|
|
|
||
|
|
# Generate variables for templates
|
||
|
|
let variables = generate_variables $name $category $port $description $author
|
||
|
|
|
||
|
|
# Create files
|
||
|
|
create_kcl_mod $kcl_path $variables
|
||
|
|
create_main_schema $kcl_path $variables
|
||
|
|
create_version_file $kcl_path $variables
|
||
|
|
create_defaults_toml $default_path $variables
|
||
|
|
create_install_script $default_path $variables
|
||
|
|
create_readme $taskserv_path $variables
|
||
|
|
|
||
|
|
print $"✅ Taskserv created successfully at: ($taskserv_path)"
|
||
|
|
print ""
|
||
|
|
print "🔄 Next steps:"
|
||
|
|
print "1. Customize the configuration in the .k files"
|
||
|
|
print "2. Update the installation script"
|
||
|
|
print "3. Test discovery:"
|
||
|
|
print $" nu -c \"use provisioning/core/nulib/taskservs/discover.nu *; get-taskserv-info ($name)\""
|
||
|
|
print "4. Create a workspace template (optional):"
|
||
|
|
print $" nu provisioning/tools/create-taskserv-helper.nu template ($name)"
|
||
|
|
|
||
|
|
# Show layer resolution test
|
||
|
|
print ""
|
||
|
|
print "🧪 Test layer resolution:"
|
||
|
|
print $" nu -c \"use provisioning/workspace/tools/layer-utils.nu *; test_layer_resolution ($name) wuji upcloud\""
|
||
|
|
}
|
||
|
|
|
||
|
|
# Generate template variables
|
||
|
|
def generate_variables [
|
||
|
|
name: string
|
||
|
|
category: string
|
||
|
|
port: int
|
||
|
|
description: string
|
||
|
|
author: string
|
||
|
|
]: nothing -> record {
|
||
|
|
let name_pascal = ($name | split row "-" | each { |word| $word | str capitalize } | str join "")
|
||
|
|
let name_snake = ($name | str replace -a "-" "_")
|
||
|
|
let display_name = ($name | split row "-" | each { |word| $word | str capitalize } | str join " ")
|
||
|
|
|
||
|
|
let final_description = if ($description | is-empty) {
|
||
|
|
$"Deployment and management for ($display_name)"
|
||
|
|
} else {
|
||
|
|
$description
|
||
|
|
}
|
||
|
|
|
||
|
|
{
|
||
|
|
name: $name,
|
||
|
|
name_pascal: $name_pascal,
|
||
|
|
name_snake: $name_snake,
|
||
|
|
display_name: $display_name,
|
||
|
|
category: $category,
|
||
|
|
port: $port,
|
||
|
|
description: $final_description,
|
||
|
|
author: $author,
|
||
|
|
date: (date now | format date "%Y-%m-%d"),
|
||
|
|
version: "1.0.0"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# Create kcl.mod file
|
||
|
|
def create_kcl_mod [kcl_path: string, vars: record] {
|
||
|
|
let content = $"[package]
|
||
|
|
name = \"($vars.name)\"
|
||
|
|
version = \"($vars.version)\"
|
||
|
|
description = \"($vars.description)\"
|
||
|
|
authors = [\"($vars.author)\"]
|
||
|
|
|
||
|
|
[dependencies]
|
||
|
|
k8s = { oci = \"oci://ghcr.io/kcl-lang/k8s\", tag = \"1.30\" }
|
||
|
|
"
|
||
|
|
|
||
|
|
$content | save ($kcl_path | path join "kcl.mod")
|
||
|
|
print $" ✓ Created kcl.mod"
|
||
|
|
}
|
||
|
|
|
||
|
|
# Create main KCL schema
|
||
|
|
def create_main_schema [kcl_path: string, vars: record] {
|
||
|
|
let content = $"# ($vars.display_name) Taskserv Configuration
|
||
|
|
# ($vars.description)
|
||
|
|
|
||
|
|
schema ($vars.name_pascal) {
|
||
|
|
# Service metadata
|
||
|
|
name: str = \"($vars.name)\"
|
||
|
|
version: str = \"latest\"
|
||
|
|
namespace: str = \"default\"
|
||
|
|
|
||
|
|
# Service configuration
|
||
|
|
replicas: int = 1
|
||
|
|
port: int = ($vars.port)
|
||
|
|
|
||
|
|
# Resource requirements
|
||
|
|
resources: {
|
||
|
|
cpu: str = \"100m\"
|
||
|
|
memory: str = \"128Mi\"
|
||
|
|
limits?: {
|
||
|
|
cpu?: str = \"500m\"
|
||
|
|
memory?: str = \"512Mi\"
|
||
|
|
}
|
||
|
|
} = {
|
||
|
|
cpu = \"100m\"
|
||
|
|
memory = \"128Mi\"
|
||
|
|
}
|
||
|
|
|
||
|
|
# Service specific configuration
|
||
|
|
config?: {str: any} = {}
|
||
|
|
|
||
|
|
# Health checks
|
||
|
|
health?: {
|
||
|
|
enabled: bool = true
|
||
|
|
path: str = \"/health\"
|
||
|
|
initial_delay: int = 30
|
||
|
|
period: int = 10
|
||
|
|
} = {
|
||
|
|
enabled = true
|
||
|
|
path = \"/health\"
|
||
|
|
initial_delay = 30
|
||
|
|
period = 10
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# Default configuration
|
||
|
|
($vars.name_snake)_config: ($vars.name_pascal) = ($vars.name_pascal) {
|
||
|
|
name = \"($vars.name)\"
|
||
|
|
version = \"latest\"
|
||
|
|
replicas = 1
|
||
|
|
port = ($vars.port)
|
||
|
|
}
|
||
|
|
"
|
||
|
|
|
||
|
|
$content | save ($kcl_path | path join $"($vars.name).k")
|
||
|
|
print $" ✓ Created ($vars.name).k"
|
||
|
|
}
|
||
|
|
|
||
|
|
# Create version file
|
||
|
|
def create_version_file [kcl_path: string, vars: record] {
|
||
|
|
let content = $"# Version information for ($vars.name) taskserv
|
||
|
|
|
||
|
|
schema ($vars.name_pascal)Version {
|
||
|
|
current: str = \"($vars.version)\"
|
||
|
|
compatible: [str] = [\"($vars.version)\"]
|
||
|
|
deprecated?: [str] = []
|
||
|
|
changelog?: {str: str} = {}
|
||
|
|
}
|
||
|
|
|
||
|
|
($vars.name_snake)_version: ($vars.name_pascal)Version = ($vars.name_pascal)Version {
|
||
|
|
current = \"($vars.version)\"
|
||
|
|
changelog = {
|
||
|
|
\"($vars.version)\" = \"Initial release\"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
"
|
||
|
|
|
||
|
|
$content | save ($kcl_path | path join "version.k")
|
||
|
|
print $" ✓ Created version.k"
|
||
|
|
}
|
||
|
|
|
||
|
|
# Create defaults TOML
|
||
|
|
def create_defaults_toml [default_path: string, vars: record] {
|
||
|
|
let content = $"# Default configuration for ($vars.name)
|
||
|
|
# Generated on ($vars.date)
|
||
|
|
|
||
|
|
[service]
|
||
|
|
name = \"($vars.name)\"
|
||
|
|
version = \"latest\"
|
||
|
|
port = ($vars.port)
|
||
|
|
replicas = 1
|
||
|
|
|
||
|
|
[deployment]
|
||
|
|
strategy = \"RollingUpdate\"
|
||
|
|
max_unavailable = 1
|
||
|
|
max_surge = 1
|
||
|
|
|
||
|
|
[resources]
|
||
|
|
cpu_request = \"100m\"
|
||
|
|
cpu_limit = \"500m\"
|
||
|
|
memory_request = \"128Mi\"
|
||
|
|
memory_limit = \"512Mi\"
|
||
|
|
|
||
|
|
[health]
|
||
|
|
enabled = true
|
||
|
|
path = \"/health\"
|
||
|
|
initial_delay_seconds = 30
|
||
|
|
period_seconds = 10
|
||
|
|
timeout_seconds = 5
|
||
|
|
|
||
|
|
[networking]
|
||
|
|
service_type = \"ClusterIP\"
|
||
|
|
expose_metrics = false
|
||
|
|
metrics_port = 9090
|
||
|
|
"
|
||
|
|
|
||
|
|
$content | save ($default_path | path join "defs.toml")
|
||
|
|
print $" ✓ Created defs.toml"
|
||
|
|
}
|
||
|
|
|
||
|
|
# Create installation script
|
||
|
|
def create_install_script [default_path: string, vars: record] {
|
||
|
|
let content = $"#!/bin/bash
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
# ($vars.display_name) Installation Script
|
||
|
|
# Generated on ($vars.date)
|
||
|
|
|
||
|
|
echo \"🚀 Installing ($vars.name)...\"
|
||
|
|
|
||
|
|
# Configuration
|
||
|
|
SERVICE_NAME=\"${SERVICE_NAME:-($vars.name)}\"
|
||
|
|
SERVICE_VERSION=\"${SERVICE_VERSION:-latest}\"
|
||
|
|
NAMESPACE=\"${NAMESPACE:-default}\"
|
||
|
|
REPLICAS=\"${REPLICAS:-1}\"
|
||
|
|
PORT=\"${PORT:-($vars.port)}\"
|
||
|
|
|
||
|
|
# Validation
|
||
|
|
if [[ -z \"$SERVICE_NAME\" ]]; then
|
||
|
|
echo \"❌ SERVICE_NAME is required\"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo \"📋 Configuration:\"
|
||
|
|
echo \" Service: $SERVICE_NAME\"
|
||
|
|
echo \" Version: $SERVICE_VERSION\"
|
||
|
|
echo \" Namespace: $NAMESPACE\"
|
||
|
|
echo \" Port: $PORT\"
|
||
|
|
echo \" Replicas: $REPLICAS\"
|
||
|
|
|
||
|
|
# Create namespace if it doesn't exist
|
||
|
|
echo \"🏗️ Creating namespace...\"
|
||
|
|
kubectl create namespace \"$NAMESPACE\" --dry-run=client -o yaml | kubectl apply -f -
|
||
|
|
|
||
|
|
# Apply deployment
|
||
|
|
echo \"🚢 Applying deployment...\"
|
||
|
|
cat <<EOF | envsubst | kubectl apply -f -
|
||
|
|
apiVersion: apps/v1
|
||
|
|
kind: Deployment
|
||
|
|
metadata:
|
||
|
|
name: $SERVICE_NAME
|
||
|
|
namespace: $NAMESPACE
|
||
|
|
labels:
|
||
|
|
app: $SERVICE_NAME
|
||
|
|
spec:
|
||
|
|
replicas: $REPLICAS
|
||
|
|
selector:
|
||
|
|
matchLabels:
|
||
|
|
app: $SERVICE_NAME
|
||
|
|
template:
|
||
|
|
metadata:
|
||
|
|
labels:
|
||
|
|
app: $SERVICE_NAME
|
||
|
|
spec:
|
||
|
|
containers:
|
||
|
|
- name: $SERVICE_NAME
|
||
|
|
image: $SERVICE_NAME:$SERVICE_VERSION
|
||
|
|
ports:
|
||
|
|
- containerPort: $PORT
|
||
|
|
resources:
|
||
|
|
requests:
|
||
|
|
cpu: 100m
|
||
|
|
memory: 128Mi
|
||
|
|
limits:
|
||
|
|
cpu: 500m
|
||
|
|
memory: 512Mi
|
||
|
|
livenessProbe:
|
||
|
|
httpGet:
|
||
|
|
path: /health
|
||
|
|
port: $PORT
|
||
|
|
initialDelaySeconds: 30
|
||
|
|
periodSeconds: 10
|
||
|
|
readinessProbe:
|
||
|
|
httpGet:
|
||
|
|
path: /health
|
||
|
|
port: $PORT
|
||
|
|
initialDelaySeconds: 5
|
||
|
|
periodSeconds: 5
|
||
|
|
---
|
||
|
|
apiVersion: v1
|
||
|
|
kind: Service
|
||
|
|
metadata:
|
||
|
|
name: $SERVICE_NAME
|
||
|
|
namespace: $NAMESPACE
|
||
|
|
labels:
|
||
|
|
app: $SERVICE_NAME
|
||
|
|
spec:
|
||
|
|
selector:
|
||
|
|
app: $SERVICE_NAME
|
||
|
|
ports:
|
||
|
|
- port: $PORT
|
||
|
|
targetPort: $PORT
|
||
|
|
type: ClusterIP
|
||
|
|
EOF
|
||
|
|
|
||
|
|
# Wait for deployment
|
||
|
|
echo \"⏳ Waiting for deployment to be ready...\"
|
||
|
|
kubectl wait --for=condition=available --timeout=300s deployment/$SERVICE_NAME -n $NAMESPACE
|
||
|
|
|
||
|
|
echo \"✅ ($vars.display_name) installed successfully\"
|
||
|
|
echo \"🔍 Check status with: kubectl get pods -n $NAMESPACE -l app=$SERVICE_NAME\"
|
||
|
|
"
|
||
|
|
|
||
|
|
$content | save ($default_path | path join $"install-($vars.name).sh")
|
||
|
|
|
||
|
|
# Make script executable
|
||
|
|
chmod +x ($default_path | path join $"install-($vars.name).sh")
|
||
|
|
print $" ✓ Created install-($vars.name).sh"
|
||
|
|
}
|
||
|
|
|
||
|
|
# Create README
|
||
|
|
def create_readme [taskserv_path: string, vars: record] {
|
||
|
|
let content = $"# ($vars.display_name) Taskserv
|
||
|
|
|
||
|
|
($vars.description)
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
This taskserv provides deployment and management capabilities for ($vars.display_name) in Kubernetes environments.
|
||
|
|
|
||
|
|
## Configuration
|
||
|
|
|
||
|
|
### Basic Configuration
|
||
|
|
|
||
|
|
```kcl
|
||
|
|
import taskservs.($vars.category).($vars.name).kcl.($vars.name) as ($vars.name_snake)
|
||
|
|
|
||
|
|
($vars.name_snake)_config: ($vars.name_snake).($vars.name_pascal) = ($vars.name_snake).($vars.name_snake)_config {
|
||
|
|
# Customize configuration
|
||
|
|
version = \"1.2.3\"
|
||
|
|
replicas = 2
|
||
|
|
port = ($vars.port)
|
||
|
|
|
||
|
|
resources = {
|
||
|
|
cpu = \"200m\"
|
||
|
|
memory = \"256Mi\"
|
||
|
|
limits = {
|
||
|
|
cpu = \"1000m\"
|
||
|
|
memory = \"1Gi\"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Advanced Configuration
|
||
|
|
|
||
|
|
```kcl
|
||
|
|
($vars.name_snake)_production: ($vars.name_snake).($vars.name_pascal) = ($vars.name_snake).($vars.name_snake)_config {
|
||
|
|
# Production settings
|
||
|
|
replicas = 3
|
||
|
|
|
||
|
|
resources = {
|
||
|
|
cpu = \"500m\"
|
||
|
|
memory = \"512Mi\"
|
||
|
|
limits = {
|
||
|
|
cpu = \"2000m\"
|
||
|
|
memory = \"2Gi\"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
health = {
|
||
|
|
enabled = true
|
||
|
|
path = \"/healthz\"
|
||
|
|
initial_delay = 60
|
||
|
|
period = 15
|
||
|
|
}
|
||
|
|
|
||
|
|
config = {
|
||
|
|
\"log_level\" = \"info\"
|
||
|
|
\"metrics_enabled\" = \"true\"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Usage
|
||
|
|
|
||
|
|
### Deploy with Provisioning System
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Deploy to infrastructure
|
||
|
|
provisioning/core/cli/provisioning taskserv create ($vars.name) --infra my-infra --check
|
||
|
|
|
||
|
|
# Generate configuration
|
||
|
|
provisioning/core/cli/provisioning taskserv generate ($vars.name) --infra my-infra
|
||
|
|
```
|
||
|
|
|
||
|
|
### Direct Installation
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Set environment variables
|
||
|
|
export SERVICE_VERSION=\"1.2.3\"
|
||
|
|
export NAMESPACE=\"production\"
|
||
|
|
export REPLICAS=\"3\"
|
||
|
|
|
||
|
|
# Run installation script
|
||
|
|
cd provisioning/extensions/taskservs/($vars.category)/($vars.name)/default
|
||
|
|
./install-($vars.name).sh
|
||
|
|
```
|
||
|
|
|
||
|
|
## Configuration Options
|
||
|
|
|
||
|
|
| Option | Type | Default | Description |
|
||
|
|
|--------|------|---------|-------------|
|
||
|
|
| `name` | str | `($vars.name)` | Service name |
|
||
|
|
| `version` | str | `latest` | Container image version |
|
||
|
|
| `namespace` | str | `default` | Kubernetes namespace |
|
||
|
|
| `replicas` | int | `1` | Number of replicas |
|
||
|
|
| `port` | int | `($vars.port)` | Service port |
|
||
|
|
| `resources.cpu` | str | `100m` | CPU request |
|
||
|
|
| `resources.memory` | str | `128Mi` | Memory request |
|
||
|
|
| `health.enabled` | bool | `true` | Enable health checks |
|
||
|
|
| `health.path` | str | `/health` | Health check endpoint |
|
||
|
|
| `config` | object | `{}` | Additional configuration |
|
||
|
|
|
||
|
|
## Dependencies
|
||
|
|
|
||
|
|
- Kubernetes cluster
|
||
|
|
- kubectl configured
|
||
|
|
- Container image: `($vars.name):latest`
|
||
|
|
|
||
|
|
## Troubleshooting
|
||
|
|
|
||
|
|
### Check Pod Status
|
||
|
|
```bash
|
||
|
|
kubectl get pods -n <namespace> -l app=($vars.name)
|
||
|
|
kubectl describe pod <pod-name> -n <namespace>
|
||
|
|
```
|
||
|
|
|
||
|
|
### View Logs
|
||
|
|
```bash
|
||
|
|
kubectl logs -f deployment/($vars.name) -n <namespace>
|
||
|
|
```
|
||
|
|
|
||
|
|
### Debug Configuration
|
||
|
|
```bash
|
||
|
|
# Test KCL configuration
|
||
|
|
kcl run provisioning/extensions/taskservs/($vars.category)/($vars.name)/kcl/($vars.name).k
|
||
|
|
|
||
|
|
# Validate deployment
|
||
|
|
provisioning/core/cli/provisioning taskserv create ($vars.name) --infra <infra> --check
|
||
|
|
```
|
||
|
|
|
||
|
|
### Common Issues
|
||
|
|
|
||
|
|
1. **Pod not starting**: Check resource requests and image availability
|
||
|
|
2. **Health check failures**: Verify health check endpoint and timing
|
||
|
|
3. **Service not accessible**: Check service configuration and network policies
|
||
|
|
|
||
|
|
## Development
|
||
|
|
|
||
|
|
### Layer Resolution
|
||
|
|
This taskserv supports the 3-layer architecture:
|
||
|
|
|
||
|
|
1. **Core Layer**: Base configuration in this directory
|
||
|
|
2. **Workspace Layer**: Templates in `provisioning/workspace/templates/taskservs/($vars.category)/($vars.name).k`
|
||
|
|
3. **Infrastructure Layer**: Overrides in `workspace/infra/<infra>/task-servs/($vars.name).k`
|
||
|
|
|
||
|
|
### Testing
|
||
|
|
```bash
|
||
|
|
# Test layer resolution
|
||
|
|
nu -c \"use provisioning/workspace/tools/layer-utils.nu *; test_layer_resolution ($vars.name) <infra> <provider>\"
|
||
|
|
|
||
|
|
# Discover taskserv
|
||
|
|
nu -c \"use provisioning/core/nulib/taskservs/discover.nu *; get-taskserv-info ($vars.name)\"
|
||
|
|
```
|
||
|
|
|
||
|
|
## Contributing
|
||
|
|
|
||
|
|
1. Follow the taskserv development guidelines
|
||
|
|
2. Update version information when making changes
|
||
|
|
3. Test across different environments
|
||
|
|
4. Update this README with any new configuration options
|
||
|
|
|
||
|
|
## License
|
||
|
|
|
||
|
|
MIT License
|
||
|
|
|
||
|
|
## Author
|
||
|
|
|
||
|
|
($vars.author)
|
||
|
|
|
||
|
|
## Generated
|
||
|
|
|
||
|
|
Created on ($vars.date) using the Taskserv Helper Tool.
|
||
|
|
"
|
||
|
|
|
||
|
|
$content | save ($taskserv_path | path join "README.md")
|
||
|
|
print $" ✓ Created README.md"
|
||
|
|
}
|
||
|
|
|
||
|
|
# Create workspace template
|
||
|
|
def create_workspace_template [name?: string] {
|
||
|
|
if ($name == null) or ($name | is-empty) {
|
||
|
|
print "📋 Create workspace template for existing taskserv"
|
||
|
|
let taskservs = (discover-taskservs | select name category)
|
||
|
|
|
||
|
|
print "Available taskservs:"
|
||
|
|
for i in 0..($taskservs | length | $in - 1) {
|
||
|
|
let ts = ($taskservs | get $i)
|
||
|
|
print $" ($i + 1). ($ts.name) (($ts.category))"
|
||
|
|
}
|
||
|
|
|
||
|
|
let choice = input "Select taskserv number:"
|
||
|
|
let index = (($choice | into int) - 1)
|
||
|
|
|
||
|
|
if $index < 0 or $index >= ($taskservs | length) {
|
||
|
|
error make { msg: "Invalid selection" }
|
||
|
|
}
|
||
|
|
|
||
|
|
let selected = ($taskservs | get $index)
|
||
|
|
create_template_for_taskserv $selected.name $selected.category
|
||
|
|
} else {
|
||
|
|
let taskserv_info = get-taskserv-info $name
|
||
|
|
create_template_for_taskserv $taskserv_info.name $taskserv_info.group
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# Create template for specific taskserv
|
||
|
|
def create_template_for_taskserv [name: string, category: string] {
|
||
|
|
print $"📝 Creating workspace template for ($name)"
|
||
|
|
|
||
|
|
let template_dir = ("provisioning/workspace/templates/taskservs" | path join $category)
|
||
|
|
let template_file = ($template_dir | path join $"($name).k")
|
||
|
|
|
||
|
|
mkdir $template_dir
|
||
|
|
|
||
|
|
let name_snake = ($name | str replace -a "-" "_")
|
||
|
|
let name_pascal = ($name | str replace -a "-" " " | str title-case | str replace -a " " "")
|
||
|
|
|
||
|
|
let content = $"# Workspace template for ($name) taskserv
|
||
|
|
import taskservs.($category).($name).kcl.($name) as base
|
||
|
|
|
||
|
|
# Template configuration extending base
|
||
|
|
($name_snake)_template: base.($name_pascal) = base.($name_snake)_config {
|
||
|
|
# Template customizations for workspace layer
|
||
|
|
# These can be overridden at the infrastructure layer
|
||
|
|
|
||
|
|
# Common template settings
|
||
|
|
version = \"stable\"
|
||
|
|
|
||
|
|
# Adjust for template environment
|
||
|
|
replicas = 2 # Default for multi-replica setup
|
||
|
|
|
||
|
|
# Template resource defaults
|
||
|
|
resources = base.($name_snake)_config.resources {
|
||
|
|
cpu = \"200m\"
|
||
|
|
memory = \"256Mi\"
|
||
|
|
limits = {
|
||
|
|
cpu = \"1000m\"
|
||
|
|
memory = \"1Gi\"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# Template-level configuration
|
||
|
|
config = {
|
||
|
|
\"environment\" = \"template\"
|
||
|
|
\"log_level\" = \"info\"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
"
|
||
|
|
|
||
|
|
$content | save $template_file
|
||
|
|
print $"✅ Created workspace template: ($template_file)"
|
||
|
|
|
||
|
|
print ""
|
||
|
|
print "🧪 Test the template:"
|
||
|
|
print $" nu -c \"use provisioning/workspace/tools/layer-utils.nu *; test_layer_resolution ($name) <infra> <provider>\""
|
||
|
|
}
|
||
|
|
|
||
|
|
# Show discovery information
|
||
|
|
def show_discovery_info [] {
|
||
|
|
print "🔍 Taskserv Discovery Information"
|
||
|
|
print ""
|
||
|
|
|
||
|
|
let taskservs = discover-taskservs
|
||
|
|
let total = ($taskservs | length)
|
||
|
|
let by_group = ($taskservs | group-by group | transpose group taskservs | each { |row| {group: $row.group, count: ($row.taskservs | length)} })
|
||
|
|
|
||
|
|
print $"📊 Total taskservs discovered: ($total)"
|
||
|
|
print ""
|
||
|
|
print "📂 By category:"
|
||
|
|
|
||
|
|
for group_info in $by_group {
|
||
|
|
print $" ($group_info.group): ($group_info.count) taskservs"
|
||
|
|
let group_taskservs = ($taskservs | where group == $group_info.group | get name)
|
||
|
|
for taskserv in $group_taskservs {
|
||
|
|
print $" • ($taskserv)"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
print ""
|
||
|
|
print "🛠️ Available commands:"
|
||
|
|
print " nu -c \"use provisioning/core/nulib/taskservs/discover.nu *; discover-taskservs\""
|
||
|
|
print " nu -c \"use provisioning/core/nulib/taskservs/discover.nu *; search-taskservs <query>\""
|
||
|
|
print " nu -c \"use provisioning/workspace/tools/layer-utils.nu *; show_layer_stats\""
|
||
|
|
}
|
||
|
|
|
||
|
|
# Show help information
|
||
|
|
def show_help [] {
|
||
|
|
print "🚀 Taskserv Helper Tool"
|
||
|
|
print ""
|
||
|
|
print "USAGE:"
|
||
|
|
print " nu provisioning/tools/create-taskserv-helper.nu <command> [options]"
|
||
|
|
print ""
|
||
|
|
print "COMMANDS:"
|
||
|
|
print " interactive Launch interactive taskserv creator"
|
||
|
|
print " create <name> Create taskserv with specified name"
|
||
|
|
print " template [name] Create workspace template for taskserv"
|
||
|
|
print " discover Show discovery information"
|
||
|
|
print " help Show this help message"
|
||
|
|
print ""
|
||
|
|
print "CREATE OPTIONS:"
|
||
|
|
print " --category <cat> Taskserv category (required for create)"
|
||
|
|
print " --port <port> Service port (default: 8080)"
|
||
|
|
print " --description <desc> Service description"
|
||
|
|
print " --author <author> Author name (default: Developer)"
|
||
|
|
print " --output <dir> Output directory (default: provisioning/extensions)"
|
||
|
|
print ""
|
||
|
|
print "CATEGORIES:"
|
||
|
|
print " container-runtime Container runtime engines"
|
||
|
|
print " databases Database services"
|
||
|
|
print " development Development tools"
|
||
|
|
print " infrastructure System infrastructure"
|
||
|
|
print " kubernetes Kubernetes orchestration"
|
||
|
|
print " networking Network services"
|
||
|
|
print " storage Storage solutions"
|
||
|
|
print ""
|
||
|
|
print "EXAMPLES:"
|
||
|
|
print " # Interactive creation"
|
||
|
|
print " nu provisioning/tools/create-taskserv-helper.nu interactive"
|
||
|
|
print ""
|
||
|
|
print " # Create API service"
|
||
|
|
print " nu provisioning/tools/create-taskserv-helper.nu create my-api \\"
|
||
|
|
print " --category development \\"
|
||
|
|
print " --port 8080 \\"
|
||
|
|
print " --description \"My REST API service\""
|
||
|
|
print ""
|
||
|
|
print " # Create database service"
|
||
|
|
print " nu provisioning/tools/create-taskserv-helper.nu create my-db \\"
|
||
|
|
print " --category databases \\"
|
||
|
|
print " --port 5432 \\"
|
||
|
|
print " --author \"Database Team\""
|
||
|
|
print ""
|
||
|
|
print " # Create workspace template"
|
||
|
|
print " nu provisioning/tools/create-taskserv-helper.nu template my-api"
|
||
|
|
print ""
|
||
|
|
print "📖 For more information, see:"
|
||
|
|
print " docs/development/TASKSERV_DEVELOPER_GUIDE.md"
|
||
|
|
print " docs/development/TASKSERV_QUICK_GUIDE.md"
|
||
|
|
}
|
||
|
|
|
||
|
|
# String utility functions
|
||
|
|
def "str title-case" [] {
|
||
|
|
let text = $in
|
||
|
|
$text | split row " " | each { |word|
|
||
|
|
if ($word | is-empty) {
|
||
|
|
$word
|
||
|
|
} else {
|
||
|
|
($word | str substring 0..1 | str upcase) + ($word | str substring 1..)
|
||
|
|
}
|
||
|
|
} | str join " "
|
||
|
|
}
|