Files
higress/.claude/skills/nginx-to-higress-migration/scripts/generate-plugin-scaffold.sh

262 lines
6.5 KiB
Bash
Executable File

#!/bin/bash
# Generate WASM plugin scaffold for nginx snippet migration
set -e
if [ "$#" -lt 1 ]; then
echo "Usage: $0 <plugin-name> [output-dir]"
echo ""
echo "Example: $0 custom-headers ./plugins"
exit 1
fi
PLUGIN_NAME="$1"
OUTPUT_DIR="${2:-.}"
PLUGIN_DIR="${OUTPUT_DIR}/${PLUGIN_NAME}"
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo -e "${YELLOW}Generating WASM plugin scaffold: ${PLUGIN_NAME}${NC}"
# Create directory
mkdir -p "$PLUGIN_DIR"
# Generate go.mod
cat > "${PLUGIN_DIR}/go.mod" << EOF
module ${PLUGIN_NAME}
go 1.24
require (
github.com/higress-group/proxy-wasm-go-sdk v1.0.1-0.20241230091623-edc7227eb588
github.com/higress-group/wasm-go v1.0.1-0.20250107151137-19a0ab53cfec
github.com/tidwall/gjson v1.18.0
)
EOF
# Generate main.go
cat > "${PLUGIN_DIR}/main.go" << 'EOF'
package main
import (
"github.com/higress-group/proxy-wasm-go-sdk/proxywasm"
"github.com/higress-group/proxy-wasm-go-sdk/proxywasm/types"
"github.com/higress-group/wasm-go/pkg/wrapper"
"github.com/tidwall/gjson"
)
func main() {}
func init() {
wrapper.SetCtx(
"PLUGIN_NAME_PLACEHOLDER",
wrapper.ParseConfig(parseConfig),
wrapper.ProcessRequestHeaders(onHttpRequestHeaders),
wrapper.ProcessRequestBody(onHttpRequestBody),
wrapper.ProcessResponseHeaders(onHttpResponseHeaders),
wrapper.ProcessResponseBody(onHttpResponseBody),
)
}
// PluginConfig holds the plugin configuration
type PluginConfig struct {
// TODO: Add configuration fields
// Example:
// HeaderName string
// HeaderValue string
Enabled bool
}
// parseConfig parses the plugin configuration from YAML (converted to JSON)
func parseConfig(json gjson.Result, config *PluginConfig) error {
// TODO: Parse configuration
// Example:
// config.HeaderName = json.Get("headerName").String()
// config.HeaderValue = json.Get("headerValue").String()
config.Enabled = json.Get("enabled").Bool()
proxywasm.LogInfof("Plugin config loaded: enabled=%v", config.Enabled)
return nil
}
// onHttpRequestHeaders is called when request headers are received
func onHttpRequestHeaders(ctx wrapper.HttpContext, config PluginConfig) types.Action {
if !config.Enabled {
return types.HeaderContinue
}
// TODO: Implement request header processing
// Example: Add custom header
// proxywasm.AddHttpRequestHeader(config.HeaderName, config.HeaderValue)
// Example: Check path and block
// path := ctx.Path()
// if strings.Contains(path, "/blocked") {
// proxywasm.SendHttpResponse(403, nil, []byte("Forbidden"), -1)
// return types.HeaderStopAllIterationAndWatermark
// }
return types.HeaderContinue
}
// onHttpRequestBody is called when request body is received
// Remove this function from init() if not needed
func onHttpRequestBody(ctx wrapper.HttpContext, config PluginConfig, body []byte) types.Action {
if !config.Enabled {
return types.BodyContinue
}
// TODO: Implement request body processing
// Example: Log body size
// proxywasm.LogInfof("Request body size: %d", len(body))
return types.BodyContinue
}
// onHttpResponseHeaders is called when response headers are received
func onHttpResponseHeaders(ctx wrapper.HttpContext, config PluginConfig) types.Action {
if !config.Enabled {
return types.HeaderContinue
}
// TODO: Implement response header processing
// Example: Add security headers
// proxywasm.AddHttpResponseHeader("X-Content-Type-Options", "nosniff")
// proxywasm.AddHttpResponseHeader("X-Frame-Options", "DENY")
return types.HeaderContinue
}
// onHttpResponseBody is called when response body is received
// Remove this function from init() if not needed
func onHttpResponseBody(ctx wrapper.HttpContext, config PluginConfig, body []byte) types.Action {
if !config.Enabled {
return types.BodyContinue
}
// TODO: Implement response body processing
// Example: Modify response body
// newBody := strings.Replace(string(body), "old", "new", -1)
// proxywasm.ReplaceHttpResponseBody([]byte(newBody))
return types.BodyContinue
}
EOF
# Replace plugin name placeholder
sed -i "s/PLUGIN_NAME_PLACEHOLDER/${PLUGIN_NAME}/g" "${PLUGIN_DIR}/main.go"
# Generate Dockerfile
cat > "${PLUGIN_DIR}/Dockerfile" << 'EOF'
FROM scratch
COPY main.wasm /plugin.wasm
EOF
# Generate build script
cat > "${PLUGIN_DIR}/build.sh" << 'EOF'
#!/bin/bash
set -e
echo "Downloading dependencies..."
go mod tidy
echo "Building WASM plugin..."
GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o main.wasm ./
echo "Build complete: main.wasm"
ls -lh main.wasm
EOF
chmod +x "${PLUGIN_DIR}/build.sh"
# Generate WasmPlugin manifest
cat > "${PLUGIN_DIR}/wasmplugin.yaml" << EOF
apiVersion: extensions.higress.io/v1alpha1
kind: WasmPlugin
metadata:
name: ${PLUGIN_NAME}
namespace: higress-system
spec:
# TODO: Replace with your registry
url: oci://YOUR_REGISTRY/${PLUGIN_NAME}:v1
phase: UNSPECIFIED_PHASE
priority: 100
defaultConfig:
enabled: true
# TODO: Add your configuration
# Optional: Apply to specific routes/domains
# matchRules:
# - domain:
# - "*.example.com"
# config:
# enabled: true
EOF
# Generate README
cat > "${PLUGIN_DIR}/README.md" << EOF
# ${PLUGIN_NAME}
A Higress WASM plugin migrated from nginx configuration.
## Build
\`\`\`bash
./build.sh
\`\`\`
## Push to Registry
\`\`\`bash
# Set your registry
REGISTRY=your-registry.com/higress-plugins
# Build Docker image
docker build -t \${REGISTRY}/${PLUGIN_NAME}:v1 .
# Push
docker push \${REGISTRY}/${PLUGIN_NAME}:v1
\`\`\`
## Deploy
1. Update \`wasmplugin.yaml\` with your registry URL
2. Apply to cluster:
\`\`\`bash
kubectl apply -f wasmplugin.yaml
\`\`\`
## Configuration
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| enabled | bool | true | Enable/disable plugin |
## TODO
- [ ] Implement plugin logic in main.go
- [ ] Add configuration fields
- [ ] Test locally
- [ ] Push to registry
- [ ] Deploy to cluster
EOF
echo -e "\n${GREEN}✓ Plugin scaffold generated at: ${PLUGIN_DIR}${NC}"
echo ""
echo "Files created:"
echo " - ${PLUGIN_DIR}/main.go (plugin source)"
echo " - ${PLUGIN_DIR}/go.mod (Go module)"
echo " - ${PLUGIN_DIR}/Dockerfile (OCI image)"
echo " - ${PLUGIN_DIR}/build.sh (build script)"
echo " - ${PLUGIN_DIR}/wasmplugin.yaml (K8s manifest)"
echo " - ${PLUGIN_DIR}/README.md (documentation)"
echo ""
echo -e "${YELLOW}Next steps:${NC}"
echo "1. cd ${PLUGIN_DIR}"
echo "2. Edit main.go to implement your logic"
echo "3. Run: ./build.sh"
echo "4. Push image to your registry"
echo "5. Update wasmplugin.yaml with registry URL"
echo "6. Deploy: kubectl apply -f wasmplugin.yaml"