refactor: introduce app struct

This commit is contained in:
Patryk Hegenberg 2025-01-03 11:21:28 +01:00
parent c052e6daf0
commit aa3000cce6

246
main.go
View file

@ -37,48 +37,51 @@ type Flags struct {
ShowExport bool
}
var (
type App struct {
cfg Config
flags Flags
)
}
func init() {
showCmd.Flags().BoolVarP(&flags.ShowWeek, "week", "w", false, "show timewarrior week summary")
showCmd.Flags().BoolVarP(&flags.ShowMonth, "month", "m", false, "show timewarrior month summary")
showCmd.Flags().BoolVarP(&flags.ShowExport, "export", "e", false, "export timewarrior timetable")
rootCmd.AddCommand(startCmd)
rootCmd.AddCommand(stopCmd)
rootCmd.AddCommand(showCmd)
log.Println("Loading Config File")
func NewApp() (*App, error) {
cfg, err := loadConfig()
if err != nil {
return nil, fmt.Errorf("error loading config: %w", err)
}
return &App{
cfg: cfg,
}, nil
}
func loadConfig() (Config, error) {
var cfg Config
configPath, err := os.UserConfigDir()
if err != nil {
return
return cfg, err
}
workConfigPath := filepath.Join(configPath, "work")
configFile := filepath.Join(workConfigPath, "config.toml")
viper.SetConfigFile(configFile)
viper.SetConfigType("toml")
viper.AddConfigPath(".")
viper.AutomaticEnv()
err = viper.ReadInConfig()
if err != nil {
log.Printf("error loading config file: %v", err)
if err := viper.ReadInConfig(); err != nil {
return cfg, fmt.Errorf("error reading config file: %w", err)
}
// allSettings := viper.AllSettings()
// log.Printf("All loaded settings: %+v", allSettings)
err = viper.UnmarshalKey("default", &cfg)
if err != nil {
log.Printf("unable to decode into struct: %v", err)
if err := viper.UnmarshalKey("default", &cfg); err != nil {
return cfg, fmt.Errorf("error decoding config: %w", err)
}
return cfg, nil
}
func connect() {
runCommand("timew", "start", "work")
wakeWorkstation()
sshClient, err := ssh.Dial("tcp", cfg.SSHHost+":"+fmt.Sprintf("%v", cfg.SSHPort), makeSSHClient())
func (a *App) connect() {
a.runCommand("timew", "start", "work")
a.wakeWorkstation()
sshClient, err := ssh.Dial("tcp", a.cfg.SSHHost+":"+fmt.Sprintf("%v", a.cfg.SSHPort), a.makeSSHClient())
if err != nil {
log.Fatal("Failed to dial: ", err)
}
@ -90,11 +93,11 @@ func connect() {
}
defer session.Close()
go forwardPort(sshClient, "2048", cfg.WorkstationIP, "22")
go forwardPort(sshClient, "2048", a.cfg.WorkstationIP, "22")
go forwardPort(sshClient, "6000", cfg.WorkstationIP, "3389")
go forwardPort(sshClient, "6000", a.cfg.WorkstationIP, "3389")
connectToWorkstation()
a.connectToWorkstation()
}
func forwardPort(sshConn *ssh.Client, localPort, remoteHost, remotePort string) {
@ -130,20 +133,20 @@ func copyConn(dst, src net.Conn) {
io.Copy(dst, src)
}
func makeSSHClient() *ssh.ClientConfig {
func (a *App) makeSSHClient() *ssh.ClientConfig {
keypath := os.ExpandEnv("$HOME/.ssh/hegenberg")
keyBytes, err := os.ReadFile(keypath)
if err != nil {
log.Fatalf("Failed to read private key: %s", err)
}
key, err := ssh.ParsePrivateKeyWithPassphrase(keyBytes, []byte(cfg.RDPPassword))
key, err := ssh.ParsePrivateKeyWithPassphrase(keyBytes, []byte(a.cfg.RDPPassword))
if err != nil {
log.Fatalf("Failed to parse private key: %s", err)
}
return &ssh.ClientConfig{
User: cfg.SSHUser,
User: a.cfg.SSHUser,
Auth: []ssh.AuthMethod{
ssh.PublicKeys(key),
},
@ -152,7 +155,7 @@ func makeSSHClient() *ssh.ClientConfig {
}
}
func runCommand(name string, args ...string) {
func (a *App) runCommand(name string, args ...string) {
cmd := exec.Command(name, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
@ -163,50 +166,44 @@ func runCommand(name string, args ...string) {
}
}
func startSequence() {
runCommand("timew", "start", "work")
wakeWorkstation()
connectToJump()
}
func wakeWorkstation() {
func (a *App) wakeWorkstation() {
sshCommand := fmt.Sprintf("ssh -tt -p %s %s@%s ssh -tt %s@%s \"wakeonlan %s && exit\"",
fmt.Sprintf("%v", cfg.SSHPort),
cfg.SSHUser,
cfg.SSHHost,
cfg.JumpUser,
cfg.JumpHost,
cfg.WorkstationMac)
fmt.Sprintf("%v", a.cfg.SSHPort),
a.cfg.SSHUser,
a.cfg.SSHHost,
a.cfg.JumpUser,
a.cfg.JumpHost,
a.cfg.WorkstationMac)
args := strings.Split(sshCommand, " ")
log.Println(args)
runCommand("ssh", args[1:]...)
a.runCommand("ssh", args[1:]...)
}
func connectToJump() {
func (a *App) connectToJump() {
sshCommand := fmt.Sprintf("ssh -tt -L 2048:%s:22 %s@%s",
cfg.WorkstationHost,
cfg.SSHUser,
cfg.SSHHost)
a.cfg.WorkstationHost,
a.cfg.SSHUser,
a.cfg.SSHHost)
args := strings.Split(sshCommand, " ")
runCommand("ssh", args[1:]...)
a.runCommand("ssh", args[1:]...)
}
func connectToWorkstation() {
func (a *App) connectToWorkstation() {
sshCommand := fmt.Sprintf("ssh -tt -L 6000:%s:3389 -p 2048 %s@127.0.0.1",
cfg.WorkstationHost,
cfg.SSHUser)
a.cfg.WorkstationHost,
a.cfg.SSHUser)
args := strings.Split(sshCommand, " ")
runCommand("ssh", args[1:]...)
a.runCommand("ssh", args[1:]...)
}
func startRDPConnection() {
func (a *App) startRDPConnection() {
rdpCommand := fmt.Sprintf("xfreerdp /u:%s /p:%s /v:127.0.0.1:6000 /size:3000x1350",
cfg.RDPUser,
cfg.RDPPassword)
runCommand("bash", "-c", rdpCommand)
a.cfg.RDPUser,
a.cfg.RDPPassword)
a.runCommand("bash", "-c", rdpCommand)
}
func makeChoice() {
func (a *App) makeChoice() {
var choice string
form := huh.NewForm(
huh.NewGroup(
@ -220,9 +217,9 @@ func makeChoice() {
huh.NewOption("Start Break", "start break"),
huh.NewOption("Stop Break", "stop break"),
huh.NewOption("Export Timetable", "export"),
huh.NewOption("Wake Lou", "wake lou"),
huh.NewOption("Connect to Varda", "connect to varda"),
huh.NewOption("Connect to Lou", "connect to lou"),
huh.NewOption("Wake Workstation", "wake workstation"),
huh.NewOption("Connect to Jump", "connect to jump"),
huh.NewOption("Connect to Workstation", "connect to workstation"),
huh.NewOption("Start RDP Connection", "start rdp connection"),
).
Value(&choice),
@ -237,83 +234,104 @@ func makeChoice() {
switch choice {
case "Start":
connect()
a.connect()
// startSequence()
case "stop Work":
runCommand("timew", "stop", "work")
a.runCommand("timew", "stop", "work")
case "start break":
runCommand("timew", "stop", "work")
runCommand("timew", "start", "break")
a.runCommand("timew", "track", "break")
case "stop break":
runCommand("timew", "stop", "break")
runCommand("timew", "start", "work")
a.runCommand("timew", "track", "work")
case "show week summary":
runCommand("timew", "summary", ":week", "work")
a.runCommand("timew", "summary", ":week", "work")
case "show month summary":
runCommand("timew", "summary", ":month", "work")
case "wake lou":
wakeWorkstation()
case "connect to varda":
connectToJump()
case "connect to lou":
connectToWorkstation()
a.runCommand("timew", "summary", ":month", "work")
case "wake workstation":
a.wakeWorkstation()
case "connect to jump":
a.connectToJump()
case "connect to workstation":
a.connectToWorkstation()
case "start rdp connection":
startRDPConnection()
a.startRDPConnection()
case "export":
fmt.Println("Exporting Work times")
}
}
var rootCmd = &cobra.Command{
Use: "work",
Short: "Fast work interactions",
Long: `A CLI tool to perform basic work cli tasks.`,
func (a *App) setupCommands() *cobra.Command {
rootCmd := &cobra.Command{
Use: "work",
Short: "Fast work interactions",
Long: `A CLI tool to perform basic work cli tasks.`,
}
rootCmd.AddCommand(a.startCommand())
rootCmd.AddCommand(a.stopCommand())
rootCmd.AddCommand(a.showCommand())
return rootCmd
}
var startCmd = &cobra.Command{
Use: "start",
Short: "start work",
Long: "command to start the work day",
Run: func(cmd *cobra.Command, args []string) {
connect()
},
func (a *App) startCommand() *cobra.Command {
return &cobra.Command{
Use: "start",
Short: "start work",
Long: "command to start the work day",
Run: func(cmd *cobra.Command, args []string) {
a.connect()
},
}
}
var stopCmd = &cobra.Command{
Use: "stop",
Short: "stop work",
Long: "command to stop the work day",
Run: func(cmd *cobra.Command, args []string) {
runCommand("timew", "stop", "work")
os.Exit(0)
},
func (a *App) stopCommand() *cobra.Command {
return &cobra.Command{
Use: "stop",
Short: "stop work",
Long: "command to stop the work day",
Run: func(cmd *cobra.Command, args []string) {
a.runCommand("timew", "stop", "work")
os.Exit(0)
},
}
}
var showCmd = &cobra.Command{
Use: "show",
Short: "show timetracking",
Long: "show different timetracking",
Run: func(cmd *cobra.Command, args []string) {
if flags.ShowExport {
fmt.Println("Exporting timetable")
}
if flags.ShowWeek {
runCommand("timew", "summary", ":week", "work")
}
if flags.ShowMonth {
runCommand("timew", "summary", ":month", "work")
}
os.Exit(0)
},
func (a *App) showCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "show",
Short: "show timetracking",
Long: "show different timetracking",
Run: func(cmd *cobra.Command, args []string) {
if a.flags.ShowExport {
fmt.Println("Exporting timetable")
}
if a.flags.ShowWeek {
a.runCommand("timew", "summary", ":week", "work")
}
if a.flags.ShowMonth {
a.runCommand("timew", "summary", ":month", "work")
}
os.Exit(0)
},
}
cmd.Flags().BoolVarP(&a.flags.ShowWeek, "week", "w", false, "show timewarrior week summary")
cmd.Flags().BoolVarP(&a.flags.ShowMonth, "month", "m", false, "show timewarrior month summary")
cmd.Flags().BoolVarP(&a.flags.ShowExport, "export", "e", false, "export timewarrior timetable")
return cmd
}
func main() {
app, err := NewApp()
if err != nil {
log.Fatalf("unable to setup application: %v", err)
}
if len(os.Args) > 1 {
if err := rootCmd.Execute(); err != nil {
if err := app.setupCommands().Execute(); err != nil {
log.Fatalf("error executing command: %v", err)
}
// return
} else {
makeChoice()
app.makeChoice()
}
}