Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 3 additions & 26 deletions cmd/virtwork/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,7 @@ realistic CPU, memory, database, network, and disk I/O metrics.`,
SilenceUsage: true,
}

pf := rootCmd.PersistentFlags()
pf.String("namespace", "", "Kubernetes namespace for VMs")
pf.String("kubeconfig", "", "Path to kubeconfig file")
pf.String("config", "", "Path to YAML config file")
pf.Bool("verbose", false, "Enable verbose output")
pf.Bool("audit", true, "Enable audit logging to SQLite")
pf.Bool("no-audit", false, "Disable audit logging")
pf.String("audit-db", "", "Path to audit database file")
config.BindPersistentFlags(rootCmd)

rootCmd.AddCommand(newRunCmd(), newCleanupCmd())
return rootCmd
Expand All @@ -74,20 +67,7 @@ via systemd.`,
RunE: runE,
}

f := cmd.Flags()
f.StringSlice("workloads", workloads.AllWorkloadNames(), "Workloads to deploy (comma-separated)")
f.Int("vm-count", 1, "Number of VMs per workload")
f.Int("cpu-cores", 0, "CPU cores per VM")
f.String("memory", "", "Memory per VM (e.g., 2Gi)")
f.String("disk-size", "", "Data disk size")
f.String("container-disk-image", "", "Container disk image for VMs")
f.Bool("dry-run", false, "Print specs without creating resources")
f.Bool("no-wait", false, "Skip waiting for VM readiness")
f.Int("timeout", 0, "Readiness timeout in seconds")
f.String("ssh-user", "", "SSH user for VMs")
f.String("ssh-password", "", "SSH password for VMs")
f.StringSlice("ssh-key", nil, "SSH authorized key (repeatable)")
f.StringSlice("ssh-key-file", nil, "SSH key file path (repeatable)")
config.BindRunFlags(cmd, workloads.AllWorkloadNames())

return cmd
}
Expand All @@ -100,10 +80,7 @@ func newCleanupCmd() *cobra.Command {
RunE: cleanupE,
}

cmd.Flags().Bool("delete-namespace", false, "Also delete the namespace")
cmd.Flags().String("run-id", "", "Only delete resources from this specific run (UUID)")
cmd.Flags().Bool("dry-run", false, "Print intent without destroying resources")
cmd.Flags().BoolP("yes", "y", false, "Skip confirmation prompt and proceed with cleanup")
config.BindCleanupFlags(cmd)
return cmd
}

Expand Down
27 changes: 3 additions & 24 deletions cmd/virtwork/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,7 @@ func newRootCmd() *cobra.Command {
Use: "virtwork",
Short: "Create VMs on OpenShift with continuous workloads",
}

pf := rootCmd.PersistentFlags()
pf.String("namespace", "", "Kubernetes namespace for VMs")
pf.String("kubeconfig", "", "Path to kubeconfig file")
pf.String("config", "", "Path to YAML config file")
pf.Bool("verbose", false, "Enable verbose output")
config.BindPersistentFlags(rootCmd)

runCmd := &cobra.Command{
Use: "run",
Expand All @@ -51,20 +46,7 @@ func newRootCmd() *cobra.Command {
return nil
},
}
rf := runCmd.Flags()
rf.StringSlice("workloads", workloads.AllWorkloadNames(), "Workloads to deploy (comma-separated)")
rf.Int("vm-count", 1, "Number of VMs per workload")
rf.Int("cpu-cores", 0, "CPU cores per VM")
rf.String("memory", "", "Memory per VM (e.g., 2Gi)")
rf.String("disk-size", "", "Data disk size")
rf.String("container-disk-image", "", "Container disk image for VMs")
rf.Bool("dry-run", false, "Print specs without creating resources")
rf.Bool("no-wait", false, "Skip waiting for VM readiness")
rf.Int("timeout", 0, "Readiness timeout in seconds")
rf.String("ssh-user", "", "SSH user for VMs")
rf.String("ssh-password", "", "SSH password for VMs")
rf.StringSlice("ssh-key", nil, "SSH authorized key (repeatable)")
rf.StringSlice("ssh-key-file", nil, "SSH key file path (repeatable)")
config.BindRunFlags(runCmd, workloads.AllWorkloadNames())

