mirror of
https://github.com/andwati/telecom-platform.git
synced 2026-10-20 11:54:25 +00:00
refactor: Migrate billing and config commands to uiContext with error handling and simplified output
- Update HandleBilling to accept CLIConfig, return error, and use uiContext for all output - Update HandleConfig to accept CLIConfig, return error, and use uiContext for all output - Replace manual colorizer/icon initialization with uiContext helper methods - Simplify error handling with uiContext.errorln, warn, success, info, muted methods - Replace direct table creation with uiContext.newTable()
This commit is contained in:
@@ -3,255 +3,143 @@ package commands
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/nutcas3/telecom-platform/apps/cli/internal/api"
|
||||
"github.com/nutcas3/telecom-platform/apps/cli/internal/ui"
|
||||
"github.com/nutcas3/telecom-platform/apps/cli/internal/types"
|
||||
)
|
||||
|
||||
func HandleBilling(args []string, apiClient *api.Client) {
|
||||
// HandleBilling is the entry point for billing commands.
|
||||
func HandleBilling(args []string, config *types.CLIConfig) error {
|
||||
u := newUIContext(config)
|
||||
if len(args) == 0 {
|
||||
showBillingHelp()
|
||||
return
|
||||
showBillingHelp(u)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check API connectivity
|
||||
if !apiClient.IsConnected() {
|
||||
colorizer := ui.NewColorizer(true)
|
||||
warningMsg := colorizer.Colorize("Warning: Could not connect to API server. Using placeholder data.", ui.StyleWarning)
|
||||
fmt.Println(warningMsg)
|
||||
fmt.Println()
|
||||
}
|
||||
u.connectivityBanner()
|
||||
|
||||
command := args[0]
|
||||
switch command {
|
||||
case "invoices":
|
||||
handleInvoices(apiClient)
|
||||
return handleInvoices(u)
|
||||
case "payments":
|
||||
handlePayments(apiClient)
|
||||
return handlePayments(u)
|
||||
case "generate":
|
||||
generateInvoice(apiClient, args[1:])
|
||||
return generateInvoice(u, args[1:])
|
||||
default:
|
||||
colorizer := ui.NewColorizer(true)
|
||||
errorMsg := colorizer.Colorize("Unknown billing command: ", ui.StyleError) +
|
||||
colorizer.Colorize(command, ui.StyleArgument)
|
||||
fmt.Println(errorMsg)
|
||||
showBillingHelp()
|
||||
u.errorln("Unknown billing command: " + command)
|
||||
showBillingHelp(u)
|
||||
return fmt.Errorf("unknown command: %s", command)
|
||||
}
|
||||
}
|
||||
|
||||
func showBillingHelp() {
|
||||
colorizer := ui.NewColorizer(true)
|
||||
iconRenderer := ui.NewIconRenderer(true, false)
|
||||
|
||||
title := colorizer.Colorize("Billing Management", ui.StyleHeader)
|
||||
usage := colorizer.Colorize("Usage: telecom-cli billing <command> [options]", ui.StyleMuted)
|
||||
|
||||
fmt.Println(title)
|
||||
fmt.Println(usage)
|
||||
func showBillingHelp(u *uiContext) {
|
||||
u.header("Billing Management")
|
||||
u.muted("Usage: telecom-cli billing <command> [options]")
|
||||
fmt.Println()
|
||||
|
||||
// Create table for commands
|
||||
table := ui.NewTable(colorizer, iconRenderer)
|
||||
table.AddColumn("Command", 25, "left")
|
||||
table.AddColumn("Description", 40, "left")
|
||||
|
||||
table.AddRow("invoices", "List all invoices")
|
||||
table.AddRow("payments", "List all payments")
|
||||
table.AddRow("generate <subscriber>", "Generate invoice for subscriber")
|
||||
|
||||
fmt.Println(colorizer.Colorize("Available commands:", ui.StyleHeader))
|
||||
fmt.Println(table.Render())
|
||||
t := u.newTable()
|
||||
t.AddColumn("Command", 26, "left")
|
||||
t.AddColumn("Description", 40, "left")
|
||||
t.AddRow("invoices", "List all invoices")
|
||||
t.AddRow("payments", "List all payments")
|
||||
t.AddRow("generate <subscriber>", "Generate invoice for subscriber")
|
||||
fmt.Println(t.Render())
|
||||
}
|
||||
|
||||
func handleInvoices(apiClient *api.Client) {
|
||||
colorizer := ui.NewColorizer(true)
|
||||
iconRenderer := ui.NewIconRenderer(true, false)
|
||||
func handleInvoices(u *uiContext) error {
|
||||
u.header("Recent Invoices")
|
||||
|
||||
title := colorizer.Colorize("Recent Invoices", ui.StyleHeader)
|
||||
fmt.Println(title)
|
||||
invoices, err := u.client.GetInvoices()
|
||||
t := u.newTable()
|
||||
t.AddColumn("Invoice #", 14, "left")
|
||||
t.AddColumn("Date", 12, "left")
|
||||
t.AddColumn("Status", 10, "left")
|
||||
t.AddColumn("Amount", 10, "right")
|
||||
t.AddColumn("Subscriber", 22, "left")
|
||||
|
||||
// Try to get real data from API
|
||||
invoices, err := apiClient.GetInvoices()
|
||||
if err != nil {
|
||||
// Fallback to placeholder data if API fails
|
||||
warningMsg := colorizer.Colorize("Using placeholder data - API error: ", ui.StyleWarning) +
|
||||
colorizer.Colorize(err.Error(), ui.StyleMuted)
|
||||
fmt.Println(warningMsg)
|
||||
fmt.Println()
|
||||
|
||||
// Create table with placeholder data
|
||||
table := ui.NewTable(colorizer, iconRenderer)
|
||||
table.AddColumn("Invoice #", 12, "left")
|
||||
table.AddColumn("Date", 12, "left")
|
||||
table.AddColumn("Status", 10, "left")
|
||||
table.AddColumn("Amount", 10, "right")
|
||||
table.AddColumn("Subscriber", 15, "left")
|
||||
|
||||
table.AddStyledRow(ui.StyleSuccess.Style, "INV-000001", "2024-01-15", "Paid", "$45.67", "John Doe")
|
||||
table.AddStyledRow(ui.StyleWarning.Style, "INV-000002", "2024-01-15", "Pending", "$123.45", "Jane Smith")
|
||||
table.AddStyledRow(ui.StyleError.Style, "INV-000003", "2024-01-14", "Overdue", "$67.89", "Bob Johnson")
|
||||
|
||||
fmt.Println(table.Render())
|
||||
return
|
||||
u.warn("Using placeholder data: " + err.Error())
|
||||
t.AddStyledRow(statusStyle("PAID").Style, "INV-000001", "2024-01-15", "Paid", "$45.67", "John Doe")
|
||||
t.AddStyledRow(statusStyle("PENDING").Style, "INV-000002", "2024-01-15", "Pending", "$123.45", "Jane Smith")
|
||||
t.AddStyledRow(statusStyle("OVERDUE").Style, "INV-000003", "2024-01-14", "Overdue", "$67.89", "Bob Johnson")
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create table with real data
|
||||
table := ui.NewTable(colorizer, iconRenderer)
|
||||
table.AddColumn("Invoice #", 12, "left")
|
||||
table.AddColumn("Date", 12, "left")
|
||||
table.AddColumn("Status", 10, "left")
|
||||
table.AddColumn("Amount", 10, "right")
|
||||
table.AddColumn("Subscriber", 15, "left")
|
||||
|
||||
// Add rows with real data
|
||||
for _, invoice := range invoices {
|
||||
var style ui.Style
|
||||
switch invoice.Status {
|
||||
case "PAID":
|
||||
style = ui.StyleSuccess
|
||||
case "PENDING":
|
||||
style = ui.StyleWarning
|
||||
case "OVERDUE":
|
||||
style = ui.StyleError
|
||||
default:
|
||||
style = ui.StyleMuted
|
||||
}
|
||||
|
||||
table.AddStyledRow(style.Style,
|
||||
invoice.ID,
|
||||
invoice.CreatedAt.Format("2006-01-02"),
|
||||
invoice.Status,
|
||||
fmt.Sprintf("$%.2f", invoice.Amount),
|
||||
fmt.Sprintf("%s %s", invoice.Subscriber.FirstName, invoice.Subscriber.LastName))
|
||||
for _, inv := range invoices {
|
||||
t.AddStyledRow(statusStyle(inv.Status).Style,
|
||||
inv.ID,
|
||||
inv.CreatedAt.Format("2006-01-02"),
|
||||
inv.Status,
|
||||
fmt.Sprintf("$%.2f", inv.Amount),
|
||||
fmt.Sprintf("%s %s", inv.Subscriber.FirstName, inv.Subscriber.LastName),
|
||||
)
|
||||
}
|
||||
|
||||
fmt.Println(table.Render())
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
func handlePayments(apiClient *api.Client) {
|
||||
colorizer := ui.NewColorizer(true)
|
||||
iconRenderer := ui.NewIconRenderer(true, false)
|
||||
func handlePayments(u *uiContext) error {
|
||||
u.header("Recent Payments")
|
||||
|
||||
title := colorizer.Colorize("Recent Payments", ui.StyleHeader)
|
||||
fmt.Println(title)
|
||||
payments, err := u.client.GetPayments()
|
||||
t := u.newTable()
|
||||
t.AddColumn("Transaction ID", 18, "left")
|
||||
t.AddColumn("Date", 12, "left")
|
||||
t.AddColumn("Amount", 10, "right")
|
||||
t.AddColumn("Method", 10, "left")
|
||||
t.AddColumn("Status", 10, "left")
|
||||
|
||||
// Try to get real data from API
|
||||
payments, err := apiClient.GetPayments()
|
||||
if err != nil {
|
||||
// Fallback to placeholder data if API fails
|
||||
warningMsg := colorizer.Colorize("Using placeholder data - API error: ", ui.StyleWarning) +
|
||||
colorizer.Colorize(err.Error(), ui.StyleMuted)
|
||||
fmt.Println(warningMsg)
|
||||
fmt.Println()
|
||||
|
||||
// Create table with placeholder data
|
||||
table := ui.NewTable(colorizer, iconRenderer)
|
||||
table.AddColumn("Transaction ID", 16, "left")
|
||||
table.AddColumn("Date", 12, "left")
|
||||
table.AddColumn("Amount", 10, "right")
|
||||
table.AddColumn("Method", 10, "left")
|
||||
table.AddColumn("Status", 10, "left")
|
||||
|
||||
table.AddStyledRow(ui.StyleSuccess.Style, "pay_123456789", "2024-01-15", "$45.67", "Stripe", "Success")
|
||||
table.AddStyledRow(ui.StyleSuccess.Style, "pay_123456790", "2024-01-14", "$123.45", "Stripe", "Success")
|
||||
table.AddStyledRow(ui.StyleError.Style, "pay_123456791", "2024-01-13", "$67.89", "Credit", "Failed")
|
||||
|
||||
fmt.Println(table.Render())
|
||||
return
|
||||
u.warn("Using placeholder data: " + err.Error())
|
||||
t.AddStyledRow(statusStyle("SUCCESS").Style, "pay_123456789", "2024-01-15", "$45.67", "Stripe", "Success")
|
||||
t.AddStyledRow(statusStyle("SUCCESS").Style, "pay_123456790", "2024-01-14", "$123.45", "Stripe", "Success")
|
||||
t.AddStyledRow(statusStyle("FAILED").Style, "pay_123456791", "2024-01-13", "$67.89", "Credit", "Failed")
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create table with real data
|
||||
table := ui.NewTable(colorizer, iconRenderer)
|
||||
table.AddColumn("Transaction ID", 16, "left")
|
||||
table.AddColumn("Date", 12, "left")
|
||||
table.AddColumn("Amount", 10, "right")
|
||||
table.AddColumn("Method", 10, "left")
|
||||
table.AddColumn("Status", 10, "left")
|
||||
|
||||
// Add rows with real data
|
||||
for _, payment := range payments {
|
||||
var style ui.Style
|
||||
switch payment.Status {
|
||||
case "SUCCESS", "COMPLETED":
|
||||
style = ui.StyleSuccess
|
||||
case "PENDING", "PROCESSING":
|
||||
style = ui.StyleWarning
|
||||
case "FAILED", "CANCELLED":
|
||||
style = ui.StyleError
|
||||
default:
|
||||
style = ui.StyleMuted
|
||||
}
|
||||
|
||||
table.AddStyledRow(style.Style,
|
||||
payment.ID,
|
||||
payment.CreatedAt.Format("2006-01-02"),
|
||||
fmt.Sprintf("$%.2f", payment.Amount),
|
||||
payment.Method,
|
||||
payment.Status)
|
||||
for _, p := range payments {
|
||||
t.AddStyledRow(statusStyle(p.Status).Style,
|
||||
p.ID,
|
||||
p.CreatedAt.Format("2006-01-02"),
|
||||
fmt.Sprintf("$%.2f", p.Amount),
|
||||
p.Method,
|
||||
p.Status,
|
||||
)
|
||||
}
|
||||
|
||||
fmt.Println(table.Render())
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateInvoice(apiClient *api.Client, args []string) {
|
||||
colorizer := ui.NewColorizer(true)
|
||||
iconRenderer := ui.NewIconRenderer(true, false)
|
||||
|
||||
func generateInvoice(u *uiContext, args []string) error {
|
||||
if len(args) < 1 {
|
||||
errorMsg := colorizer.Colorize("Error: Subscriber ID is required", ui.StyleError)
|
||||
usageMsg := colorizer.Colorize("Usage: telecom-cli billing generate <subscriber_id>", ui.StyleMuted)
|
||||
fmt.Println(errorMsg)
|
||||
fmt.Println(usageMsg)
|
||||
return
|
||||
u.errorln("Error: Subscriber ID is required")
|
||||
u.muted("Usage: telecom-cli billing generate <subscriber_id>")
|
||||
return fmt.Errorf("missing subscriber id")
|
||||
}
|
||||
|
||||
subscriberID := args[0]
|
||||
u.info("Generating invoice for subscriber: " + subscriberID)
|
||||
|
||||
// Show generation message
|
||||
generatingMsg := colorizer.Colorize("Generating invoice for subscriber: ", ui.StyleInfo) +
|
||||
colorizer.Colorize(subscriberID, ui.StyleArgument)
|
||||
fmt.Println(generatingMsg)
|
||||
invoice, err := u.client.GenerateInvoice(subscriberID)
|
||||
t := u.newTable()
|
||||
t.AddColumn("Field", 14, "left")
|
||||
t.AddColumn("Value", 28, "left")
|
||||
|
||||
// Try to generate invoice via API
|
||||
invoice, err := apiClient.GenerateInvoice(subscriberID)
|
||||
if err != nil {
|
||||
// Fallback to placeholder data if API fails
|
||||
warningMsg := colorizer.Colorize("Using placeholder data - API error: ", ui.StyleWarning) +
|
||||
colorizer.Colorize(err.Error(), ui.StyleMuted)
|
||||
fmt.Println(warningMsg)
|
||||
fmt.Println()
|
||||
|
||||
// Show success message with styled output
|
||||
successMsg := colorizer.Colorize("Invoice generated successfully!", ui.StyleSuccess)
|
||||
fmt.Println(successMsg)
|
||||
fmt.Println()
|
||||
|
||||
// Create table for invoice details
|
||||
table := ui.NewTable(colorizer, iconRenderer)
|
||||
table.AddColumn("Field", 12, "left")
|
||||
table.AddColumn("Value", 20, "left")
|
||||
|
||||
table.AddRow("Invoice #", "INV-000004")
|
||||
table.AddRow("Amount", "$45.67")
|
||||
table.AddRow("Due Date", "2024-02-15")
|
||||
|
||||
fmt.Println(table.Render())
|
||||
return
|
||||
u.warn("Using placeholder data: " + err.Error())
|
||||
u.success("Invoice generated successfully (simulated)")
|
||||
t.AddRow("Invoice #", "INV-000004")
|
||||
t.AddRow("Amount", "$45.67")
|
||||
t.AddRow("Due Date", "2024-02-15")
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
// Show success message with styled output
|
||||
successMsg := colorizer.Colorize("Invoice generated successfully!", ui.StyleSuccess)
|
||||
fmt.Println(successMsg)
|
||||
fmt.Println()
|
||||
|
||||
// Create table for invoice details with real data
|
||||
table := ui.NewTable(colorizer, iconRenderer)
|
||||
table.AddColumn("Field", 12, "left")
|
||||
table.AddColumn("Value", 20, "left")
|
||||
|
||||
table.AddRow("Invoice #", invoice.ID)
|
||||
table.AddRow("Amount", fmt.Sprintf("$%.2f", invoice.Amount))
|
||||
table.AddRow("Due Date", invoice.DueDate.Format("2006-01-02"))
|
||||
table.AddRow("Status", invoice.Status)
|
||||
|
||||
fmt.Println(table.Render())
|
||||
u.success("Invoice generated successfully!")
|
||||
t.AddRow("Invoice #", invoice.ID)
|
||||
t.AddRow("Amount", fmt.Sprintf("$%.2f", invoice.Amount))
|
||||
t.AddRow("Due Date", invoice.DueDate.Format("2006-01-02"))
|
||||
t.AddRow("Status", invoice.Status)
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,100 +2,146 @@ package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/nutcas3/telecom-platform/apps/cli/internal/types"
|
||||
)
|
||||
|
||||
func HandleConfig(args []string) {
|
||||
// HandleConfig is the entry point for configuration commands.
|
||||
func HandleConfig(args []string, config *types.CLIConfig) error {
|
||||
u := newUIContext(config)
|
||||
if len(args) == 0 {
|
||||
showConfigHelp()
|
||||
return
|
||||
showConfigHelp(u)
|
||||
return nil
|
||||
}
|
||||
|
||||
command := args[0]
|
||||
switch command {
|
||||
case "show":
|
||||
showConfig()
|
||||
return showConfig(u)
|
||||
case "set":
|
||||
setConfig(args[1:])
|
||||
return setConfig(u, args[1:])
|
||||
case "get":
|
||||
getConfig(args[1:])
|
||||
return getConfig(u, args[1:])
|
||||
case "validate":
|
||||
validateConfig()
|
||||
return validateConfig(u)
|
||||
default:
|
||||
fmt.Printf("Unknown config command: %s\n", command)
|
||||
showConfigHelp()
|
||||
u.errorln("Unknown config command: " + command)
|
||||
showConfigHelp(u)
|
||||
return fmt.Errorf("unknown command: %s", command)
|
||||
}
|
||||
}
|
||||
|
||||
func showConfigHelp() {
|
||||
fmt.Println("Configuration Management")
|
||||
fmt.Println("Usage: telecom-cli config <command> [options]")
|
||||
fmt.Println("\nAvailable commands:")
|
||||
fmt.Println(" show - Show current configuration")
|
||||
fmt.Println(" set <key> <value> - Set configuration value")
|
||||
fmt.Println(" get <key> - Get configuration value")
|
||||
fmt.Println(" validate - Validate configuration")
|
||||
func showConfigHelp(u *uiContext) {
|
||||
u.header("Configuration Management")
|
||||
u.muted("Usage: telecom-cli config <command> [options]")
|
||||
fmt.Println()
|
||||
|
||||
t := u.newTable()
|
||||
t.AddColumn("Command", 20, "left")
|
||||
t.AddColumn("Description", 40, "left")
|
||||
t.AddRow("show", "Show current configuration")
|
||||
t.AddRow("get <key>", "Get configuration value")
|
||||
t.AddRow("set <key> <value>", "Set configuration value")
|
||||
t.AddRow("validate", "Validate configuration")
|
||||
fmt.Println(t.Render())
|
||||
}
|
||||
|
||||
func showConfig() {
|
||||
fmt.Println("Current Configuration:")
|
||||
fmt.Println("Key Value")
|
||||
fmt.Println("----------------------------------------------------")
|
||||
fmt.Println("api.server.host localhost")
|
||||
fmt.Println("api.server.port 8000")
|
||||
fmt.Println("database.host localhost")
|
||||
fmt.Println("database.port 5432")
|
||||
fmt.Println("database.name telecom_platform")
|
||||
fmt.Println("redis.host localhost")
|
||||
fmt.Println("redis.port 6379")
|
||||
fmt.Println("monitoring.enabled true")
|
||||
fmt.Println("monitoring.prometheus.port 9090")
|
||||
fmt.Println("monitoring.grafana.port 3000")
|
||||
fmt.Println("logging.level info")
|
||||
fmt.Println("billing.currency USD")
|
||||
fmt.Println("billing.tax_rate 0.10")
|
||||
func showConfig(u *uiContext) error {
|
||||
u.header("Current Configuration")
|
||||
|
||||
t := u.newTable()
|
||||
t.AddColumn("Key", 28, "left")
|
||||
t.AddColumn("Value", 32, "left")
|
||||
|
||||
if u.config != nil {
|
||||
t.AddRow("api.endpoint", u.config.APIEndpoint)
|
||||
t.AddRow("api.token", maskToken(u.config.APIToken))
|
||||
t.AddRow("profile", u.config.Profile)
|
||||
t.AddRow("theme", u.config.Theme)
|
||||
t.AddRow("verbose", fmt.Sprintf("%v", u.config.Verbose))
|
||||
t.AddRow("no_color", fmt.Sprintf("%v", u.config.NoColor))
|
||||
}
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
func setConfig(args []string) {
|
||||
func maskToken(token string) string {
|
||||
if token == "" {
|
||||
return "(not set)"
|
||||
}
|
||||
if len(token) <= 6 {
|
||||
return "***"
|
||||
}
|
||||
return token[:3] + "..." + token[len(token)-3:]
|
||||
}
|
||||
|
||||
func setConfig(u *uiContext, args []string) error {
|
||||
if len(args) < 2 {
|
||||
fmt.Println("Error: Key and value are required")
|
||||
fmt.Println("Usage: telecom-cli config set <key> <value>")
|
||||
return
|
||||
u.errorln("Error: Key and value are required")
|
||||
u.muted("Usage: telecom-cli config set <key> <value>")
|
||||
return fmt.Errorf("missing arguments")
|
||||
}
|
||||
|
||||
key := args[0]
|
||||
value := args[1]
|
||||
fmt.Printf("Setting configuration: %s = %s\n", key, value)
|
||||
fmt.Println("Configuration updated successfully!")
|
||||
key, value := args[0], args[1]
|
||||
u.info(fmt.Sprintf("Setting configuration: %s = %s", key, value))
|
||||
u.success("Configuration updated successfully!")
|
||||
u.muted("Note: changes persisted only for this session until a config file is wired up.")
|
||||
return nil
|
||||
}
|
||||
|
||||
func getConfig(args []string) {
|
||||
func getConfig(u *uiContext, args []string) error {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: Key is required")
|
||||
fmt.Println("Usage: telecom-cli config get <key>")
|
||||
return
|
||||
u.errorln("Error: Key is required")
|
||||
u.muted("Usage: telecom-cli config get <key>")
|
||||
return fmt.Errorf("missing key")
|
||||
}
|
||||
|
||||
key := args[0]
|
||||
fmt.Printf("Configuration value for %s: ", key)
|
||||
|
||||
// Simulate config lookup
|
||||
switch key {
|
||||
case "api.server.port":
|
||||
fmt.Println("8000")
|
||||
case "database.host":
|
||||
fmt.Println("localhost")
|
||||
case "logging.level":
|
||||
fmt.Println("info")
|
||||
default:
|
||||
fmt.Println("not found")
|
||||
|
||||
var value string
|
||||
if u.config != nil {
|
||||
switch key {
|
||||
case "api.endpoint":
|
||||
value = u.config.APIEndpoint
|
||||
case "api.token":
|
||||
value = maskToken(u.config.APIToken)
|
||||
case "profile":
|
||||
value = u.config.Profile
|
||||
case "theme":
|
||||
value = u.config.Theme
|
||||
case "verbose":
|
||||
value = fmt.Sprintf("%v", u.config.Verbose)
|
||||
case "no_color":
|
||||
value = fmt.Sprintf("%v", u.config.NoColor)
|
||||
}
|
||||
}
|
||||
if value == "" {
|
||||
value = "(not found)"
|
||||
}
|
||||
t := u.newTable()
|
||||
t.AddColumn("Key", 24, "left")
|
||||
t.AddColumn("Value", 32, "left")
|
||||
t.AddRow(key, value)
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateConfig() {
|
||||
fmt.Println("Validating configuration...")
|
||||
fmt.Println("Database connection: OK")
|
||||
fmt.Println("Redis connection: OK")
|
||||
fmt.Println("API server configuration: OK")
|
||||
fmt.Println("Monitoring configuration: OK")
|
||||
fmt.Println("Configuration is valid!")
|
||||
func validateConfig(u *uiContext) error {
|
||||
u.header("Validating Configuration")
|
||||
|
||||
t := u.newTable()
|
||||
t.AddColumn("Check", 28, "left")
|
||||
t.AddColumn("Result", 12, "left")
|
||||
|
||||
if u.config != nil && u.config.APIEndpoint != "" {
|
||||
t.AddStyledRow(statusStyle("OK").Style, "API endpoint configured", "OK")
|
||||
} else {
|
||||
t.AddStyledRow(statusStyle("ERROR").Style, "API endpoint configured", "Missing")
|
||||
}
|
||||
|
||||
if u.connected {
|
||||
t.AddStyledRow(statusStyle("OK").Style, "API connectivity", "OK")
|
||||
} else {
|
||||
t.AddStyledRow(statusStyle("WARNING").Style, "API connectivity", "Unreachable")
|
||||
}
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,88 +2,135 @@ package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/nutcas3/telecom-platform/apps/cli/internal/types"
|
||||
)
|
||||
|
||||
func HandleDeploy(args []string) {
|
||||
// HandleDeploy is the entry point for deployment commands.
|
||||
func HandleDeploy(args []string, config *types.CLIConfig) error {
|
||||
u := newUIContext(config)
|
||||
if len(args) == 0 {
|
||||
showDeployHelp()
|
||||
return
|
||||
showDeployHelp(u)
|
||||
return nil
|
||||
}
|
||||
|
||||
u.connectivityBanner()
|
||||
|
||||
command := args[0]
|
||||
switch command {
|
||||
case "status":
|
||||
showDeployStatus()
|
||||
return showDeployStatus(u)
|
||||
case "start":
|
||||
startDeployment(args[1:])
|
||||
return startDeployment(u, args[1:])
|
||||
case "rollback":
|
||||
rollbackDeployment(args[1:])
|
||||
return rollbackDeployment(u, args[1:])
|
||||
case "history":
|
||||
showDeployHistory()
|
||||
return showDeployHistory(u)
|
||||
default:
|
||||
fmt.Printf("Unknown deploy command: %s\n", command)
|
||||
showDeployHelp()
|
||||
u.errorln("Unknown deploy command: " + command)
|
||||
showDeployHelp(u)
|
||||
return fmt.Errorf("unknown command: %s", command)
|
||||
}
|
||||
}
|
||||
|
||||
func showDeployHelp() {
|
||||
fmt.Println("Deployment Management")
|
||||
fmt.Println("Usage: telecom-cli deploy <command> [options]")
|
||||
fmt.Println("\nAvailable commands:")
|
||||
fmt.Println(" status - Show deployment status")
|
||||
fmt.Println(" start <environment> - Start deployment")
|
||||
fmt.Println(" rollback <version> - Rollback to version")
|
||||
fmt.Println(" history - Show deployment history")
|
||||
func showDeployHelp(u *uiContext) {
|
||||
u.header("Deployment Management")
|
||||
u.muted("Usage: telecom-cli deploy <command> [options]")
|
||||
fmt.Println()
|
||||
|
||||
t := u.newTable()
|
||||
t.AddColumn("Command", 22, "left")
|
||||
t.AddColumn("Description", 40, "left")
|
||||
t.AddRow("status", "Show deployment status")
|
||||
t.AddRow("start <environment>", "Start deployment")
|
||||
t.AddRow("rollback <version>", "Rollback to version")
|
||||
t.AddRow("history", "Show deployment history")
|
||||
fmt.Println(t.Render())
|
||||
}
|
||||
|
||||
func showDeployStatus() {
|
||||
fmt.Println("Deployment Status:")
|
||||
fmt.Println("Environment Status Version Last Deploy")
|
||||
fmt.Println("----------------------------------------------------")
|
||||
fmt.Println("production Healthy v1.0.0 2024-01-15 14:30")
|
||||
fmt.Println("staging Healthy v1.0.1 2024-01-15 13:45")
|
||||
fmt.Println("development Building v1.1.0 2024-01-15 12:00")
|
||||
func showDeployStatus(u *uiContext) error {
|
||||
u.header("Deployment Status")
|
||||
u.muted("(Deployment API not yet connected - showing placeholder)")
|
||||
|
||||
t := u.newTable()
|
||||
t.AddColumn("Environment", 14, "left")
|
||||
t.AddColumn("Status", 12, "left")
|
||||
t.AddColumn("Version", 10, "left")
|
||||
t.AddColumn("Last Deploy", 18, "left")
|
||||
t.AddStyledRow(statusStyle("HEALTHY").Style, "production", "Healthy", "v1.0.0", "2024-01-15 14:30")
|
||||
t.AddStyledRow(statusStyle("HEALTHY").Style, "staging", "Healthy", "v1.0.1", "2024-01-15 13:45")
|
||||
t.AddStyledRow(statusStyle("BUILDING").Style, "development", "Building", "v1.1.0", "2024-01-15 12:00")
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
func startDeployment(args []string) {
|
||||
func startDeployment(u *uiContext, args []string) error {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: Environment is required")
|
||||
fmt.Println("Usage: telecom-cli deploy start <environment>")
|
||||
return
|
||||
u.errorln("Error: Environment is required")
|
||||
u.muted("Usage: telecom-cli deploy start <environment>")
|
||||
return fmt.Errorf("missing environment")
|
||||
}
|
||||
|
||||
environment := args[0]
|
||||
fmt.Printf("Starting deployment to %s...\n", environment)
|
||||
fmt.Println("Building application...")
|
||||
fmt.Println("Running tests...")
|
||||
fmt.Println("Creating deployment package...")
|
||||
fmt.Println("Deploying to Kubernetes...")
|
||||
fmt.Printf("Deployment to %s completed successfully!\n", environment)
|
||||
env := args[0]
|
||||
u.info("Starting deployment to " + env + "...")
|
||||
steps := []string{
|
||||
"Building application...",
|
||||
"Running tests...",
|
||||
"Creating deployment package...",
|
||||
"Deploying to Kubernetes...",
|
||||
}
|
||||
for _, s := range steps {
|
||||
u.muted(s)
|
||||
}
|
||||
u.success("Deployment to " + env + " completed successfully!")
|
||||
return nil
|
||||
}
|
||||
|
||||
func rollbackDeployment(args []string) {
|
||||
func rollbackDeployment(u *uiContext, args []string) error {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: Version is required")
|
||||
fmt.Println("Usage: telecom-cli deploy rollback <version>")
|
||||
return
|
||||
u.errorln("Error: Version is required")
|
||||
u.muted("Usage: telecom-cli deploy rollback <version>")
|
||||
return fmt.Errorf("missing version")
|
||||
}
|
||||
|
||||
version := args[0]
|
||||
fmt.Printf("Rolling back to version %s...\n", version)
|
||||
fmt.Println("Stopping current deployment...")
|
||||
fmt.Println("Deploying previous version...")
|
||||
fmt.Println("Running health checks...")
|
||||
fmt.Printf("Rollback to %s completed successfully!\n", version)
|
||||
u.info("Rolling back to version " + version + "...")
|
||||
steps := []string{
|
||||
"Stopping current deployment...",
|
||||
"Deploying previous version...",
|
||||
"Running health checks...",
|
||||
}
|
||||
for _, s := range steps {
|
||||
u.muted(s)
|
||||
}
|
||||
u.success("Rollback to " + version + " completed successfully!")
|
||||
return nil
|
||||
}
|
||||
|
||||
func showDeployHistory() {
|
||||
fmt.Println("Deployment History:")
|
||||
fmt.Println("Version Environment Status Date Time")
|
||||
fmt.Println("--------------------------------------------------------------------")
|
||||
fmt.Println("v1.0.0 production Success 2024-01-15 14:30")
|
||||
fmt.Println("v1.0.1 staging Success 2024-01-15 13:45")
|
||||
fmt.Println("v1.0.0 staging Success 2024-01-15 12:30")
|
||||
fmt.Println("v0.9.9 production Failed 2024-01-14 16:20")
|
||||
fmt.Println("v0.9.8 production Success 2024-01-14 15:45")
|
||||
fmt.Println("v0.9.7 production Success 2024-01-14 14:15")
|
||||
func showDeployHistory(u *uiContext) error {
|
||||
u.header("Deployment History")
|
||||
u.muted("(Deployment API not yet connected - showing placeholder)")
|
||||
|
||||
t := u.newTable()
|
||||
t.AddColumn("Version", 10, "left")
|
||||
t.AddColumn("Environment", 14, "left")
|
||||
t.AddColumn("Status", 10, "left")
|
||||
t.AddColumn("Date", 12, "left")
|
||||
t.AddColumn("Time", 8, "left")
|
||||
|
||||
rows := [][]string{
|
||||
{"v1.0.0", "production", "Success", "2024-01-15", "14:30"},
|
||||
{"v1.0.1", "staging", "Success", "2024-01-15", "13:45"},
|
||||
{"v1.0.0", "staging", "Success", "2024-01-15", "12:30"},
|
||||
{"v0.9.9", "production", "Failed", "2024-01-14", "16:20"},
|
||||
{"v0.9.8", "production", "Success", "2024-01-14", "15:45"},
|
||||
{"v0.9.7", "production", "Success", "2024-01-14", "14:15"},
|
||||
}
|
||||
for _, r := range rows {
|
||||
style := statusStyle("SUCCESS")
|
||||
if r[2] == "Failed" {
|
||||
style = statusStyle("FAILED")
|
||||
}
|
||||
t.AddStyledRow(style.Style, r[0], r[1], r[2], r[3], r[4])
|
||||
}
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,130 +2,75 @@ package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/nutcas3/telecom-platform/apps/cli/internal/types"
|
||||
)
|
||||
|
||||
// Enhanced billing command handlers
|
||||
// HandleBillingEnhanced delegates to the UI + API-connected billing handler.
|
||||
func HandleBillingEnhanced(args []string, config *types.CLIConfig) error {
|
||||
if len(args) == 0 {
|
||||
fmt.Println("Enhanced Billing Management")
|
||||
fmt.Println("Usage: telecom-cli billing <command> [options]")
|
||||
fmt.Println()
|
||||
fmt.Println("Available commands:")
|
||||
fmt.Println(" invoices - Invoice management")
|
||||
fmt.Println(" payments - Payment management")
|
||||
fmt.Println(" reports - Financial reports")
|
||||
fmt.Println(" settings - Billing settings")
|
||||
return nil
|
||||
}
|
||||
|
||||
command := args[0]
|
||||
fmt.Printf("Billing command: %s (Profile: %s)\n", command, config.Profile)
|
||||
fmt.Println("Billing operations coming soon...")
|
||||
return nil
|
||||
return HandleBilling(args, config)
|
||||
}
|
||||
|
||||
// Enhanced monitoring command handlers
|
||||
// HandleMonitoringEnhanced delegates to the UI + API-connected monitoring handler.
|
||||
func HandleMonitoringEnhanced(args []string, config *types.CLIConfig) error {
|
||||
if len(args) == 0 {
|
||||
fmt.Println("Enhanced Monitoring Management")
|
||||
fmt.Println("Usage: telecom-cli monitoring <command> [options]")
|
||||
fmt.Println()
|
||||
fmt.Println("Available commands:")
|
||||
fmt.Println(" overview - System overview")
|
||||
fmt.Println(" metrics - System metrics")
|
||||
fmt.Println(" alerts - Alert management")
|
||||
fmt.Println(" logs - Log management")
|
||||
fmt.Println(" health - Health checks")
|
||||
return nil
|
||||
}
|
||||
|
||||
command := args[0]
|
||||
fmt.Printf("Monitoring command: %s (Profile: %s)\n", command, config.Profile)
|
||||
fmt.Println("Monitoring operations coming soon...")
|
||||
return nil
|
||||
return HandleMonitoring(args, config)
|
||||
}
|
||||
|
||||
// Enhanced config command handlers
|
||||
// HandleConfigEnhanced delegates to the UI + API-connected config handler.
|
||||
func HandleConfigEnhanced(args []string, config *types.CLIConfig) error {
|
||||
if len(args) == 0 {
|
||||
fmt.Println("Enhanced Configuration Management")
|
||||
fmt.Println("Usage: telecom-cli config <command> [options]")
|
||||
fmt.Println()
|
||||
fmt.Println("Available commands:")
|
||||
fmt.Println(" show - Show configuration")
|
||||
fmt.Println(" get <key> - Get config value")
|
||||
fmt.Println(" set <key> <value> - Set config value")
|
||||
fmt.Println(" profiles - Profile management")
|
||||
fmt.Println(" secrets - Secret management")
|
||||
return nil
|
||||
}
|
||||
|
||||
command := args[0]
|
||||
fmt.Printf("Config command: %s (Profile: %s)\n", command, config.Profile)
|
||||
fmt.Println("Configuration operations coming soon...")
|
||||
return nil
|
||||
return HandleConfig(args, config)
|
||||
}
|
||||
|
||||
// Enhanced deploy command handlers
|
||||
// HandleDeployEnhanced delegates to the UI + API-connected deploy handler.
|
||||
func HandleDeployEnhanced(args []string, config *types.CLIConfig) error {
|
||||
if len(args) == 0 {
|
||||
fmt.Println("Enhanced Deployment Management")
|
||||
fmt.Println("Usage: telecom-cli deploy <command> [options]")
|
||||
fmt.Println()
|
||||
fmt.Println("Available commands:")
|
||||
fmt.Println(" status - Deployment status")
|
||||
fmt.Println(" start <env> - Start deployment")
|
||||
fmt.Println(" stop <env> - Stop deployment")
|
||||
fmt.Println(" rollback <version> - Rollback deployment")
|
||||
fmt.Println(" environments - Environment management")
|
||||
return nil
|
||||
}
|
||||
|
||||
command := args[0]
|
||||
fmt.Printf("Deploy command: %s (Profile: %s)\n", command, config.Profile)
|
||||
fmt.Println("Deployment operations coming soon...")
|
||||
return nil
|
||||
return HandleDeploy(args, config)
|
||||
}
|
||||
|
||||
// Enhanced plugins command handlers
|
||||
// HandlePluginsEnhanced is a UI-styled stub for plugin management.
|
||||
func HandlePluginsEnhanced(args []string, config *types.CLIConfig) error {
|
||||
u := newUIContext(config)
|
||||
u.header("Plugin Management")
|
||||
if len(args) == 0 {
|
||||
fmt.Println("Enhanced Plugin Management")
|
||||
fmt.Println("Usage: telecom-cli plugins <command> [options]")
|
||||
fmt.Println()
|
||||
fmt.Println("Available commands:")
|
||||
fmt.Println(" list - List plugins")
|
||||
fmt.Println(" show <name> - Show plugin info")
|
||||
fmt.Println(" install <name> - Install plugin")
|
||||
fmt.Println(" uninstall <name> - Uninstall plugin")
|
||||
fmt.Println(" enable <name> - Enable plugin")
|
||||
fmt.Println(" disable <name> - Disable plugin")
|
||||
t := u.newTable()
|
||||
t.AddColumn("Command", 18, "left")
|
||||
t.AddColumn("Description", 40, "left")
|
||||
t.AddRow("list", "List plugins")
|
||||
t.AddRow("show <name>", "Show plugin info")
|
||||
t.AddRow("install <name>", "Install plugin")
|
||||
t.AddRow("uninstall <name>", "Uninstall plugin")
|
||||
t.AddRow("enable <name>", "Enable plugin")
|
||||
t.AddRow("disable <name>", "Disable plugin")
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
command := args[0]
|
||||
fmt.Printf("Plugin command: %s (Profile: %s)\n", command, config.Profile)
|
||||
fmt.Println("Plugin operations coming soon...")
|
||||
u.info("Plugin command: " + args[0] + " (profile: " + safeProfile(config) + ")")
|
||||
u.muted("Plugin operations are not yet wired to the API.")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Enhanced automation command handlers
|
||||
// HandleAutomationEnhanced is a UI-styled stub for automation.
|
||||
func HandleAutomationEnhanced(args []string, config *types.CLIConfig) error {
|
||||
u := newUIContext(config)
|
||||
u.header("Automation Management")
|
||||
if len(args) == 0 {
|
||||
fmt.Println("Enhanced Automation Management")
|
||||
fmt.Println("Usage: telecom-cli automation <command> [options]")
|
||||
fmt.Println()
|
||||
fmt.Println("Available commands:")
|
||||
fmt.Println(" scripts - Script management")
|
||||
fmt.Println(" workflows - Workflow management")
|
||||
fmt.Println(" schedules - Schedule management")
|
||||
fmt.Println(" jobs - Job management")
|
||||
t := u.newTable()
|
||||
t.AddColumn("Command", 18, "left")
|
||||
t.AddColumn("Description", 40, "left")
|
||||
t.AddRow("scripts", "Script management")
|
||||
t.AddRow("workflows", "Workflow management")
|
||||
t.AddRow("schedules", "Schedule management")
|
||||
t.AddRow("jobs", "Job management")
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
command := args[0]
|
||||
fmt.Printf("Automation command: %s (Profile: %s)\n", command, config.Profile)
|
||||
fmt.Println("Automation operations coming soon...")
|
||||
u.info("Automation command: " + args[0] + " (profile: " + safeProfile(config) + ")")
|
||||
u.muted("Automation operations are not yet wired to the API.")
|
||||
return nil
|
||||
}
|
||||
|
||||
func safeProfile(cfg *types.CLIConfig) string {
|
||||
if cfg == nil || cfg.Profile == "" {
|
||||
return "default"
|
||||
}
|
||||
return cfg.Profile
|
||||
}
|
||||
|
||||
@@ -3,267 +3,89 @@ package commands
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/nutcas3/telecom-platform/apps/cli/internal/types"
|
||||
"github.com/nutcas3/telecom-platform/apps/cli/internal/ui"
|
||||
)
|
||||
|
||||
// HandleServicesEnhanced delegates to the UI + API-connected services handler.
|
||||
// Additional subcommands (start/stop/scale/health) use UI-styled placeholders
|
||||
// until their API endpoints are available.
|
||||
func HandleServicesEnhanced(args []string, config *types.CLIConfig) error {
|
||||
if len(args) == 0 {
|
||||
showServicesEnhancedHelp()
|
||||
return nil
|
||||
return HandleServices(args, config)
|
||||
}
|
||||
|
||||
command := args[0]
|
||||
commandArgs := args[1:]
|
||||
|
||||
switch command {
|
||||
case "list":
|
||||
return listServicesEnhanced(commandArgs, config)
|
||||
case "status":
|
||||
return showServiceStatusEnhanced(commandArgs, config)
|
||||
case "start":
|
||||
return startServiceEnhanced(commandArgs, config)
|
||||
case "stop":
|
||||
return stopServiceEnhanced(commandArgs, config)
|
||||
case "restart":
|
||||
return restartServiceEnhanced(commandArgs, config)
|
||||
case "logs":
|
||||
return showServiceLogsEnhanced(commandArgs, config)
|
||||
case "metrics":
|
||||
return showServiceMetricsEnhanced(commandArgs, config)
|
||||
case "health":
|
||||
return checkServiceHealthEnhanced(commandArgs, config)
|
||||
case "list", "status", "restart", "logs":
|
||||
return HandleServices(args, config)
|
||||
case "start", "stop":
|
||||
return lifecycleServiceUI(command, args[1:], config)
|
||||
case "scale":
|
||||
return scaleServiceEnhanced(commandArgs, config)
|
||||
return scaleServiceUI(args[1:], config)
|
||||
case "health":
|
||||
return healthServiceUI(args[1:], config)
|
||||
default:
|
||||
fmt.Printf("Unknown services command: %s\n", command)
|
||||
showServicesEnhancedHelp()
|
||||
return fmt.Errorf("unknown command: %s", command)
|
||||
u := newUIContext(config)
|
||||
u.errorln("Unknown services command: " + command)
|
||||
return HandleServices(nil, config)
|
||||
}
|
||||
}
|
||||
|
||||
func showServicesEnhancedHelp() {
|
||||
fmt.Println("Enhanced Service Management")
|
||||
fmt.Println("Usage: telecom-cli services <command> [options]")
|
||||
fmt.Println()
|
||||
fmt.Println("Available commands:")
|
||||
fmt.Println(" list - List all services")
|
||||
fmt.Println(" status <service> - Show service status")
|
||||
fmt.Println(" start <service> - Start a service")
|
||||
fmt.Println(" stop <service> - Stop a service")
|
||||
fmt.Println(" restart <service> - Restart a service")
|
||||
fmt.Println(" logs <service> - Show service logs")
|
||||
fmt.Println(" metrics <service> - Show service metrics")
|
||||
fmt.Println(" health <service> - Check service health")
|
||||
fmt.Println(" scale <service> - Scale service")
|
||||
func lifecycleServiceUI(cmd string, args []string, config *types.CLIConfig) error {
|
||||
u := newUIContext(config)
|
||||
if len(args) < 1 {
|
||||
u.errorln("Error: Service name is required")
|
||||
u.muted("Usage: telecom-cli services " + cmd + " <service>")
|
||||
return fmt.Errorf("missing service")
|
||||
}
|
||||
service := args[0]
|
||||
u.info(cmd + " service: " + service)
|
||||
u.muted("Lifecycle API endpoint not yet wired; showing placeholder confirmation.")
|
||||
u.success("Service " + service + " " + cmd + " completed (simulated)")
|
||||
return nil
|
||||
}
|
||||
|
||||
func listServicesEnhanced(args []string, config *types.CLIConfig) error {
|
||||
// Initialize UI components
|
||||
colorizer := ui.NewColorizer(!config.NoColor)
|
||||
iconRenderer := ui.NewIconRenderer(true, true)
|
||||
|
||||
// Print header with styling
|
||||
fmt.Printf("%s %s %s\n",
|
||||
colorizer.Header("Telecom Platform"),
|
||||
colorizer.Info("Services"),
|
||||
colorizer.Muted(fmt.Sprintf("(Profile: %s, Endpoint: %s)", config.Profile, config.APIEndpoint)))
|
||||
|
||||
// Create styled table
|
||||
table := ui.NewServicesTable(colorizer, iconRenderer)
|
||||
|
||||
// Add rows with styling
|
||||
services := []struct {
|
||||
name string
|
||||
status string
|
||||
version string
|
||||
cpu float64
|
||||
memory string
|
||||
uptime string
|
||||
}{
|
||||
{"api-server", "running", "v1.0.0", 45, "256MB", "2h15m"},
|
||||
{"charging-engine", "running", "v1.0.0", 23, "128MB", "2h15m"},
|
||||
{"packet-gateway", "running", "v1.0.0", 67, "512MB", "2h15m"},
|
||||
{"web-dashboard", "running", "v1.0.0", 12, "64MB", "2h15m"},
|
||||
{"prometheus", "running", "v2.45.0", 8, "32MB", "2h15m"},
|
||||
{"grafana", "running", "v9.5.2", 5, "24MB", "2h15m"},
|
||||
func scaleServiceUI(args []string, config *types.CLIConfig) error {
|
||||
u := newUIContext(config)
|
||||
if len(args) < 2 {
|
||||
u.errorln("Error: Service name and replica count are required")
|
||||
u.muted("Usage: telecom-cli services scale <service> <replicas>")
|
||||
return fmt.Errorf("missing arguments")
|
||||
}
|
||||
service, replicas := args[0], args[1]
|
||||
u.info("Scaling " + service + " to " + replicas + " replicas")
|
||||
u.muted("Scaling API endpoint not yet wired; showing placeholder confirmation.")
|
||||
u.success("Service " + service + " scaled (simulated)")
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, svc := range services {
|
||||
statusIcon := iconRenderer.StatusColored(svc.status, colorizer)
|
||||
cpuStyle := lipgloss.NewStyle()
|
||||
if svc.cpu >= 70 {
|
||||
cpuStyle = ui.StyleMetricCritical.Style
|
||||
} else if svc.cpu >= 50 {
|
||||
cpuStyle = ui.StyleMetricWarning.Style
|
||||
} else {
|
||||
cpuStyle = ui.StyleMetricGood.Style
|
||||
func healthServiceUI(args []string, config *types.CLIConfig) error {
|
||||
u := newUIContext(config)
|
||||
target := "all"
|
||||
if len(args) > 0 {
|
||||
target = args[0]
|
||||
}
|
||||
u.header("Service Health: " + target)
|
||||
|
||||
health, err := u.client.GetHealth()
|
||||
t := u.newTable()
|
||||
t.AddColumn("Service", 18, "left")
|
||||
t.AddColumn("Status", 10, "left")
|
||||
t.AddColumn("Uptime", 10, "right")
|
||||
|
||||
if err != nil {
|
||||
u.warn("Using placeholder data: " + err.Error())
|
||||
t.AddStyledRow(statusStyle("HEALTHY").Style, "api-server", "Healthy", "99.9%")
|
||||
t.AddStyledRow(statusStyle("HEALTHY").Style, "charging-engine", "Healthy", "99.8%")
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
for _, h := range health {
|
||||
if target != "all" && h.Service != target {
|
||||
continue
|
||||
}
|
||||
|
||||
table.AddStyledCellRow(
|
||||
ui.TableCell{Text: statusIcon, Align: "center"},
|
||||
ui.TableCell{Text: svc.name},
|
||||
ui.TableCell{Text: iconRenderer.StatusColored(svc.status, colorizer), Align: "center"},
|
||||
ui.TableCell{Text: svc.version, Align: "center"},
|
||||
ui.TableCell{Text: colorizer.Metric(svc.cpu), Style: cpuStyle, Align: "right"},
|
||||
ui.TableCell{Text: iconRenderer.Memory() + " " + svc.memory, Align: "right"},
|
||||
ui.TableCell{Text: iconRenderer.Clock() + " " + svc.uptime, Align: "right"},
|
||||
)
|
||||
t.AddStyledRow(statusStyle(h.Status).Style, h.Service, h.Status, h.Uptime)
|
||||
}
|
||||
|
||||
// Render the table
|
||||
fmt.Println(table.Render())
|
||||
|
||||
// Add summary with metrics
|
||||
runningCount := 6
|
||||
totalCPU := 45 + 23 + 67 + 12 + 8 + 5
|
||||
avgCPU := float64(totalCPU) / float64(runningCount)
|
||||
|
||||
fmt.Printf("\n%s %s %s, %s: %s, %s: %s\n",
|
||||
colorizer.Info("Summary:"),
|
||||
colorizer.Success(fmt.Sprintf("%d", runningCount)),
|
||||
colorizer.Success("running"),
|
||||
colorizer.Info("Avg CPU"),
|
||||
colorizer.Metric(avgCPU),
|
||||
colorizer.Info("Status"),
|
||||
colorizer.Success("healthy"))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func showServiceStatusEnhanced(args []string, config *types.CLIConfig) error {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: Service name is required")
|
||||
fmt.Println("Usage: telecom-cli services status <service>")
|
||||
return fmt.Errorf("missing service name")
|
||||
}
|
||||
|
||||
service := args[0]
|
||||
fmt.Printf("Service Status: %s (Profile: %s)\n", service, config.Profile)
|
||||
fmt.Println("========================================")
|
||||
fmt.Printf("Status: Running\n")
|
||||
fmt.Printf("Version: v1.0.0\n")
|
||||
fmt.Printf("Uptime: 2h15m\n")
|
||||
fmt.Printf("CPU Usage: 45%%\n")
|
||||
fmt.Printf("Memory Usage: 256MB\n")
|
||||
fmt.Printf("Last Restart: 2024-01-15 14:30:00\n")
|
||||
fmt.Printf("Health Check: Healthy\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
func startServiceEnhanced(args []string, config *types.CLIConfig) error {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: Service name is required")
|
||||
fmt.Println("Usage: telecom-cli services start <service>")
|
||||
return fmt.Errorf("missing service name")
|
||||
}
|
||||
|
||||
service := args[0]
|
||||
fmt.Printf("Starting service: %s (Profile: %s)\n", service, config.Profile)
|
||||
fmt.Println("Service started successfully!")
|
||||
return nil
|
||||
}
|
||||
|
||||
func stopServiceEnhanced(args []string, config *types.CLIConfig) error {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: Service name is required")
|
||||
fmt.Println("Usage: telecom-cli services stop <service>")
|
||||
return fmt.Errorf("missing service name")
|
||||
}
|
||||
|
||||
service := args[0]
|
||||
fmt.Printf("Stopping service: %s (Profile: %s)\n", service, config.Profile)
|
||||
fmt.Println("Service stopped successfully!")
|
||||
return nil
|
||||
}
|
||||
|
||||
func restartServiceEnhanced(args []string, config *types.CLIConfig) error {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: Service name is required")
|
||||
fmt.Println("Usage: telecom-cli services restart <service>")
|
||||
return fmt.Errorf("missing service name")
|
||||
}
|
||||
|
||||
service := args[0]
|
||||
fmt.Printf("Restarting service: %s (Profile: %s)\n", service, config.Profile)
|
||||
fmt.Println("Service restarted successfully!")
|
||||
return nil
|
||||
}
|
||||
|
||||
func showServiceLogsEnhanced(args []string, config *types.CLIConfig) error {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: Service name is required")
|
||||
fmt.Println("Usage: telecom-cli services logs <service>")
|
||||
return fmt.Errorf("missing service name")
|
||||
}
|
||||
|
||||
service := args[0]
|
||||
fmt.Printf("Recent logs for %s (Profile: %s):\n", service, config.Profile)
|
||||
fmt.Println("2024-01-15 16:45:30 [INFO] Service started successfully")
|
||||
fmt.Println("2024-01-15 16:45:35 [INFO] Database connection established")
|
||||
fmt.Println("2024-01-15 16:45:40 [INFO] API server listening on port 8000")
|
||||
fmt.Println("2024-01-15 16:45:45 [INFO] Health check passed")
|
||||
fmt.Println("2024-01-15 16:45:50 [WARN] High memory usage detected")
|
||||
fmt.Println("2024-01-15 16:45:55 [ERROR] Database connection timeout")
|
||||
fmt.Println("2024-01-15 16:46:00 [INFO] Database connection restored")
|
||||
return nil
|
||||
}
|
||||
|
||||
func showServiceMetricsEnhanced(args []string, config *types.CLIConfig) error {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: Service name is required")
|
||||
fmt.Println("Usage: telecom-cli services metrics <service>")
|
||||
return fmt.Errorf("missing service name")
|
||||
}
|
||||
|
||||
service := args[0]
|
||||
fmt.Printf("Metrics for %s (Profile: %s):\n", service, config.Profile)
|
||||
fmt.Println("========================================")
|
||||
fmt.Printf("Request Rate: 450 req/s\n")
|
||||
fmt.Printf("Response Time: 125ms avg\n")
|
||||
fmt.Printf("Error Rate: 0.5%%\n")
|
||||
fmt.Printf("Throughput: 1.2GB/s\n")
|
||||
fmt.Printf("Connections: 150 active\n")
|
||||
fmt.Printf("Memory Usage: 256MB / 512MB\n")
|
||||
fmt.Printf("CPU Usage: 45%%\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkServiceHealthEnhanced(args []string, config *types.CLIConfig) error {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: Service name is required")
|
||||
fmt.Println("Usage: telecom-cli services health <service>")
|
||||
return fmt.Errorf("missing service name")
|
||||
}
|
||||
|
||||
service := args[0]
|
||||
fmt.Printf("Health check for %s (Profile: %s):\n", service, config.Profile)
|
||||
fmt.Println("========================================")
|
||||
fmt.Printf("Overall Status: Healthy\n")
|
||||
fmt.Printf("Database: Connected\n")
|
||||
fmt.Printf("Redis: Connected\n")
|
||||
fmt.Printf("API Endpoint: Responsive\n")
|
||||
fmt.Printf("Dependencies: All healthy\n")
|
||||
fmt.Printf("Last Check: 2024-01-15 16:46:30\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
func scaleServiceEnhanced(args []string, config *types.CLIConfig) error {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: Service name is required")
|
||||
fmt.Println("Usage: telecom-cli services scale <service> [replicas]")
|
||||
return fmt.Errorf("missing service name")
|
||||
}
|
||||
|
||||
service := args[0]
|
||||
replicas := 3
|
||||
if len(args) > 1 {
|
||||
// Parse replicas from args[1]
|
||||
fmt.Printf("Scaling %s to %d replicas (Profile: %s)\n", service, replicas, config.Profile)
|
||||
} else {
|
||||
fmt.Printf("Scaling %s to default %d replicas (Profile: %s)\n", service, replicas, config.Profile)
|
||||
}
|
||||
fmt.Println("Service scaled successfully!")
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,387 +3,143 @@ package commands
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/nutcas3/telecom-platform/apps/cli/internal/types"
|
||||
"github.com/nutcas3/telecom-platform/apps/cli/internal/ui"
|
||||
)
|
||||
|
||||
// HandleSubscribersEnhanced delegates to the UI + API-connected subscribers handler.
|
||||
// It also supports a few extra subcommands (activate/deactivate/balance/usage/search)
|
||||
// that fall back to informative UI-styled placeholders until their API endpoints
|
||||
// are wired up.
|
||||
func HandleSubscribersEnhanced(args []string, config *types.CLIConfig) error {
|
||||
if len(args) == 0 {
|
||||
showSubscribersEnhancedHelp()
|
||||
return nil
|
||||
return HandleSubscribers(args, config)
|
||||
}
|
||||
|
||||
command := args[0]
|
||||
commandArgs := args[1:]
|
||||
|
||||
switch command {
|
||||
case "list":
|
||||
return listSubscribersEnhanced(commandArgs, config)
|
||||
case "show":
|
||||
return showSubscriberEnhanced(commandArgs, config)
|
||||
case "create":
|
||||
return createSubscriberEnhanced(commandArgs, config)
|
||||
case "list", "show", "create", "delete":
|
||||
return HandleSubscribers(args, config)
|
||||
case "update":
|
||||
return updateSubscriberEnhanced(commandArgs, config)
|
||||
case "delete":
|
||||
return deleteSubscriberEnhanced(commandArgs, config)
|
||||
case "activate":
|
||||
return activateSubscriberEnhanced(commandArgs, config)
|
||||
case "deactivate":
|
||||
return deactivateSubscriberEnhanced(commandArgs, config)
|
||||
return updateSubscriberUI(args[1:], config)
|
||||
case "activate", "deactivate":
|
||||
return toggleSubscriberUI(command, args[1:], config)
|
||||
case "balance":
|
||||
return checkBalanceEnhanced(commandArgs, config)
|
||||
return balanceSubscriberUI(args[1:], config)
|
||||
case "usage":
|
||||
return showUsageEnhanced(commandArgs, config)
|
||||
return usageSubscriberUI(args[1:], config)
|
||||
case "search":
|
||||
return searchSubscribersEnhanced(commandArgs, config)
|
||||
return searchSubscribersUI(args[1:], config)
|
||||
default:
|
||||
fmt.Printf("Unknown subscribers command: %s\n", command)
|
||||
showSubscribersEnhancedHelp()
|
||||
return fmt.Errorf("unknown command: %s", command)
|
||||
u := newUIContext(config)
|
||||
u.errorln("Unknown subscribers command: " + command)
|
||||
return HandleSubscribers(nil, config)
|
||||
}
|
||||
}
|
||||
|
||||
func showSubscribersEnhancedHelp() {
|
||||
fmt.Println("Enhanced Subscriber Management")
|
||||
fmt.Println("Usage: telecom-cli subscribers <command> [options]")
|
||||
fmt.Println()
|
||||
fmt.Println("Available commands:")
|
||||
fmt.Println(" list - List all subscribers (with filtering)")
|
||||
fmt.Println(" show <imsi> - Show subscriber details")
|
||||
fmt.Println(" create <imsi> <name> - Create a new subscriber")
|
||||
fmt.Println(" update <imsi> - Update subscriber information")
|
||||
fmt.Println(" delete <imsi> - Delete a subscriber")
|
||||
fmt.Println(" activate <imsi> - Activate subscriber")
|
||||
fmt.Println(" deactivate <imsi> - Deactivate subscriber")
|
||||
fmt.Println(" balance <imsi> - Check subscriber balance")
|
||||
fmt.Println(" usage <imsi> - Show usage statistics")
|
||||
fmt.Println(" search <query> - Search subscribers")
|
||||
fmt.Println()
|
||||
fmt.Println("Global options:")
|
||||
fmt.Println(" --format <format> Output format (table, json, yaml)")
|
||||
fmt.Println(" --filter <filter> Filter results")
|
||||
fmt.Println(" --sort <field> Sort by field")
|
||||
fmt.Println(" --limit <count> Limit results")
|
||||
}
|
||||
|
||||
func listSubscribersEnhanced(args []string, config *types.CLIConfig) error {
|
||||
// Initialize UI components
|
||||
colorizer := ui.NewColorizer(!config.NoColor)
|
||||
iconRenderer := ui.NewIconRenderer(true, true)
|
||||
|
||||
// Print header with lipgloss styling
|
||||
header := lipgloss.JoinHorizontal(lipgloss.Left,
|
||||
colorizer.Header("Telecom Platform"),
|
||||
colorizer.Info("Subscribers"),
|
||||
colorizer.Muted(fmt.Sprintf("(Profile: %s, Endpoint: %s)", config.Profile, config.APIEndpoint)),
|
||||
)
|
||||
fmt.Println(header)
|
||||
|
||||
// Parse options
|
||||
format := "table"
|
||||
filter := ""
|
||||
sort := "name"
|
||||
limit := 50
|
||||
|
||||
for i := 0; i < len(args); i++ {
|
||||
switch args[i] {
|
||||
case "--format":
|
||||
if i+1 < len(args) {
|
||||
format = args[i+1]
|
||||
i++
|
||||
}
|
||||
case "--filter":
|
||||
if i+1 < len(args) {
|
||||
filter = args[i+1]
|
||||
i++
|
||||
}
|
||||
case "--sort":
|
||||
if i+1 < len(args) {
|
||||
sort = args[i+1]
|
||||
i++
|
||||
}
|
||||
case "--limit":
|
||||
if i+1 < len(args) {
|
||||
limit = parseInt(args[i+1])
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if config.Verbose {
|
||||
debugInfo := lipgloss.JoinHorizontal(lipgloss.Left,
|
||||
colorizer.Debug("Debug"),
|
||||
colorizer.Option("Format: "+format),
|
||||
colorizer.Option("Filter: "+filter),
|
||||
colorizer.Option("Sort: "+sort),
|
||||
colorizer.Option(fmt.Sprintf("Limit: %d", limit)),
|
||||
)
|
||||
fmt.Println(debugInfo)
|
||||
}
|
||||
|
||||
// Create styled table with lipgloss
|
||||
table := ui.NewSubscribersTable(colorizer, iconRenderer)
|
||||
|
||||
// Add rows with lipgloss styling
|
||||
subscribers := []struct {
|
||||
imsi string
|
||||
name string
|
||||
status string
|
||||
balance string
|
||||
plan string
|
||||
lastActivity string
|
||||
}{
|
||||
{"310260123456789", "John Doe", "active", "$45.67", "Premium", "2024-01-15 16:45"},
|
||||
{"310260123456790", "Jane Smith", "active", "$123.45", "Business", "2024-01-15 16:30"},
|
||||
{"310260123456791", "Bob Johnson", "inactive", "$0.00", "Basic", "2024-01-14 12:15"},
|
||||
{"310260123456792", "Alice Brown", "active", "$89.23", "Premium", "2024-01-15 15:20"},
|
||||
{"310260123456793", "Charlie Davis", "active", "$234.56", "Enterprise", "2024-01-15 14:10"},
|
||||
}
|
||||
|
||||
for _, sub := range subscribers {
|
||||
statusIcon := iconRenderer.StatusColored(sub.status, colorizer)
|
||||
balanceStyle := lipgloss.NewStyle()
|
||||
if sub.status == "active" {
|
||||
balanceStyle = ui.StyleSuccess.Style
|
||||
} else {
|
||||
balanceStyle = ui.StyleMuted.Style
|
||||
}
|
||||
|
||||
table.AddStyledCellRow(
|
||||
ui.TableCell{Text: statusIcon, Align: "center"},
|
||||
ui.TableCell{Text: sub.imsi},
|
||||
ui.TableCell{Text: sub.name},
|
||||
ui.TableCell{Text: iconRenderer.StatusColored(sub.status, colorizer), Align: "center"},
|
||||
ui.TableCell{Text: sub.balance, Style: balanceStyle, Align: "right"},
|
||||
ui.TableCell{Text: sub.plan},
|
||||
ui.TableCell{Text: sub.lastActivity, Align: "center"},
|
||||
)
|
||||
}
|
||||
|
||||
// Render the table
|
||||
fmt.Println(table.Render())
|
||||
|
||||
// Add summary with lipgloss styling
|
||||
activeCount := 4
|
||||
inactiveCount := 1
|
||||
summary := lipgloss.JoinHorizontal(lipgloss.Left,
|
||||
colorizer.Info("Summary:"),
|
||||
colorizer.Success(fmt.Sprintf("%d active", activeCount)),
|
||||
colorizer.Error(fmt.Sprintf("%d inactive", inactiveCount)),
|
||||
)
|
||||
fmt.Printf("\n%s\n", summary)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func showSubscriberEnhanced(args []string, config *types.CLIConfig) error {
|
||||
func updateSubscriberUI(args []string, config *types.CLIConfig) error {
|
||||
u := newUIContext(config)
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: IMSI is required")
|
||||
fmt.Println("Usage: telecom-cli subscribers show <imsi>")
|
||||
return fmt.Errorf("missing IMSI")
|
||||
u.errorln("Error: IMSI is required")
|
||||
u.muted("Usage: telecom-cli subscribers update <imsi>")
|
||||
return fmt.Errorf("missing imsi")
|
||||
}
|
||||
|
||||
imsi := args[0]
|
||||
fmt.Printf("Subscriber Details: IMSI=%s (Profile: %s)\n", imsi, config.Profile)
|
||||
|
||||
fmt.Println("=========================================")
|
||||
fmt.Printf("IMSI: %s\n", imsi)
|
||||
fmt.Printf("Name: John Doe\n")
|
||||
fmt.Printf("Status: Active\n")
|
||||
fmt.Printf("Plan: Premium\n")
|
||||
fmt.Printf("Balance: $45.67\n")
|
||||
fmt.Printf("Since: 2023-06-15\n")
|
||||
fmt.Println()
|
||||
fmt.Println("Usage Statistics:")
|
||||
fmt.Printf("Data Used: 2.3GB / 10GB (23%%)\n")
|
||||
fmt.Printf("Voice Used: 45min / 500min (9%%)\n")
|
||||
fmt.Printf("SMS Used: 23 / 100 (23%%)\n")
|
||||
fmt.Println()
|
||||
fmt.Println("Recent Activity:")
|
||||
fmt.Println("2024-01-15 16:45 - Data session: 45MB")
|
||||
fmt.Println("2024-01-15 16:30 - Voice call: 5min")
|
||||
fmt.Println("2024-01-15 16:15 - SMS sent: 2 messages")
|
||||
fmt.Println("2024-01-15 15:20 - Data session: 120MB")
|
||||
|
||||
u.info("Update subscriber: " + args[0])
|
||||
u.muted("Update API endpoint is not yet wired; showing placeholder confirmation.")
|
||||
u.success("Subscriber update accepted (simulated)")
|
||||
return nil
|
||||
}
|
||||
|
||||
func createSubscriberEnhanced(args []string, config *types.CLIConfig) error {
|
||||
if len(args) < 2 {
|
||||
fmt.Println("Error: IMSI and name are required")
|
||||
fmt.Println("Usage: telecom-cli subscribers create <imsi> <name> [options]")
|
||||
return fmt.Errorf("missing required arguments")
|
||||
}
|
||||
|
||||
imsi := args[0]
|
||||
name := args[1]
|
||||
|
||||
// Parse additional options
|
||||
plan := "Basic"
|
||||
balance := 0.0
|
||||
|
||||
for i := 2; i < len(args); i++ {
|
||||
switch args[i] {
|
||||
case "--plan":
|
||||
if i+1 < len(args) {
|
||||
plan = args[i+1]
|
||||
i++
|
||||
}
|
||||
case "--balance":
|
||||
if i+1 < len(args) {
|
||||
balance = parseFloat(args[i+1])
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Creating subscriber (Profile: %s):\n", config.Profile)
|
||||
fmt.Printf(" IMSI: %s\n", imsi)
|
||||
fmt.Printf(" Name: %s\n", name)
|
||||
fmt.Printf(" Plan: %s\n", plan)
|
||||
fmt.Printf(" Balance: $%.2f\n", balance)
|
||||
|
||||
if config.Verbose {
|
||||
fmt.Println("Connecting to API...")
|
||||
fmt.Printf("POST %s/api/subscribers\n", config.APIEndpoint)
|
||||
}
|
||||
|
||||
fmt.Println("Subscriber created successfully!")
|
||||
fmt.Printf("Subscriber ID: %s\n", imsi)
|
||||
fmt.Printf("Account created with initial balance: $%.2f\n", balance)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateSubscriberEnhanced(args []string, config *types.CLIConfig) error {
|
||||
func toggleSubscriberUI(cmd string, args []string, config *types.CLIConfig) error {
|
||||
u := newUIContext(config)
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: IMSI is required")
|
||||
fmt.Println("Usage: telecom-cli subscribers update <imsi> [options]")
|
||||
return fmt.Errorf("missing IMSI")
|
||||
u.errorln("Error: IMSI is required")
|
||||
u.muted("Usage: telecom-cli subscribers " + cmd + " <imsi>")
|
||||
return fmt.Errorf("missing imsi")
|
||||
}
|
||||
|
||||
imsi := args[0]
|
||||
fmt.Printf("Updating subscriber: IMSI=%s (Profile: %s)\n", imsi, config.Profile)
|
||||
fmt.Println("Subscriber updated successfully!")
|
||||
|
||||
u.info(cmd + " subscriber: " + imsi)
|
||||
u.muted("Activation API endpoint is not yet wired; showing placeholder confirmation.")
|
||||
u.success("Subscriber " + cmd + " completed (simulated)")
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteSubscriberEnhanced(args []string, config *types.CLIConfig) error {
|
||||
func balanceSubscriberUI(args []string, config *types.CLIConfig) error {
|
||||
u := newUIContext(config)
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: IMSI is required")
|
||||
fmt.Println("Usage: telecom-cli subscribers delete <imsi>")
|
||||
return fmt.Errorf("missing IMSI")
|
||||
u.errorln("Error: IMSI is required")
|
||||
u.muted("Usage: telecom-cli subscribers balance <imsi>")
|
||||
return fmt.Errorf("missing imsi")
|
||||
}
|
||||
|
||||
imsi := args[0]
|
||||
fmt.Printf("Deleting subscriber: IMSI=%s (Profile: %s)\n", imsi, config.Profile)
|
||||
fmt.Println("Subscriber deleted successfully!")
|
||||
u.header("Subscriber Balance: " + imsi)
|
||||
|
||||
sub, err := u.client.GetSubscriber(imsi)
|
||||
t := u.newTable()
|
||||
t.AddColumn("Field", 14, "left")
|
||||
t.AddColumn("Value", 24, "left")
|
||||
if err != nil {
|
||||
u.warn("Using placeholder data: " + err.Error())
|
||||
t.AddRow("IMSI", imsi)
|
||||
t.AddRow("Balance", "$45.67")
|
||||
t.AddRow("Currency", "USD")
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
t.AddRow("IMSI", sub.IMSI)
|
||||
t.AddRow("Name", sub.Name)
|
||||
t.AddRow("Balance", fmt.Sprintf("$%.2f", sub.Balance))
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
func activateSubscriberEnhanced(args []string, config *types.CLIConfig) error {
|
||||
func usageSubscriberUI(args []string, config *types.CLIConfig) error {
|
||||
u := newUIContext(config)
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: IMSI is required")
|
||||
fmt.Println("Usage: telecom-cli subscribers activate <imsi>")
|
||||
return fmt.Errorf("missing IMSI")
|
||||
u.errorln("Error: IMSI is required")
|
||||
u.muted("Usage: telecom-cli subscribers usage <imsi>")
|
||||
return fmt.Errorf("missing imsi")
|
||||
}
|
||||
|
||||
imsi := args[0]
|
||||
fmt.Printf("Activating subscriber: IMSI=%s (Profile: %s)\n", imsi, config.Profile)
|
||||
fmt.Println("Subscriber activated successfully!")
|
||||
u.header("Subscriber Usage: " + imsi)
|
||||
u.muted("(Usage API endpoint not yet wired - showing placeholder)")
|
||||
|
||||
t := u.newTable()
|
||||
t.AddColumn("Metric", 14, "left")
|
||||
t.AddColumn("Used", 14, "right")
|
||||
t.AddColumn("Limit", 14, "right")
|
||||
t.AddRow("Data", "2.3 GB", "10 GB")
|
||||
t.AddRow("Voice", "45 min", "500 min")
|
||||
t.AddRow("SMS", "23", "100")
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
func deactivateSubscriberEnhanced(args []string, config *types.CLIConfig) error {
|
||||
func searchSubscribersUI(args []string, config *types.CLIConfig) error {
|
||||
u := newUIContext(config)
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: IMSI is required")
|
||||
fmt.Println("Usage: telecom-cli subscribers deactivate <imsi>")
|
||||
return fmt.Errorf("missing IMSI")
|
||||
u.errorln("Error: search query is required")
|
||||
u.muted("Usage: telecom-cli subscribers search <query>")
|
||||
return fmt.Errorf("missing query")
|
||||
}
|
||||
u.header("Search Subscribers: " + args[0])
|
||||
|
||||
imsi := args[0]
|
||||
fmt.Printf("Deactivating subscriber: IMSI=%s (Profile: %s)\n", imsi, config.Profile)
|
||||
fmt.Println("Subscriber deactivated successfully!")
|
||||
subs, err := u.client.ListSubscribers()
|
||||
t := u.newTable()
|
||||
t.AddColumn("IMSI", 16, "left")
|
||||
t.AddColumn("Name", 22, "left")
|
||||
t.AddColumn("Status", 10, "left")
|
||||
t.AddColumn("Balance", 10, "right")
|
||||
|
||||
if err != nil {
|
||||
u.warn("Using placeholder data: " + err.Error())
|
||||
t.AddStyledRow(statusStyle("ACTIVE").Style, "310260123456789", "John Doe", "Active", "$45.67")
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
for _, s := range subs {
|
||||
t.AddStyledRow(statusStyle(s.Status).Style,
|
||||
s.IMSI, s.Name, s.Status, fmt.Sprintf("$%.2f", s.Balance))
|
||||
}
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkBalanceEnhanced(args []string, config *types.CLIConfig) error {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: IMSI is required")
|
||||
fmt.Println("Usage: telecom-cli subscribers balance <imsi>")
|
||||
return fmt.Errorf("missing IMSI")
|
||||
}
|
||||
|
||||
imsi := args[0]
|
||||
fmt.Printf("Balance for subscriber IMSI=%s (Profile: %s):\n", imsi, config.Profile)
|
||||
fmt.Printf("Current Balance: $45.67\n")
|
||||
fmt.Printf("Last Top-up: $50.00 on 2024-01-10\n")
|
||||
fmt.Printf("Monthly Usage: $12.33\n")
|
||||
fmt.Printf("Available Credit: $33.34\n")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func showUsageEnhanced(args []string, config *types.CLIConfig) error {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: IMSI is required")
|
||||
fmt.Println("Usage: telecom-cli subscribers usage <imsi>")
|
||||
return fmt.Errorf("missing IMSI")
|
||||
}
|
||||
|
||||
imsi := args[0]
|
||||
fmt.Printf("Usage Statistics for IMSI=%s (Profile: %s):\n", imsi, config.Profile)
|
||||
|
||||
fmt.Println("Current Billing Period (2024-01)")
|
||||
fmt.Println("Data Usage:")
|
||||
fmt.Printf(" Used: 2.3GB\n")
|
||||
fmt.Printf(" Limit: 10GB\n")
|
||||
fmt.Printf(" Remaining: 7.7GB\n")
|
||||
fmt.Println()
|
||||
fmt.Println("Voice Usage:")
|
||||
fmt.Printf(" Used: 45 minutes\n")
|
||||
fmt.Printf(" Limit: 500 minutes\n")
|
||||
fmt.Printf(" Remaining: 455 minutes\n")
|
||||
fmt.Println()
|
||||
fmt.Println("SMS Usage:")
|
||||
fmt.Printf(" Used: 23 messages\n")
|
||||
fmt.Printf(" Limit: 100 messages\n")
|
||||
fmt.Printf(" Remaining: 77 messages\n")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func searchSubscribersEnhanced(args []string, config *types.CLIConfig) error {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: Search query is required")
|
||||
fmt.Println("Usage: telecom-cli subscribers search <query>")
|
||||
return fmt.Errorf("missing search query")
|
||||
}
|
||||
|
||||
query := args[0]
|
||||
fmt.Printf("Searching subscribers for: %s (Profile: %s)\n", query, config.Profile)
|
||||
fmt.Println("Search Results:")
|
||||
fmt.Println("IMSI Name Status Balance")
|
||||
fmt.Println("----------------------------------------------------")
|
||||
fmt.Println("310260123456789 John Doe Active $45.67")
|
||||
fmt.Println("310260123456792 Alice Brown Active $89.23")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
func parseInt(s string) int {
|
||||
// Simple implementation - in real code would use strconv.Atoi
|
||||
return 50
|
||||
}
|
||||
|
||||
func parseFloat(s string) float64 {
|
||||
// Simple implementation - in real code would use strconv.ParseFloat
|
||||
return 0.0
|
||||
}
|
||||
|
||||
@@ -2,87 +2,181 @@ package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/nutcas3/telecom-platform/apps/cli/internal/types"
|
||||
)
|
||||
|
||||
func HandleMonitoring(args []string) {
|
||||
// HandleMonitoring is the entry point for monitoring commands.
|
||||
func HandleMonitoring(args []string, config *types.CLIConfig) error {
|
||||
u := newUIContext(config)
|
||||
if len(args) == 0 {
|
||||
showMonitoringHelp()
|
||||
return
|
||||
showMonitoringHelp(u)
|
||||
return nil
|
||||
}
|
||||
|
||||
u.connectivityBanner()
|
||||
|
||||
command := args[0]
|
||||
switch command {
|
||||
case "metrics":
|
||||
showMetrics()
|
||||
return showMetrics(u)
|
||||
case "alerts":
|
||||
showAlerts()
|
||||
return showAlerts(u)
|
||||
case "health":
|
||||
showHealth()
|
||||
return showHealth(u)
|
||||
case "logs":
|
||||
showLogs(args[1:])
|
||||
return showLogs(u, args[1:])
|
||||
default:
|
||||
fmt.Printf("Unknown monitoring command: %s\n", command)
|
||||
showMonitoringHelp()
|
||||
u.errorln("Unknown monitoring command: " + command)
|
||||
showMonitoringHelp(u)
|
||||
return fmt.Errorf("unknown command: %s", command)
|
||||
}
|
||||
}
|
||||
|
||||
func showMonitoringHelp() {
|
||||
fmt.Println("Monitoring Management")
|
||||
fmt.Println("Usage: telecom-cli monitoring <command> [options]")
|
||||
fmt.Println("\nAvailable commands:")
|
||||
fmt.Println(" metrics - Show system metrics")
|
||||
fmt.Println(" alerts - Show active alerts")
|
||||
fmt.Println(" health - Show system health")
|
||||
fmt.Println(" logs <service> - Show service logs")
|
||||
func showMonitoringHelp(u *uiContext) {
|
||||
u.header("Monitoring Management")
|
||||
u.muted("Usage: telecom-cli monitoring <command> [options]")
|
||||
fmt.Println()
|
||||
|
||||
t := u.newTable()
|
||||
t.AddColumn("Command", 18, "left")
|
||||
t.AddColumn("Description", 40, "left")
|
||||
t.AddRow("metrics", "Show system metrics")
|
||||
t.AddRow("alerts", "Show active alerts")
|
||||
t.AddRow("health", "Show system health")
|
||||
t.AddRow("logs <service>", "Show service logs")
|
||||
fmt.Println(t.Render())
|
||||
}
|
||||
|
||||
func showMetrics() {
|
||||
fmt.Println("System Metrics:")
|
||||
fmt.Println("Metric Value Status")
|
||||
fmt.Println("----------------------------------------------------")
|
||||
fmt.Println("API Response Time 125ms Good")
|
||||
fmt.Println("Database Connections 15/100 Good")
|
||||
fmt.Println("CPU Usage 45% Good")
|
||||
fmt.Println("Memory Usage 2.3GB/8GB Good")
|
||||
fmt.Println("Disk Usage 45% Good")
|
||||
fmt.Println("Network Throughput 1.2GB/s Good")
|
||||
fmt.Println("Active Subscribers 1,234 Good")
|
||||
fmt.Println("Request Rate 450/s Good")
|
||||
func showMetrics(u *uiContext) error {
|
||||
u.header("System Metrics")
|
||||
|
||||
stats, err := u.client.GetSystemStats()
|
||||
t := u.newTable()
|
||||
t.AddColumn("Metric", 24, "left")
|
||||
t.AddColumn("Value", 16, "right")
|
||||
t.AddColumn("Status", 10, "left")
|
||||
|
||||
if err != nil {
|
||||
u.warn("Using placeholder data: " + err.Error())
|
||||
rows := [][]string{
|
||||
{"API Response Time", "125ms", "Good"},
|
||||
{"Database Connections", "15/100", "Good"},
|
||||
{"CPU Usage", "45%", "Good"},
|
||||
{"Memory Usage", "2.3GB/8GB", "Good"},
|
||||
{"Active Subscribers", "1234", "Good"},
|
||||
{"Request Rate", "450/s", "Good"},
|
||||
}
|
||||
for _, r := range rows {
|
||||
t.AddStyledRow(statusStyle("HEALTHY").Style, r[0], r[1], r[2])
|
||||
}
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
t.AddRow("Active Sessions", fmt.Sprintf("%d", stats.ActiveSessions))
|
||||
t.AddRow("Total Accounts", fmt.Sprintf("%d", stats.TotalAccounts))
|
||||
t.AddRow("Blocked Users", fmt.Sprintf("%d", stats.BlockedUsers))
|
||||
t.AddRow("Low Balance Alerts", fmt.Sprintf("%d", stats.LowBalanceAlerts))
|
||||
t.AddRow("CPU Usage", fmt.Sprintf("%.1f%%", stats.CPUUsage))
|
||||
t.AddRow("Memory Usage", fmt.Sprintf("%.1f%%", stats.MemoryUsage))
|
||||
t.AddRow("Uptime", stats.Uptime)
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
func showAlerts() {
|
||||
fmt.Println("Active Alerts:")
|
||||
fmt.Println("Severity Service Message Time")
|
||||
fmt.Println("--------------------------------------------------------------------")
|
||||
fmt.Println("High API Server High memory usage detected 14:30")
|
||||
fmt.Println("Medium Database Slow query detected 14:25")
|
||||
fmt.Println("Low Gateway Packet loss increased 14:20")
|
||||
func showAlerts(u *uiContext) error {
|
||||
u.header("Active Alerts")
|
||||
|
||||
alerts, err := u.client.ListAlerts()
|
||||
t := u.newTable()
|
||||
t.AddColumn("Severity", 10, "left")
|
||||
t.AddColumn("Service", 16, "left")
|
||||
t.AddColumn("Message", 40, "left")
|
||||
t.AddColumn("Time", 10, "left")
|
||||
|
||||
if err != nil {
|
||||
u.warn("Using placeholder data: " + err.Error())
|
||||
rows := [][]string{
|
||||
{"High", "API Server", "High memory usage detected", "14:30"},
|
||||
{"Medium", "Database", "Slow query detected", "14:25"},
|
||||
{"Low", "Gateway", "Packet loss increased", "14:20"},
|
||||
}
|
||||
for _, r := range rows {
|
||||
style := statusStyle(strings.ToUpper(r[0]))
|
||||
if r[0] == "High" {
|
||||
style = statusStyle("ERROR")
|
||||
} else if r[0] == "Medium" {
|
||||
style = statusStyle("WARNING")
|
||||
}
|
||||
t.AddStyledRow(style.Style, r[0], r[1], r[2], r[3])
|
||||
}
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
for _, a := range alerts {
|
||||
style := statusStyle(strings.ToUpper(a.Severity))
|
||||
t.AddStyledRow(style.Style, a.Severity, a.Service, a.Message, a.Time.Format("15:04"))
|
||||
}
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
func showHealth() {
|
||||
fmt.Println("System Health Status:")
|
||||
fmt.Println("Service Status Uptime Last Check")
|
||||
fmt.Println("----------------------------------------------------")
|
||||
fmt.Println("API Server Healthy 99.9% 14:45:30")
|
||||
fmt.Println("Charging Engine Healthy 99.8% 14:45:30")
|
||||
fmt.Println("Packet Gateway Healthy 99.7% 14:45:30")
|
||||
fmt.Println("Web Dashboard Healthy 99.9% 14:45:30")
|
||||
fmt.Println("Database Healthy 99.5% 14:45:30")
|
||||
fmt.Println("Redis Healthy 99.9% 14:45:30")
|
||||
func showHealth(u *uiContext) error {
|
||||
u.header("System Health Status")
|
||||
|
||||
health, err := u.client.GetHealth()
|
||||
t := u.newTable()
|
||||
t.AddColumn("Service", 18, "left")
|
||||
t.AddColumn("Status", 10, "left")
|
||||
t.AddColumn("Uptime", 10, "right")
|
||||
t.AddColumn("Last Check", 12, "right")
|
||||
|
||||
if err != nil {
|
||||
u.warn("Using placeholder data: " + err.Error())
|
||||
rows := [][]string{
|
||||
{"API Server", "Healthy", "99.9%", "14:45:30"},
|
||||
{"Charging Engine", "Healthy", "99.8%", "14:45:30"},
|
||||
{"Packet Gateway", "Healthy", "99.7%", "14:45:30"},
|
||||
{"Web Dashboard", "Healthy", "99.9%", "14:45:30"},
|
||||
{"Database", "Healthy", "99.5%", "14:45:30"},
|
||||
{"Redis", "Healthy", "99.9%", "14:45:30"},
|
||||
}
|
||||
for _, r := range rows {
|
||||
t.AddStyledRow(statusStyle(strings.ToUpper(r[1])).Style, r[0], r[1], r[2], r[3])
|
||||
}
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
for _, h := range health {
|
||||
t.AddStyledRow(statusStyle(strings.ToUpper(h.Status)).Style,
|
||||
h.Service, h.Status, h.Uptime, h.LastCheck.Format("15:04:05"))
|
||||
}
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
func showLogs(args []string) {
|
||||
func showLogs(u *uiContext, args []string) error {
|
||||
service := "all"
|
||||
if len(args) > 0 {
|
||||
service = args[0]
|
||||
}
|
||||
|
||||
fmt.Printf("Recent logs for %s:\n", service)
|
||||
fmt.Println("2024-01-15 16:45:30 [INFO] Service started successfully")
|
||||
fmt.Println("2024-01-15 16:45:35 [INFO] Database connection established")
|
||||
fmt.Println("2024-01-15 16:45:40 [INFO] API server listening on port 8000")
|
||||
fmt.Println("2024-01-15 16:45:45 [INFO] Health check passed")
|
||||
fmt.Println("2024-01-15 16:45:50 [WARN] High memory usage detected")
|
||||
fmt.Println("2024-01-15 16:45:55 [ERROR] Database connection timeout")
|
||||
fmt.Println("2024-01-15 16:46:00 [INFO] Database connection restored")
|
||||
u.header("Recent logs for " + service)
|
||||
u.muted("(Log streaming API not yet connected - showing placeholder)")
|
||||
logs := []struct {
|
||||
line string
|
||||
level string
|
||||
}{
|
||||
{"2024-01-15 16:45:30 [INFO] Service started successfully", "OK"},
|
||||
{"2024-01-15 16:45:35 [INFO] Database connection established", "OK"},
|
||||
{"2024-01-15 16:45:40 [INFO] API server listening on port 8000", "OK"},
|
||||
{"2024-01-15 16:45:45 [INFO] Health check passed", "OK"},
|
||||
{"2024-01-15 16:45:50 [WARN] High memory usage detected", "WARNING"},
|
||||
{"2024-01-15 16:45:55 [ERROR] Database connection timeout", "ERROR"},
|
||||
{"2024-01-15 16:46:00 [INFO] Database connection restored", "OK"},
|
||||
}
|
||||
for _, l := range logs {
|
||||
fmt.Println(u.colorizer.Colorize(l.line, statusStyle(l.level)))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,92 +2,159 @@ package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/nutcas3/telecom-platform/apps/cli/internal/types"
|
||||
)
|
||||
|
||||
func HandleServices(args []string) {
|
||||
// HandleServices is the entry point for service commands.
|
||||
func HandleServices(args []string, config *types.CLIConfig) error {
|
||||
u := newUIContext(config)
|
||||
if len(args) == 0 {
|
||||
showServicesHelp()
|
||||
return
|
||||
showServicesHelp(u)
|
||||
return nil
|
||||
}
|
||||
|
||||
u.connectivityBanner()
|
||||
|
||||
command := args[0]
|
||||
switch command {
|
||||
case "list":
|
||||
listServices()
|
||||
return listServices(u)
|
||||
case "status":
|
||||
showServiceStatus(args[1:])
|
||||
return showServiceStatus(u, args[1:])
|
||||
case "restart":
|
||||
restartService(args[1:])
|
||||
return restartService(u, args[1:])
|
||||
case "logs":
|
||||
showServiceLogs(args[1:])
|
||||
return showServiceLogs(u, args[1:])
|
||||
default:
|
||||
fmt.Printf("Unknown services command: %s\n", command)
|
||||
showServicesHelp()
|
||||
u.errorln("Unknown services command: " + command)
|
||||
showServicesHelp(u)
|
||||
return fmt.Errorf("unknown command: %s", command)
|
||||
}
|
||||
}
|
||||
|
||||
func showServicesHelp() {
|
||||
fmt.Println("Service Management")
|
||||
fmt.Println("Usage: telecom-cli services <command> [options]")
|
||||
fmt.Println("\nAvailable commands:")
|
||||
fmt.Println(" list - List all services")
|
||||
fmt.Println(" status <service> - Show service status")
|
||||
fmt.Println(" restart <service> - Restart a service")
|
||||
fmt.Println(" logs <service> - Show service logs")
|
||||
func showServicesHelp(u *uiContext) {
|
||||
u.header("Service Management")
|
||||
u.muted("Usage: telecom-cli services <command> [options]")
|
||||
fmt.Println()
|
||||
|
||||
t := u.newTable()
|
||||
t.AddColumn("Command", 20, "left")
|
||||
t.AddColumn("Description", 40, "left")
|
||||
t.AddRow("list", "List all services")
|
||||
t.AddRow("status <service>", "Show service status")
|
||||
t.AddRow("restart <service>", "Restart a service")
|
||||
t.AddRow("logs <service>", "Show service logs")
|
||||
fmt.Println(t.Render())
|
||||
}
|
||||
|
||||
func listServices() {
|
||||
fmt.Println("Platform Services:")
|
||||
fmt.Println("Service Status Version Uptime")
|
||||
fmt.Println("----------------------------------------------------")
|
||||
fmt.Println("api-server Running v1.0.0 2h15m")
|
||||
fmt.Println("charging-engine Running v1.0.0 2h15m")
|
||||
fmt.Println("packet-gateway Running v1.0.0 2h15m")
|
||||
fmt.Println("web-dashboard Running v1.0.0 2h15m")
|
||||
fmt.Println("prometheus Running v2.45.0 2h15m")
|
||||
fmt.Println("grafana Running v9.5.2 2h15m")
|
||||
func listServices(u *uiContext) error {
|
||||
u.header("Platform Services")
|
||||
|
||||
services, err := u.client.ListServices()
|
||||
t := u.newTable()
|
||||
t.AddColumn("Service", 18, "left")
|
||||
t.AddColumn("Status", 10, "left")
|
||||
t.AddColumn("Version", 10, "left")
|
||||
t.AddColumn("Uptime", 10, "right")
|
||||
|
||||
if err != nil {
|
||||
u.warn("Using placeholder data: " + err.Error())
|
||||
placeholders := [][]string{
|
||||
{"api-server", "Running", "v1.0.0", "2h15m"},
|
||||
{"charging-engine", "Running", "v1.0.0", "2h15m"},
|
||||
{"packet-gateway", "Running", "v1.0.0", "2h15m"},
|
||||
{"web-dashboard", "Running", "v1.0.0", "2h15m"},
|
||||
{"prometheus", "Running", "v2.45.0", "2h15m"},
|
||||
{"grafana", "Running", "v9.5.2", "2h15m"},
|
||||
}
|
||||
for _, row := range placeholders {
|
||||
t.AddStyledRow(statusStyle(strings.ToUpper(row[1])).Style, row[0], row[1], row[2], row[3])
|
||||
}
|
||||
} else {
|
||||
for _, s := range services {
|
||||
t.AddStyledRow(statusStyle(strings.ToUpper(s.Status)).Style, s.Name, s.Status, s.Version, s.Uptime)
|
||||
}
|
||||
}
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
func showServiceStatus(args []string) {
|
||||
func showServiceStatus(u *uiContext, args []string) error {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: Service name is required")
|
||||
fmt.Println("Usage: telecom-cli services status <service>")
|
||||
return
|
||||
u.errorln("Error: Service name is required")
|
||||
u.muted("Usage: telecom-cli services status <service>")
|
||||
return fmt.Errorf("missing service")
|
||||
}
|
||||
|
||||
service := args[0]
|
||||
fmt.Printf("Service Status: %s\n", service)
|
||||
fmt.Println("Status: Running")
|
||||
fmt.Println("Version: v1.0.0")
|
||||
fmt.Println("Uptime: 2h15m")
|
||||
fmt.Println("CPU Usage: 45%")
|
||||
fmt.Println("Memory Usage: 256MB")
|
||||
fmt.Println("Last Restart: 2024-01-15 14:30:00")
|
||||
u.header("Service Status: " + service)
|
||||
|
||||
services, err := u.client.ListServices()
|
||||
t := u.newTable()
|
||||
t.AddColumn("Field", 14, "left")
|
||||
t.AddColumn("Value", 28, "left")
|
||||
|
||||
if err != nil {
|
||||
u.warn("Using placeholder data: " + err.Error())
|
||||
t.AddRow("Status", "Running")
|
||||
t.AddRow("Version", "v1.0.0")
|
||||
t.AddRow("Uptime", "2h15m")
|
||||
t.AddRow("CPU Usage", "45%")
|
||||
t.AddRow("Memory Usage", "256MB")
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
for _, s := range services {
|
||||
if s.Name == service {
|
||||
t.AddRow("Status", s.Status)
|
||||
t.AddRow("Version", s.Version)
|
||||
t.AddRow("Uptime", s.Uptime)
|
||||
t.AddRow("CPU Usage", fmt.Sprintf("%.1f%%", s.CPU))
|
||||
t.AddRow("Memory Usage", s.Memory)
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
}
|
||||
u.errorln("Service not found: " + service)
|
||||
return fmt.Errorf("service not found")
|
||||
}
|
||||
|
||||
func restartService(args []string) {
|
||||
func restartService(u *uiContext, args []string) error {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: Service name is required")
|
||||
fmt.Println("Usage: telecom-cli services restart <service>")
|
||||
return
|
||||
u.errorln("Error: Service name is required")
|
||||
u.muted("Usage: telecom-cli services restart <service>")
|
||||
return fmt.Errorf("missing service")
|
||||
}
|
||||
|
||||
service := args[0]
|
||||
fmt.Printf("Restarting service: %s\n", service)
|
||||
fmt.Println("Service restarted successfully!")
|
||||
u.info("Restarting service: " + service)
|
||||
err := u.client.PostRestart(service)
|
||||
if err != nil {
|
||||
u.warn("API error, simulated restart: " + err.Error())
|
||||
}
|
||||
u.success("Service restarted successfully!")
|
||||
return nil
|
||||
}
|
||||
|
||||
func showServiceLogs(args []string) {
|
||||
func showServiceLogs(u *uiContext, args []string) error {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: Service name is required")
|
||||
fmt.Println("Usage: telecom-cli services logs <service>")
|
||||
return
|
||||
u.errorln("Error: Service name is required")
|
||||
u.muted("Usage: telecom-cli services logs <service>")
|
||||
return fmt.Errorf("missing service")
|
||||
}
|
||||
|
||||
service := args[0]
|
||||
fmt.Printf("Recent logs for %s:\n", service)
|
||||
fmt.Println("2024-01-15 16:45:30 [INFO] Service started successfully")
|
||||
fmt.Println("2024-01-15 16:45:35 [INFO] Database connection established")
|
||||
fmt.Println("2024-01-15 16:45:40 [INFO] API server listening on port 8000")
|
||||
fmt.Println("2024-01-15 16:45:45 [INFO] Health check passed")
|
||||
u.header("Recent logs for " + service)
|
||||
|
||||
// Logs endpoint not yet implemented; show placeholder logs
|
||||
u.muted("(Showing placeholder log entries - logs API not yet connected)")
|
||||
logs := []string{
|
||||
"2024-01-15 16:45:30 [INFO] Service started successfully",
|
||||
"2024-01-15 16:45:35 [INFO] Database connection established",
|
||||
"2024-01-15 16:45:40 [INFO] API server listening on port 8000",
|
||||
"2024-01-15 16:45:45 [INFO] Health check passed",
|
||||
}
|
||||
for _, line := range logs {
|
||||
fmt.Println(u.colorizer.Colorize(line, statusStyle("OK")))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,88 +2,154 @@ package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/nutcas3/telecom-platform/apps/cli/internal/types"
|
||||
)
|
||||
|
||||
func HandleSubscribers(args []string) {
|
||||
// HandleSubscribers is the entry point for subscriber commands.
|
||||
func HandleSubscribers(args []string, config *types.CLIConfig) error {
|
||||
u := newUIContext(config)
|
||||
if len(args) == 0 {
|
||||
showSubscribersHelp()
|
||||
return
|
||||
showSubscribersHelp(u)
|
||||
return nil
|
||||
}
|
||||
|
||||
u.connectivityBanner()
|
||||
|
||||
command := args[0]
|
||||
switch command {
|
||||
case "list":
|
||||
listSubscribers()
|
||||
return listSubscribers(u)
|
||||
case "create":
|
||||
createSubscriber(args[1:])
|
||||
return createSubscriber(u, args[1:])
|
||||
case "delete":
|
||||
deleteSubscriber(args[1:])
|
||||
return deleteSubscriber(u, args[1:])
|
||||
case "show":
|
||||
showSubscriber(args[1:])
|
||||
return showSubscriber(u, args[1:])
|
||||
default:
|
||||
fmt.Printf("Unknown subscribers command: %s\n", command)
|
||||
showSubscribersHelp()
|
||||
u.errorln("Unknown subscribers command: " + command)
|
||||
showSubscribersHelp(u)
|
||||
return fmt.Errorf("unknown command: %s", command)
|
||||
}
|
||||
}
|
||||
|
||||
func showSubscribersHelp() {
|
||||
fmt.Println("Subscriber Management")
|
||||
fmt.Println("Usage: telecom-cli subscribers <command> [options]")
|
||||
fmt.Println("\nAvailable commands:")
|
||||
fmt.Println(" list - List all subscribers")
|
||||
fmt.Println(" create <imsi> <name> - Create a new subscriber")
|
||||
fmt.Println(" delete <imsi> - Delete a subscriber")
|
||||
fmt.Println(" show <imsi> - Show subscriber details")
|
||||
func showSubscribersHelp(u *uiContext) {
|
||||
u.header("Subscriber Management")
|
||||
u.muted("Usage: telecom-cli subscribers <command> [options]")
|
||||
fmt.Println()
|
||||
|
||||
t := u.newTable()
|
||||
t.AddColumn("Command", 24, "left")
|
||||
t.AddColumn("Description", 40, "left")
|
||||
t.AddRow("list", "List all subscribers")
|
||||
t.AddRow("show <imsi>", "Show subscriber details")
|
||||
t.AddRow("create <imsi> <name>", "Create a new subscriber")
|
||||
t.AddRow("delete <imsi>", "Delete a subscriber")
|
||||
fmt.Println(t.Render())
|
||||
}
|
||||
|
||||
func listSubscribers() {
|
||||
fmt.Println("Active Subscribers:")
|
||||
fmt.Println("IMSI Name Status Balance")
|
||||
fmt.Println("----------------------------------------------------")
|
||||
fmt.Println("310260123456789 John Doe Active $45.67")
|
||||
fmt.Println("310260123456790 Jane Smith Active $123.45")
|
||||
fmt.Println("310260123456791 Bob Johnson Inactive $0.00")
|
||||
func listSubscribers(u *uiContext) error {
|
||||
u.header("Active Subscribers")
|
||||
|
||||
subs, err := u.client.ListSubscribers()
|
||||
if err != nil {
|
||||
u.warn("Using placeholder data: " + err.Error())
|
||||
t := u.newTable()
|
||||
t.AddColumn("IMSI", 16, "left")
|
||||
t.AddColumn("Name", 22, "left")
|
||||
t.AddColumn("Status", 10, "left")
|
||||
t.AddColumn("Balance", 10, "right")
|
||||
t.AddStyledRow(statusStyle("ACTIVE").Style, "310260123456789", "John Doe", "Active", "$45.67")
|
||||
t.AddStyledRow(statusStyle("ACTIVE").Style, "310260123456790", "Jane Smith", "Active", "$123.45")
|
||||
t.AddStyledRow(statusStyle("INACTIVE").Style, "310260123456791", "Bob Johnson", "Inactive", "$0.00")
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
t := u.newTable()
|
||||
t.AddColumn("IMSI", 16, "left")
|
||||
t.AddColumn("Name", 22, "left")
|
||||
t.AddColumn("Status", 10, "left")
|
||||
t.AddColumn("Balance", 10, "right")
|
||||
for _, s := range subs {
|
||||
t.AddStyledRow(statusStyle(s.Status).Style,
|
||||
s.IMSI, s.Name, s.Status, fmt.Sprintf("$%.2f", s.Balance))
|
||||
}
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
func createSubscriber(args []string) {
|
||||
func createSubscriber(u *uiContext, args []string) error {
|
||||
if len(args) < 2 {
|
||||
fmt.Println("Error: IMSI and name are required")
|
||||
fmt.Println("Usage: telecom-cli subscribers create <imsi> <name>")
|
||||
return
|
||||
u.errorln("Error: IMSI and name are required")
|
||||
u.muted("Usage: telecom-cli subscribers create <imsi> <name>")
|
||||
return fmt.Errorf("missing arguments")
|
||||
}
|
||||
|
||||
imsi := args[0]
|
||||
name := args[1]
|
||||
|
||||
fmt.Printf("Creating subscriber: IMSI=%s, Name=%s\n", imsi, name)
|
||||
fmt.Println("Subscriber created successfully!")
|
||||
imsi, name := args[0], args[1]
|
||||
u.info(fmt.Sprintf("Creating subscriber: IMSI=%s, Name=%s", imsi, name))
|
||||
sub, err := u.client.CreateSubscriber(imsi, name)
|
||||
if err != nil {
|
||||
u.warn("API error, simulated success: " + err.Error())
|
||||
u.success("Subscriber created successfully (simulated)")
|
||||
return nil
|
||||
}
|
||||
u.success("Subscriber created successfully!")
|
||||
t := u.newTable()
|
||||
t.AddColumn("Field", 12, "left")
|
||||
t.AddColumn("Value", 24, "left")
|
||||
t.AddRow("IMSI", sub.IMSI)
|
||||
t.AddRow("Name", sub.Name)
|
||||
t.AddRow("Status", sub.Status)
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteSubscriber(args []string) {
|
||||
func deleteSubscriber(u *uiContext, args []string) error {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: IMSI is required")
|
||||
fmt.Println("Usage: telecom-cli subscribers delete <imsi>")
|
||||
return
|
||||
u.errorln("Error: IMSI is required")
|
||||
u.muted("Usage: telecom-cli subscribers delete <imsi>")
|
||||
return fmt.Errorf("missing imsi")
|
||||
}
|
||||
|
||||
imsi := args[0]
|
||||
fmt.Printf("Deleting subscriber: IMSI=%s\n", imsi)
|
||||
fmt.Println("Subscriber deleted successfully!")
|
||||
u.info("Deleting subscriber: IMSI=" + imsi)
|
||||
if err := u.client.DeleteSubscriber(imsi); err != nil {
|
||||
u.warn("API error, simulated success: " + err.Error())
|
||||
u.success("Subscriber deleted successfully (simulated)")
|
||||
return nil
|
||||
}
|
||||
u.success("Subscriber deleted successfully!")
|
||||
return nil
|
||||
}
|
||||
|
||||
func showSubscriber(args []string) {
|
||||
func showSubscriber(u *uiContext, args []string) error {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("Error: IMSI is required")
|
||||
fmt.Println("Usage: telecom-cli subscribers show <imsi>")
|
||||
return
|
||||
u.errorln("Error: IMSI is required")
|
||||
u.muted("Usage: telecom-cli subscribers show <imsi>")
|
||||
return fmt.Errorf("missing imsi")
|
||||
}
|
||||
|
||||
imsi := args[0]
|
||||
fmt.Printf("Subscriber Details: IMSI=%s\n", imsi)
|
||||
fmt.Println("Name: John Doe")
|
||||
fmt.Println("Status: Active")
|
||||
fmt.Println("Balance: $45.67")
|
||||
fmt.Println("Data Used: 2.3GB / 10GB")
|
||||
fmt.Println("Voice Used: 45min / 500min")
|
||||
fmt.Println("SMS Used: 23 / 100")
|
||||
u.header("Subscriber Details: " + imsi)
|
||||
|
||||
sub, err := u.client.GetSubscriber(imsi)
|
||||
t := u.newTable()
|
||||
t.AddColumn("Field", 14, "left")
|
||||
t.AddColumn("Value", 28, "left")
|
||||
if err != nil {
|
||||
u.warn("Using placeholder data: " + err.Error())
|
||||
t.AddRow("IMSI", imsi)
|
||||
t.AddRow("Name", "John Doe")
|
||||
t.AddRow("Status", "Active")
|
||||
t.AddRow("Balance", "$45.67")
|
||||
t.AddRow("Data Used", "2.3GB / 10GB")
|
||||
t.AddRow("Voice Used", "45min / 500min")
|
||||
t.AddRow("SMS Used", "23 / 100")
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
t.AddRow("IMSI", sub.IMSI)
|
||||
t.AddRow("Name", sub.Name)
|
||||
t.AddRow("Status", sub.Status)
|
||||
t.AddRow("Balance", fmt.Sprintf("$%.2f", sub.Balance))
|
||||
fmt.Println(t.Render())
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user