debian-forge-composer/internal/production/production_cli.go
robojerk 4eeaa43c39
Some checks failed
Tests / 🛃 Unit tests (push) Failing after 13s
Tests / 🗄 DB tests (push) Failing after 19s
Tests / 🐍 Lint python scripts (push) Failing after 1s
Tests / ⌨ Golang Lint (push) Failing after 1s
Tests / 📦 Packit config lint (push) Failing after 1s
Tests / 🔍 Check source preparation (push) Failing after 1s
Tests / 🔍 Check for valid snapshot urls (push) Failing after 1s
Tests / 🔍 Check for missing or unused runner repos (push) Failing after 1s
Tests / 🐚 Shellcheck (push) Failing after 1s
Tests / 📦 RPMlint (push) Failing after 1s
Tests / Gitlab CI trigger helper (push) Failing after 1s
Tests / 🎀 kube-linter (push) Failing after 1s
Tests / 🧹 cloud-cleaner-is-enabled (push) Successful in 3s
Tests / 🔍 Check spec file osbuild/images dependencies (push) Failing after 1s
did stuff
2025-08-26 10:34:42 -07:00

607 lines
18 KiB
Go

package production
import (
"fmt"
"strconv"
"time"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
// ProductionCLI provides command-line interface for production management
type ProductionCLI struct {
manager *ProductionManager
configPath string
logger *logrus.Logger
}
// NewProductionCLI creates a new production CLI
func NewProductionCLI(configPath string, logger *logrus.Logger) *ProductionCLI {
return &ProductionCLI{
configPath: configPath,
logger: logger,
}
}
// CreateRootCommand creates the root production command
func (cli *ProductionCLI) CreateRootCommand() *cobra.Command {
rootCmd := &cobra.Command{
Use: "production",
Short: "Debian Forge Production Management",
Long: "Manage production readiness, deployment automation, and production support",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return cli.initializeManager()
},
}
// Add subcommands
rootCmd.AddCommand(cli.createPerformanceCommand())
rootCmd.AddCommand(cli.createDeploymentCommand())
rootCmd.AddCommand(cli.createSupportCommand())
rootCmd.AddCommand(cli.createConfigCommand())
rootCmd.AddCommand(cli.createStatusCommand())
return rootCmd
}
// initializeManager initializes the production manager
func (cli *ProductionCLI) initializeManager() error {
// Load configuration
config, err := LoadProductionConfig(cli.configPath)
if err != nil {
return fmt.Errorf("failed to load configuration: %w", err)
}
// Validate configuration
configManager := &ProductionConfigManager{configPath: cli.configPath, config: config}
if err := configManager.ValidateConfig(); err != nil {
return fmt.Errorf("configuration validation failed: %w", err)
}
// Create production manager
cli.manager = NewProductionManager(config, cli.logger)
return nil
}
// createPerformanceCommand creates the performance command
func (cli *ProductionCLI) createPerformanceCommand() *cobra.Command {
performanceCmd := &cobra.Command{
Use: "performance",
Short: "Manage performance optimization",
Long: "Run load tests, scalability tests, and benchmarks",
}
// Load testing subcommand
loadTestCmd := &cobra.Command{
Use: "load-test [test]",
Short: "Run a load test",
Long: "Run a load testing scenario",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return cli.runLoadTest(args[0])
},
}
// Scalability testing subcommand
scalabilityCmd := &cobra.Command{
Use: "scalability [test]",
Short: "Run a scalability test",
Long: "Run a scalability testing scenario",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return cli.runScalabilityTest(args[0])
},
}
// Benchmark subcommand
benchmarkCmd := &cobra.Command{
Use: "benchmark [benchmark]",
Short: "Run a benchmark",
Long: "Run a performance benchmark",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return cli.runBenchmark(args[0])
},
}
// List tests subcommand
listTestsCmd := &cobra.Command{
Use: "list",
Short: "List available tests",
Long: "List all available performance tests and benchmarks",
RunE: func(cmd *cobra.Command, args []string) error {
return cli.listPerformanceTests()
},
}
performanceCmd.AddCommand(loadTestCmd, scalabilityCmd, benchmarkCmd, listTestsCmd)
return performanceCmd
}
// createDeploymentCommand creates the deployment command
func (cli *ProductionCLI) createDeploymentCommand() *cobra.Command {
deploymentCmd := &cobra.Command{
Use: "deployment",
Short: "Manage deployment automation",
Long: "Execute deployments, manage configurations, and provision environments",
}
// Execute deployment subcommand
executeCmd := &cobra.Command{
Use: "execute [script]",
Short: "Execute a deployment",
Long: "Execute a deployment script",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return cli.executeDeployment(args[0])
},
}
// Provision environment subcommand
provisionCmd := &cobra.Command{
Use: "provision [environment]",
Short: "Provision an environment",
Long: "Provision a deployment environment",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return cli.provisionEnvironment(args[0])
},
}
// List deployments subcommand
listDeploymentsCmd := &cobra.Command{
Use: "list",
Short: "List available deployments",
Long: "List all available deployment scripts and environments",
RunE: func(cmd *cobra.Command, args []string) error {
return cli.listDeployments()
},
}
deploymentCmd.AddCommand(executeCmd, provisionCmd, listDeploymentsCmd)
return deploymentCmd
}
// createSupportCommand creates the support command
func (cli *ProductionCLI) createSupportCommand() *cobra.Command {
supportCmd := &cobra.Command{
Use: "support",
Short: "Manage production support",
Long: "Access documentation, execute maintenance, and get troubleshooting help",
}
// Documentation subcommand
docsCmd := &cobra.Command{
Use: "docs [document]",
Short: "Show documentation",
Long: "Show production documentation",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return cli.showDocumentation(args[0])
},
}
// Maintenance subcommand
maintenanceCmd := &cobra.Command{
Use: "maintenance [procedure]",
Short: "Execute maintenance",
Long: "Execute a maintenance procedure",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return cli.executeMaintenance(args[0])
},
}
// Troubleshooting subcommand
troubleshootingCmd := &cobra.Command{
Use: "troubleshooting [category]",
Short: "Get troubleshooting help",
Long: "Get troubleshooting guidance for a category",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return cli.getTroubleshootingHelp(args[0])
},
}
// Training subcommand
trainingCmd := &cobra.Command{
Use: "training [material]",
Short: "Show training material",
Long: "Show training material for production support",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return cli.showTrainingMaterial(args[0])
},
}
// List support resources subcommand
listSupportCmd := &cobra.Command{
Use: "list",
Short: "List support resources",
Long: "List all available support resources",
RunE: func(cmd *cobra.Command, args []string) error {
return cli.listSupportResources()
},
}
supportCmd.AddCommand(docsCmd, maintenanceCmd, troubleshootingCmd, trainingCmd, listSupportCmd)
return supportCmd
}
// createConfigCommand creates the configuration command
func (cli *ProductionCLI) createConfigCommand() *cobra.Command {
configCmd := &cobra.Command{
Use: "config",
Short: "Manage production configuration",
Long: "View and modify production configuration",
}
// Show configuration subcommand
showCmd := &cobra.Command{
Use: "show",
Short: "Show current configuration",
Long: "Show current production configuration",
RunE: func(cmd *cobra.Command, args []string) error {
return cli.showConfig()
},
}
// Update configuration subcommand
updateCmd := &cobra.Command{
Use: "update [key] [value]",
Short: "Update configuration",
Long: "Update a configuration value",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
return cli.updateConfig(args[0], args[1])
},
}
// Validate configuration subcommand
validateCmd := &cobra.Command{
Use: "validate",
Short: "Validate configuration",
Long: "Validate current configuration",
RunE: func(cmd *cobra.Command, args []string) error {
return cli.validateConfig()
},
}
configCmd.AddCommand(showCmd, updateCmd, validateCmd)
return configCmd
}
// createStatusCommand creates the status command
func (cli *ProductionCLI) createStatusCommand() *cobra.Command {
statusCmd := &cobra.Command{
Use: "status",
Short: "Show production status",
Long: "Show current status of production systems",
RunE: func(cmd *cobra.Command, args []string) error {
return cli.showStatus()
},
}
return statusCmd
}
// Performance methods
func (cli *ProductionCLI) runLoadTest(testID string) error {
if err := cli.manager.performance.RunLoadTest(testID); err != nil {
return fmt.Errorf("load test failed: %w", err)
}
fmt.Printf("Load test completed successfully: %s\n", testID)
return nil
}
func (cli *ProductionCLI) runScalabilityTest(testID string) error {
if err := cli.manager.performance.RunScalabilityTest(testID); err != nil {
return fmt.Errorf("scalability test failed: %w", err)
}
fmt.Printf("Scalability test completed successfully: %s\n", testID)
return nil
}
func (cli *ProductionCLI) runBenchmark(benchmarkID string) error {
if err := cli.manager.performance.RunBenchmark(benchmarkID); err != nil {
return fmt.Errorf("benchmark failed: %w", err)
}
fmt.Printf("Benchmark completed successfully: %s\n", benchmarkID)
return nil
}
func (cli *ProductionCLI) listPerformanceTests() error {
fmt.Printf("Performance Tests:\n")
fmt.Printf("==================\n")
fmt.Printf("\nLoad Tests:\n")
for id, test := range cli.manager.performance.loadTests {
fmt.Printf(" %s:\n", id)
fmt.Printf(" Name: %s\n", test.Name)
fmt.Printf(" Description: %s\n", test.Description)
fmt.Printf(" Users: %d\n", test.Users)
fmt.Printf(" Duration: %v\n", test.Duration)
fmt.Printf(" Ramp Up: %v\n", test.RampUp)
fmt.Printf(" Enabled: %t\n", test.Enabled)
fmt.Printf("\n")
}
fmt.Printf("Scalability Tests:\n")
for id, test := range cli.manager.performance.scalability {
fmt.Printf(" %s:\n", id)
fmt.Printf(" Name: %s\n", test.Name)
fmt.Printf(" Description: %s\n", test.Description)
fmt.Printf(" Start Nodes: %d\n", test.StartNodes)
fmt.Printf(" End Nodes: %d\n", test.EndNodes)
fmt.Printf(" Step Size: %d\n", test.StepSize)
fmt.Printf(" Enabled: %t\n", test.Enabled)
fmt.Printf("\n")
}
fmt.Printf("Benchmarks:\n")
for id, benchmark := range cli.manager.performance.benchmarks {
fmt.Printf(" %s:\n", id)
fmt.Printf(" Name: %s\n", benchmark.Name)
fmt.Printf(" Description: %s\n", benchmark.Description)
fmt.Printf(" Metric: %s\n", benchmark.Metric)
fmt.Printf(" Target: %.2f\n", benchmark.Target)
fmt.Printf(" Enabled: %t\n", benchmark.Enabled)
fmt.Printf("\n")
}
return nil
}
// Deployment methods
func (cli *ProductionCLI) executeDeployment(scriptID string) error {
if err := cli.manager.deployment.ExecuteDeployment(scriptID); err != nil {
return fmt.Errorf("deployment failed: %w", err)
}
fmt.Printf("Deployment completed successfully: %s\n", scriptID)
return nil
}
func (cli *ProductionCLI) provisionEnvironment(envID string) error {
if err := cli.manager.deployment.ProvisionEnvironment(envID); err != nil {
return fmt.Errorf("environment provisioning failed: %w", err)
}
fmt.Printf("Environment provisioned successfully: %s\n", envID)
return nil
}
func (cli *ProductionCLI) listDeployments() error {
fmt.Printf("Deployment Scripts:\n")
fmt.Printf("===================\n")
for id, script := range cli.manager.deployment.scripts {
fmt.Printf(" %s:\n", id)
fmt.Printf(" Name: %s\n", script.Name)
fmt.Printf(" Description: %s\n", script.Description)
fmt.Printf(" Type: %s\n", script.Type)
fmt.Printf(" Script Path: %s\n", script.ScriptPath)
fmt.Printf(" Timeout: %v\n", script.Timeout)
fmt.Printf(" Enabled: %t\n", script.Enabled)
fmt.Printf("\n")
}
fmt.Printf("Environment Provisioning:\n")
for id, env := range cli.manager.deployment.provisioning {
fmt.Printf(" %s:\n", id)
fmt.Printf(" Name: %s\n", env.Name)
fmt.Printf(" Description: %s\n", env.Description)
fmt.Printf(" Type: %s\n", env.Type)
fmt.Printf(" Provider: %s\n", env.Provider)
fmt.Printf(" Resources: %v\n", env.Resources)
fmt.Printf(" Enabled: %t\n", env.Enabled)
fmt.Printf("\n")
}
return nil
}
// Support methods
func (cli *ProductionCLI) showDocumentation(docID string) error {
doc, err := cli.manager.support.GetDocumentation(docID)
if err != nil {
return fmt.Errorf("failed to get documentation: %w", err)
}
fmt.Printf("Documentation: %s\n", doc.Name)
fmt.Printf("===============\n")
fmt.Printf(" ID: %s\n", doc.ID)
fmt.Printf(" Description: %s\n", doc.Description)
fmt.Printf(" Type: %s\n", doc.Type)
fmt.Printf(" Path: %s\n", doc.Path)
fmt.Printf(" Format: %s\n", doc.Format)
fmt.Printf(" Version: %s\n", doc.Version)
fmt.Printf(" Updated: %v\n", doc.Updated)
fmt.Printf(" Enabled: %t\n", doc.Enabled)
return nil
}
func (cli *ProductionCLI) executeMaintenance(procedureID string) error {
if err := cli.manager.support.ExecuteMaintenance(procedureID); err != nil {
return fmt.Errorf("maintenance failed: %w", err)
}
fmt.Printf("Maintenance completed successfully: %s\n", procedureID)
return nil
}
func (cli *ProductionCLI) getTroubleshootingHelp(category string) error {
guide, err := cli.manager.support.GetTroubleshootingGuide(category)
if err != nil {
return fmt.Errorf("failed to get troubleshooting guide: %w", err)
}
fmt.Printf("Troubleshooting Guide: %s\n", guide.Name)
fmt.Printf("========================\n")
fmt.Printf(" Description: %s\n", guide.Description)
fmt.Printf(" Category: %s\n", guide.Category)
fmt.Printf("\n Problems:\n")
for _, problem := range guide.Problems {
fmt.Printf(" %s:\n", problem.Name)
fmt.Printf(" Description: %s\n", problem.Description)
fmt.Printf(" Priority: %s\n", problem.Priority)
fmt.Printf(" Symptoms:\n")
for _, symptom := range problem.Symptoms {
fmt.Printf(" - %s\n", symptom)
}
fmt.Printf(" Solutions:\n")
for _, solution := range problem.Solutions {
fmt.Printf(" - %s\n", solution)
}
fmt.Printf("\n")
}
return nil
}
func (cli *ProductionCLI) showTrainingMaterial(trainingID string) error {
training, err := cli.manager.support.GetTrainingMaterial(trainingID)
if err != nil {
return fmt.Errorf("failed to get training material: %w", err)
}
fmt.Printf("Training Material: %s\n", training.Name)
fmt.Printf("===================\n")
fmt.Printf(" Description: %s\n", training.Description)
fmt.Printf(" Type: %s\n", training.Type)
fmt.Printf(" Path: %s\n", training.Path)
fmt.Printf(" Duration: %v\n", training.Duration)
fmt.Printf(" Prerequisites:\n")
for _, prereq := range training.Prerequisites {
fmt.Printf(" - %s\n", prereq)
}
fmt.Printf(" Enabled: %t\n", training.Enabled)
return nil
}
func (cli *ProductionCLI) listSupportResources() error {
fmt.Printf("Support Resources:\n")
fmt.Printf("==================\n")
fmt.Printf("\nDocumentation:\n")
for id, doc := range cli.manager.support.documentation {
fmt.Printf(" %s: %s\n", id, doc.Name)
}
fmt.Printf("\nMaintenance Procedures:\n")
for id, procedure := range cli.manager.support.maintenance {
fmt.Printf(" %s: %s (%s)\n", id, procedure.Name, procedure.Schedule)
}
fmt.Printf("\nTroubleshooting Guides:\n")
for id, guide := range cli.manager.support.troubleshooting {
fmt.Printf(" %s: %s (%s)\n", id, guide.Name, guide.Category)
}
fmt.Printf("\nTraining Materials:\n")
for id, training := range cli.manager.support.training {
fmt.Printf(" %s: %s (%v)\n", id, training.Name, training.Duration)
}
return nil
}
// Configuration methods
func (cli *ProductionCLI) showConfig() error {
if cli.manager.config == nil {
return fmt.Errorf("no configuration loaded")
}
fmt.Printf("Production Configuration:\n")
fmt.Printf("=========================\n")
fmt.Printf(" Enabled: %t\n", cli.manager.config.Enabled)
fmt.Printf(" Environment: %s\n", cli.manager.config.Environment)
fmt.Printf(" Deployment Path: %s\n", cli.manager.config.DeploymentPath)
fmt.Printf(" Performance: %t\n", cli.manager.config.Performance)
fmt.Printf(" Automation: %t\n", cli.manager.config.Automation)
fmt.Printf(" Support: %t\n", cli.manager.config.Support)
if len(cli.manager.config.Metadata) > 0 {
fmt.Printf(" Metadata:\n")
for key, value := range cli.manager.config.Metadata {
fmt.Printf(" %s: %s\n", key, value)
}
}
return nil
}
func (cli *ProductionCLI) updateConfig(key string, value string) error {
configManager := &ProductionConfigManager{configPath: cli.configPath, config: cli.manager.config}
updates := make(map[string]interface{})
// Parse value based on key type
switch key {
case "enabled", "performance", "automation", "support":
if boolVal, err := strconv.ParseBool(value); err == nil {
updates[key] = boolVal
} else {
return fmt.Errorf("invalid boolean value for %s: %s", key, value)
}
case "environment", "deployment_path":
updates[key] = value
default:
return fmt.Errorf("unknown configuration key: %s", key)
}
if err := configManager.UpdateConfig(updates); err != nil {
return fmt.Errorf("failed to update configuration: %w", err)
}
fmt.Printf("Configuration updated: %s = %s\n", key, value)
return nil
}
func (cli *ProductionCLI) validateConfig() error {
configManager := &ProductionConfigManager{configPath: cli.configPath, config: cli.manager.config}
if err := configManager.ValidateConfig(); err != nil {
return fmt.Errorf("configuration validation failed: %w", err)
}
fmt.Printf("Configuration validation passed\n")
return nil
}
// Status methods
func (cli *ProductionCLI) showStatus() error {
fmt.Printf("Production System Status:\n")
fmt.Printf("=========================\n")
// Performance system status
fmt.Printf("Performance System:\n")
fmt.Printf(" Status: Active\n")
fmt.Printf(" Load Tests: %d\n", len(cli.manager.performance.loadTests))
fmt.Printf(" Scalability Tests: %d\n", len(cli.manager.performance.scalability))
fmt.Printf(" Benchmarks: %d\n", len(cli.manager.performance.benchmarks))
// Deployment system status
fmt.Printf("\nDeployment System:\n")
fmt.Printf(" Status: Active\n")
fmt.Printf(" Scripts: %d\n", len(cli.manager.deployment.scripts))
fmt.Printf(" Configurations: %d\n", len(cli.manager.deployment.configs))
fmt.Printf(" Environments: %d\n", len(cli.manager.deployment.provisioning))
// Support system status
fmt.Printf("\nSupport System:\n")
fmt.Printf(" Status: Active\n")
fmt.Printf(" Documentation: %d\n", len(cli.manager.support.documentation))
fmt.Printf(" Maintenance Procedures: %d\n", len(cli.manager.support.maintenance))
fmt.Printf(" Troubleshooting Guides: %d\n", len(cli.manager.support.troubleshooting))
fmt.Printf(" Training Materials: %d\n", len(cli.manager.support.training))
return nil
}