cleanupCmd := &cobra.Command{
Use: "cleanup",
Expand All @@ -73,10 +55,7 @@ func newRootCmd() *cobra.Command {
return nil
},
}
cleanupCmd.Flags().Bool("delete-namespace", false, "Also delete the namespace")
cleanupCmd.Flags().String("run-id", "", "Only delete resources from this specific run (UUID)")
cleanupCmd.Flags().Bool("dry-run", false, "Print intent without destroying resources")
cleanupCmd.Flags().BoolP("yes", "y", false, "Skip confirmation prompt and proceed with cleanup")
config.BindCleanupFlags(cleanupCmd)

rootCmd.AddCommand(runCmd, cleanupCmd)
return rootCmd
Expand Down
36 changes: 28 additions & 8 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,26 +71,46 @@ func SetDefaults(v *viper.Viper) {
v.SetDefault("audit-db", constants.DefaultAuditDBPath)
}

// BindFlags registers Cobra flags on the given command.
func BindFlags(cmd *cobra.Command) {
// BindPersistentFlags registers persistent flags shared across all subcommands.
func BindPersistentFlags(cmd *cobra.Command) {
pf := cmd.PersistentFlags()
pf.String("namespace", "", "Kubernetes namespace for VMs")
pf.String("kubeconfig", "", "Path to kubeconfig file")
pf.String("config", "", "Path to YAML config file")
pf.Bool("verbose", false, "Enable verbose output")
pf.Bool("audit", true, "Enable audit logging to SQLite")
pf.Bool("no-audit", false, "Disable audit logging")
pf.String("audit-db", "", "Path to audit database file")
}

// BindRunFlags registers flags specific to the "run" subcommand.
// defaultWorkloads sets the default value for the --workloads flag.
func BindRunFlags(cmd *cobra.Command, defaultWorkloads []string) {
f := cmd.Flags()
f.String("namespace", "", "Kubernetes namespace for VMs")
f.String("kubeconfig", "", "Path to kubeconfig file")
f.String("config", "", "Path to YAML config file")
f.String("container-disk-image", "", "Container disk image for VMs")
f.String("disk-size", "", "Data disk size")
f.StringSlice("workloads", defaultWorkloads, "Workloads to deploy (comma-separated)")
f.Int("vm-count", 1, "Number of VMs per workload")
f.Int("cpu-cores", 0, "CPU cores per VM")
f.String("memory", "", "Memory per VM (e.g., 2Gi)")
f.String("disk-size", "", "Data disk size")
f.String("container-disk-image", "", "Container disk image for VMs")
f.Bool("dry-run", false, "Print specs without creating resources")
f.Bool("no-wait", false, "Skip waiting for VM readiness")
f.Int("timeout", 0, "Readiness timeout in seconds")
f.Bool("verbose", false, "Enable verbose output")
f.String("ssh-user", "", "SSH user for VMs")
f.String("ssh-password", "", "SSH password for VMs")
f.StringSlice("ssh-key", nil, "SSH authorized key (repeatable)")
f.StringSlice("ssh-key-file", nil, "SSH key file path (repeatable)")
}

// BindCleanupFlags registers flags specific to the "cleanup" subcommand.
func BindCleanupFlags(cmd *cobra.Command) {
f := cmd.Flags()
f.Bool("delete-namespace", false, "Also delete the namespace")
f.String("run-id", "", "Only delete resources from this specific run (UUID)")
f.Bool("dry-run", false, "Print intent without destroying resources")
f.BoolP("yes", "y", false, "Skip confirmation prompt and proceed with cleanup")
}

// LoadConfig loads configuration from flags, environment variables, config file,
// and defaults using the Viper priority chain: flags > env > file > defaults.
func LoadConfig(cmd *cobra.Command) (*Config, error) {
Expand Down
14 changes: 13 additions & 1 deletion internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,31 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/spf13/cobra"
"github.com/spf13/pflag"

"github.com/opdev/virtwork/internal/config"
"github.com/opdev/virtwork/internal/constants"
)

func newTestCommand() *cobra.Command {
root := &cobra.Command{Use: "root"}
config.BindPersistentFlags(root)

cmd := &cobra.Command{
Use: "test",
RunE: func(cmd *cobra.Command, args []string) error {
return nil
},
}
config.BindFlags(cmd)
config.BindRunFlags(cmd, nil)
root.AddCommand(cmd)

// Merge root's persistent flags into cmd (Cobra does this during Execute;
// tests call LoadConfig directly so we replicate the merge here).
root.PersistentFlags().VisitAll(func(f *pflag.Flag) {
cmd.Flags().AddFlag(f)
})

return cmd
}

Expand Down
Loading