refactor: seperate application into seperate files and add killForwarding
This commit is contained in:
parent
fec43ea77d
commit
a7ea6f41a7
7 changed files with 481 additions and 357 deletions
230
app.go
Normal file
230
app.go
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/charmbracelet/huh"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type App struct {
|
||||
cfg Config
|
||||
flags Flags
|
||||
}
|
||||
|
||||
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 (a *App) connect() {
|
||||
tw := NewTimeWarrior()
|
||||
tw.StartWork()
|
||||
a.wakeWorkstation()
|
||||
sshCon, err := a.newSSHConnection()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to establish ssh-connection: %v", err)
|
||||
}
|
||||
defer sshCon.Close()
|
||||
|
||||
sshFowarder := NewPortForwarder(sshCon.client, "2048", "22", a.cfg.WorkstationIP)
|
||||
go sshFowarder.forward()
|
||||
|
||||
rdpFowarder := NewPortForwarder(sshCon.client, "6000", "3389", a.cfg.WorkstationIP)
|
||||
go rdpFowarder.forward()
|
||||
|
||||
a.connectToWorkstation()
|
||||
}
|
||||
|
||||
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(a.cfg.RDPPassword))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to parse private key: %s", err)
|
||||
}
|
||||
|
||||
return &ssh.ClientConfig{
|
||||
User: a.cfg.SSHUser,
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.PublicKeys(key),
|
||||
},
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
Timeout: 5 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) runCommand(name string, args ...string) {
|
||||
cmd := exec.Command(name, args...)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdin = os.Stdin
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) wakeWorkstation() {
|
||||
sshCommand := fmt.Sprintf("ssh -tt -p %s %s@%s ssh -tt %s@%s \"wakeonlan %s && exit\"",
|
||||
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)
|
||||
a.runCommand("ssh", args[1:]...)
|
||||
}
|
||||
|
||||
func (a *App) connectToJump() {
|
||||
sshCommand := fmt.Sprintf("ssh -tt -L 2048:%s:22 %s@%s",
|
||||
a.cfg.WorkstationHost,
|
||||
a.cfg.SSHUser,
|
||||
a.cfg.SSHHost)
|
||||
args := strings.Split(sshCommand, " ")
|
||||
a.runCommand("ssh", args[1:]...)
|
||||
}
|
||||
|
||||
func (a *App) connectToWorkstation() {
|
||||
sshCommand := fmt.Sprintf("ssh -tt -L 6000:%s:3389 -p 2048 %s@127.0.0.1",
|
||||
a.cfg.WorkstationHost,
|
||||
a.cfg.SSHUser)
|
||||
args := strings.Split(sshCommand, " ")
|
||||
a.runCommand("ssh", args[1:]...)
|
||||
}
|
||||
|
||||
func (a *App) startRDPConnection() {
|
||||
rdpCommand := fmt.Sprintf("xfreerdp /u:%s /p:%s /v:127.0.0.1:6000 /size:3000x1350",
|
||||
a.cfg.RDPUser,
|
||||
a.cfg.RDPPassword)
|
||||
a.runCommand("bash", "-c", rdpCommand)
|
||||
}
|
||||
|
||||
func (a *App) makeChoice() {
|
||||
var choice string
|
||||
tw := NewTimeWarrior()
|
||||
form := huh.NewForm(
|
||||
huh.NewGroup(
|
||||
huh.NewSelect[string]().
|
||||
Title("What would you like to do?").
|
||||
Options(
|
||||
huh.NewOption("Start Work", "start work"),
|
||||
huh.NewOption("Stop Work", "stop work"),
|
||||
huh.NewOption("Show Week Summary", "show week summary"),
|
||||
huh.NewOption("Show Month Summary", "show month summary"),
|
||||
huh.NewOption("Start Break", "start break"),
|
||||
huh.NewOption("Stop Break", "stop break"),
|
||||
huh.NewOption("Export Timetable", "export"),
|
||||
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),
|
||||
),
|
||||
)
|
||||
|
||||
err := form.Run()
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
return
|
||||
}
|
||||
|
||||
switch choice {
|
||||
case "start work":
|
||||
a.connect()
|
||||
case "stop work":
|
||||
tw.StopWork()
|
||||
case "start break":
|
||||
tw.StartBreak()
|
||||
case "stop break":
|
||||
tw.StopBreak()
|
||||
case "show week summary":
|
||||
tw.ShowSummary(":week")
|
||||
case "show month summary":
|
||||
tw.ShowSummary(":month")
|
||||
case "connect to jump":
|
||||
a.connectToJump()
|
||||
case "connect to workstation":
|
||||
a.connectToWorkstation()
|
||||
case "start rdp connection":
|
||||
a.startRDPConnection()
|
||||
case "export":
|
||||
tw.ExportSummary()
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) getSSHAuth() ssh.AuthMethod {
|
||||
keypath := os.ExpandEnv("$HOME/.ssh/hegenberg")
|
||||
keyBytes, err := os.ReadFile(keypath)
|
||||
if err != nil {
|
||||
fmt.Printf("unable to read private key: %v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
key, err := ssh.ParsePrivateKeyWithPassphrase(keyBytes, []byte(a.cfg.RDPPassword))
|
||||
if err != nil {
|
||||
fmt.Printf("unable to parse privat key: %v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
return ssh.PublicKeys(key)
|
||||
}
|
||||
|
||||
func (a *App) newSSHConnection() (*SSHConnection, error) {
|
||||
config := &ssh.ClientConfig{
|
||||
User: a.cfg.SSHUser,
|
||||
Auth: []ssh.AuthMethod{a.getSSHAuth()},
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
Timeout: 5 * time.Second,
|
||||
}
|
||||
|
||||
client, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", a.cfg.SSHHost, a.cfg.SSHPort), config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ssh dial failed: %w", err)
|
||||
}
|
||||
|
||||
session, err := client.NewSession()
|
||||
if err != nil {
|
||||
client.Close()
|
||||
return nil, fmt.Errorf("creating ssh session failed: %w", err)
|
||||
}
|
||||
|
||||
return &SSHConnection{
|
||||
client: client,
|
||||
session: session,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *App) killForwardings() error {
|
||||
ports := []string{"2048", "6000"}
|
||||
for _, port := range ports {
|
||||
cmd := exec.Command("lsof", "-ti", "tcp:"+port)
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
pids := strings.Split(string(output), "\n")
|
||||
pid := strings.TrimSpace(pids[0])
|
||||
killCmd := exec.Command("kill", pid)
|
||||
killCmd.Run()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
75
cmd.go
Normal file
75
cmd.go
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
tw := NewTimeWarrior()
|
||||
tw.StopWork()
|
||||
if err := a.killForwardings(); err != nil {
|
||||
log.Printf("error stoping port forwarding: %v", err)
|
||||
}
|
||||
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) {
|
||||
tw := NewTimeWarrior()
|
||||
if a.flags.ShowExport {
|
||||
tw.ExportSummary()
|
||||
}
|
||||
if a.flags.ShowWeek {
|
||||
tw.ShowSummary(":week")
|
||||
}
|
||||
if a.flags.ShowMonth {
|
||||
tw.ShowSummary(":month")
|
||||
}
|
||||
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
|
||||
}
|
||||
54
config.go
Normal file
54
config.go
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
SSHUser string `mapstructure:"SSH_USER"`
|
||||
SSHHost string `mapstructure:"SSH_HOST"`
|
||||
JumpUser string `mapstructure:"JUMP_USER"`
|
||||
JumpHost string `mapstructure:"JUMP_HOST"`
|
||||
WorkstationHost string `mapstructure:"WORKSTATION_HOST"`
|
||||
WorkstationUser string `mapstructure:"WORKSTATION_USER"`
|
||||
WorkstationMac string `mapstructure:"WORKSTATION_MAC"`
|
||||
RDPUser string `mapstructure:"RDP_USER"`
|
||||
RDPPassword string `mapstructure:"RDP_PASSWORD"`
|
||||
WorkstationIP string `mapstructure:"WORKSTATION_IP"`
|
||||
SSHPort int `mapstructure:"SSH_PORT"`
|
||||
}
|
||||
|
||||
type Flags struct {
|
||||
ShowWeek bool
|
||||
ShowMonth bool
|
||||
ShowExport bool
|
||||
}
|
||||
|
||||
func loadConfig() (Config, error) {
|
||||
var cfg Config
|
||||
configPath, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
return cfg, err
|
||||
}
|
||||
|
||||
workConfigPath := filepath.Join(configPath, "work")
|
||||
configFile := filepath.Join(workConfigPath, "config.toml")
|
||||
|
||||
viper.SetConfigFile(configFile)
|
||||
viper.SetConfigType("toml")
|
||||
viper.AddConfigPath(".")
|
||||
viper.AutomaticEnv()
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
return cfg, fmt.Errorf("error reading config file: %w", err)
|
||||
}
|
||||
|
||||
if err := viper.UnmarshalKey("default", &cfg); err != nil {
|
||||
return cfg, fmt.Errorf("error decoding config: %w", err)
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
58
forwarder.go
Normal file
58
forwarder.go
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type PortFowarder struct {
|
||||
sshCon *ssh.Client
|
||||
localPort string
|
||||
remotePort string
|
||||
remoteHost string
|
||||
}
|
||||
|
||||
func NewPortForwarder(sshCon *ssh.Client, localPort, remotePort, remoteHost string) *PortFowarder {
|
||||
return &PortFowarder{
|
||||
sshCon: sshCon,
|
||||
localPort: localPort,
|
||||
remotePort: remotePort,
|
||||
remoteHost: remoteHost,
|
||||
}
|
||||
}
|
||||
|
||||
func (pw *PortFowarder) forward() error {
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:"+pw.localPort)
|
||||
if err != nil {
|
||||
log.Printf("Fehler beim Öffnen des lokalen Ports %s: %v", pw.localPort, err)
|
||||
return err
|
||||
}
|
||||
defer listener.Close()
|
||||
|
||||
for {
|
||||
localConn, err := listener.Accept()
|
||||
if err != nil {
|
||||
log.Printf("Fehler beim Akzeptieren der Verbindung: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
remoteConn, err := pw.sshCon.Dial("tcp", pw.remoteHost+":"+pw.remotePort)
|
||||
if err != nil {
|
||||
log.Printf("Fehler beim Verbinden zum Remote-Host %s:%s: %v", pw.remoteHost, pw.remotePort, err)
|
||||
localConn.Close()
|
||||
continue
|
||||
}
|
||||
|
||||
go pw.copyConn(localConn, remoteConn)
|
||||
go pw.copyConn(remoteConn, localConn)
|
||||
}
|
||||
}
|
||||
|
||||
func (pw *PortFowarder) copyConn(dst, src net.Conn) {
|
||||
defer dst.Close()
|
||||
defer src.Close()
|
||||
io.Copy(dst, src)
|
||||
}
|
||||
357
main.go
357
main.go
|
|
@ -1,367 +1,10 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/charmbracelet/huh"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
SSHUser string `mapstructure:"SSH_USER"`
|
||||
SSHHost string `mapstructure:"SSH_HOST"`
|
||||
JumpUser string `mapstructure:"JUMP_USER"`
|
||||
JumpHost string `mapstructure:"JUMP_HOST"`
|
||||
WorkstationHost string `mapstructure:"WORKSTATION_HOST"`
|
||||
WorkstationUser string `mapstructure:"WORKSTATION_USER"`
|
||||
WorkstationMac string `mapstructure:"WORKSTATION_MAC"`
|
||||
RDPUser string `mapstructure:"RDP_USER"`
|
||||
RDPPassword string `mapstructure:"RDP_PASSWORD"`
|
||||
WorkstationIP string `mapstructure:"WORKSTATION_IP"`
|
||||
SSHPort int `mapstructure:"SSH_PORT"`
|
||||
}
|
||||
|
||||
type Flags struct {
|
||||
ShowWeek bool
|
||||
ShowMonth bool
|
||||
ShowExport bool
|
||||
}
|
||||
|
||||
type App struct {
|
||||
cfg Config
|
||||
flags Flags
|
||||
}
|
||||
|
||||
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 cfg, err
|
||||
}
|
||||
|
||||
workConfigPath := filepath.Join(configPath, "work")
|
||||
configFile := filepath.Join(workConfigPath, "config.toml")
|
||||
|
||||
viper.SetConfigFile(configFile)
|
||||
viper.SetConfigType("toml")
|
||||
viper.AddConfigPath(".")
|
||||
viper.AutomaticEnv()
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
return cfg, fmt.Errorf("error reading config file: %w", err)
|
||||
}
|
||||
|
||||
if err := viper.UnmarshalKey("default", &cfg); err != nil {
|
||||
return cfg, fmt.Errorf("error decoding config: %w", err)
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (a *App) connect() {
|
||||
tw := NewTimeWarrior()
|
||||
tw.StartWork()
|
||||
// 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)
|
||||
}
|
||||
defer sshClient.Close()
|
||||
|
||||
session, err := sshClient.NewSession()
|
||||
if err != nil {
|
||||
log.Fatal("Failed to create session: ", err)
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
go forwardPort(sshClient, "2048", a.cfg.WorkstationIP, "22")
|
||||
|
||||
go forwardPort(sshClient, "6000", a.cfg.WorkstationIP, "3389")
|
||||
|
||||
a.connectToWorkstation()
|
||||
}
|
||||
|
||||
func forwardPort(sshConn *ssh.Client, localPort, remoteHost, remotePort string) {
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:"+localPort)
|
||||
if err != nil {
|
||||
log.Printf("Fehler beim Öffnen des lokalen Ports %s: %v", localPort, err)
|
||||
return
|
||||
}
|
||||
defer listener.Close()
|
||||
|
||||
for {
|
||||
localConn, err := listener.Accept()
|
||||
if err != nil {
|
||||
log.Printf("Fehler beim Akzeptieren der Verbindung: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
remoteConn, err := sshConn.Dial("tcp", remoteHost+":"+remotePort)
|
||||
if err != nil {
|
||||
log.Printf("Fehler beim Verbinden zum Remote-Host %s:%s: %v", remoteHost, remotePort, err)
|
||||
localConn.Close()
|
||||
continue
|
||||
}
|
||||
|
||||
go copyConn(localConn, remoteConn)
|
||||
go copyConn(remoteConn, localConn)
|
||||
}
|
||||
}
|
||||
|
||||
func copyConn(dst, src net.Conn) {
|
||||
defer dst.Close()
|
||||
defer src.Close()
|
||||
io.Copy(dst, src)
|
||||
}
|
||||
|
||||
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(a.cfg.RDPPassword))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to parse private key: %s", err)
|
||||
}
|
||||
|
||||
return &ssh.ClientConfig{
|
||||
User: a.cfg.SSHUser,
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.PublicKeys(key),
|
||||
},
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
Timeout: 5 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) runCommand(name string, args ...string) {
|
||||
cmd := exec.Command(name, args...)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdin = os.Stdin
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) wakeWorkstation() {
|
||||
sshCommand := fmt.Sprintf("ssh -tt -p %s %s@%s ssh -tt %s@%s \"wakeonlan %s && exit\"",
|
||||
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)
|
||||
a.runCommand("ssh", args[1:]...)
|
||||
}
|
||||
|
||||
func (a *App) connectToJump() {
|
||||
sshCommand := fmt.Sprintf("ssh -tt -L 2048:%s:22 %s@%s",
|
||||
a.cfg.WorkstationHost,
|
||||
a.cfg.SSHUser,
|
||||
a.cfg.SSHHost)
|
||||
args := strings.Split(sshCommand, " ")
|
||||
a.runCommand("ssh", args[1:]...)
|
||||
}
|
||||
|
||||
func (a *App) connectToWorkstation() {
|
||||
sshCommand := fmt.Sprintf("ssh -tt -L 6000:%s:3389 -p 2048 %s@127.0.0.1",
|
||||
a.cfg.WorkstationHost,
|
||||
a.cfg.SSHUser)
|
||||
args := strings.Split(sshCommand, " ")
|
||||
a.runCommand("ssh", args[1:]...)
|
||||
}
|
||||
|
||||
func (a *App) startRDPConnection() {
|
||||
rdpCommand := fmt.Sprintf("xfreerdp /u:%s /p:%s /v:127.0.0.1:6000 /size:3000x1350",
|
||||
a.cfg.RDPUser,
|
||||
a.cfg.RDPPassword)
|
||||
a.runCommand("bash", "-c", rdpCommand)
|
||||
}
|
||||
|
||||
func (a *App) makeChoice() {
|
||||
var choice string
|
||||
tw := NewTimeWarrior()
|
||||
form := huh.NewForm(
|
||||
huh.NewGroup(
|
||||
huh.NewSelect[string]().
|
||||
Title("What would you like to do?").
|
||||
Options(
|
||||
huh.NewOption("Start", "Start"),
|
||||
huh.NewOption("Stop Work", "stop Work"),
|
||||
huh.NewOption("Show Week Summary", "show week summary"),
|
||||
huh.NewOption("Show Month Summary", "show month summary"),
|
||||
huh.NewOption("Start Break", "start break"),
|
||||
huh.NewOption("Stop Break", "stop break"),
|
||||
huh.NewOption("Export Timetable", "export"),
|
||||
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),
|
||||
),
|
||||
)
|
||||
|
||||
err := form.Run()
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
return
|
||||
}
|
||||
|
||||
switch choice {
|
||||
case "Start":
|
||||
a.connect()
|
||||
case "stop Work":
|
||||
tw.StopWork()
|
||||
case "start break":
|
||||
tw.StartBreak()
|
||||
case "stop break":
|
||||
tw.StopBreak()
|
||||
case "show week summary":
|
||||
tw.ShowSummary(":week")
|
||||
case "show month summary":
|
||||
tw.ShowSummary(":month")
|
||||
case "wake workstation":
|
||||
a.wakeWorkstation()
|
||||
case "connect to jump":
|
||||
a.connectToJump()
|
||||
case "connect to workstation":
|
||||
a.connectToWorkstation()
|
||||
case "start rdp connection":
|
||||
a.startRDPConnection()
|
||||
case "export":
|
||||
tw.ExportSummary()
|
||||
}
|
||||
}
|
||||
|
||||
type TimeWarrior struct{}
|
||||
|
||||
func NewTimeWarrior() *TimeWarrior {
|
||||
return &TimeWarrior{}
|
||||
}
|
||||
|
||||
func (t *TimeWarrior) runCommand(args ...string) error {
|
||||
cmd := exec.Command("timew", args...)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stderr = os.Stderr
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
func (t *TimeWarrior) StartWork() error {
|
||||
return t.runCommand("start", "work")
|
||||
}
|
||||
|
||||
func (t *TimeWarrior) StopWork() error {
|
||||
return t.runCommand("stop", "work")
|
||||
}
|
||||
|
||||
func (t *TimeWarrior) StartBreak() error {
|
||||
return t.runCommand("track", "break")
|
||||
}
|
||||
|
||||
func (t *TimeWarrior) StopBreak() error {
|
||||
return t.runCommand("track", "work")
|
||||
}
|
||||
|
||||
func (t *TimeWarrior) ShowSummary(period string) error {
|
||||
return t.runCommand("summary", period, "work")
|
||||
}
|
||||
|
||||
func (t *TimeWarrior) ExportSummary() error {
|
||||
fmt.Println("Export Timetable")
|
||||
return nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
|
|
|||
18
ssh.go
Normal file
18
ssh.go
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
package main
|
||||
|
||||
import "golang.org/x/crypto/ssh"
|
||||
|
||||
type SSHConnection struct {
|
||||
client *ssh.Client
|
||||
session *ssh.Session
|
||||
}
|
||||
|
||||
func (s *SSHConnection) Close() {
|
||||
if s.session != nil {
|
||||
s.session.Close()
|
||||
}
|
||||
|
||||
if s.client != nil {
|
||||
s.client.Close()
|
||||
}
|
||||
}
|
||||
46
timewarrior.go
Normal file
46
timewarrior.go
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
type TimeWarrior struct{}
|
||||
|
||||
func NewTimeWarrior() *TimeWarrior {
|
||||
return &TimeWarrior{}
|
||||
}
|
||||
|
||||
func (t *TimeWarrior) runCommand(args ...string) error {
|
||||
cmd := exec.Command("timew", args...)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stderr = os.Stderr
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
func (t *TimeWarrior) StartWork() error {
|
||||
return t.runCommand("start", "work")
|
||||
}
|
||||
|
||||
func (t *TimeWarrior) StopWork() error {
|
||||
return t.runCommand("stop", "work")
|
||||
}
|
||||
|
||||
func (t *TimeWarrior) StartBreak() error {
|
||||
return t.runCommand("track", "break")
|
||||
}
|
||||
|
||||
func (t *TimeWarrior) StopBreak() error {
|
||||
return t.runCommand("track", "work")
|
||||
}
|
||||
|
||||
func (t *TimeWarrior) ShowSummary(period string) error {
|
||||
return t.runCommand("summary", period, "work")
|
||||
}
|
||||
|
||||
func (t *TimeWarrior) ExportSummary() error {
|
||||
fmt.Println("Export Timetable")
|
||||
return nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue