Compare commits

...

1 Commits

Author SHA1 Message Date
Quentin 2f246bb05c WIP safer logs 2021-09-23 16:40:41 +02:00
1 changed files with 50 additions and 19 deletions

69
main.go
View File

@ -1,7 +1,7 @@
package main package main
import ( import (
"bytes" "bufio"
"io" "io"
"net" "net"
"os" "os"
@ -21,11 +21,19 @@ import (
const PARALLELIZE = 16 const PARALLELIZE = 16
const instanceNotFound = Error("instance not found") const instanceNotFound = Error("instance not found")
var msgOut chan string
var msgErr chan string
func main() { func main() {
if len(os.Args) < 2 { if len(os.Args) < 2 {
usage() usage()
} }
msgOut = make(chan string, PARALLELIZE)
msgErr = make(chan string, PARALLELIZE)
go logger(os.Stdout, msgOut)
go logger(os.Stderr, msgErr)
var err error var err error
switch os.Args[1] { switch os.Args[1] {
case "spawn": case "spawn":
@ -37,17 +45,23 @@ func main() {
} }
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "cmd failed: %v\n", err) msgErr <- fmt.Sprintf("cmd failed: %v\n", err)
os.Exit(1) os.Exit(1)
} }
} }
func logger(o *os.File, c chan string) {
for m := range c {
fmt.Fprint(o, m)
}
}
func usage() { func usage() {
var programName = "swtool" var programName = "swtool"
if len(os.Args) > 0 { if len(os.Args) > 0 {
programName = os.Args[0] programName = os.Args[0]
} }
fmt.Fprintf(os.Stderr, "Usage: %v (spawn|run|destroy)\n", programName) msgErr <- fmt.Sprintf("Usage: %v (spawn|run|destroy)\n", programName)
os.Exit(1) os.Exit(1)
} }
@ -70,6 +84,7 @@ type instanceReceiver interface {
func passInstanceTo(r io.Reader, d instanceReceiver) error { func passInstanceTo(r io.Reader, d instanceReceiver) error {
com := make(chan error, PARALLELIZE) com := make(chan error, PARALLELIZE)
count := 0 count := 0
failed := 0 failed := 0
@ -87,14 +102,15 @@ func passInstanceTo(r io.Reader, d instanceReceiver) error {
go func(zone, machine, image, name string) { go func(zone, machine, image, name string) {
err := d.onInstance(zone, machine, image, name) err := d.onInstance(zone, machine, image, name)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "❌ Operation failed for %v (%v, %v, %v): %v\n", name, zone, machine, image, err) msgErr <- fmt.Sprintf("❌ Operation failed for %v (%v, %v, %v): %v\n", name, zone, machine, image, err)
} }
com <- err com <- err
}(zone, machine, image, name) }(zone, machine, image, name)
count += 1 count += 1
} }
fmt.Fprintf(os.Stdout, " Waiting for %v servers\n", count) msgOut <- fmt.Sprintf(" Waiting for %v servers\n", count)
for count > 0 { for count > 0 {
err := <- com err := <- com
count -= 1 count -= 1
@ -170,7 +186,7 @@ func (sp *spawner) onInstance(zone, machine, image, name string) error {
if err == nil { if err == nil {
ip := parseIP(targetServer) ip := parseIP(targetServer)
if targetServer.State == instance.ServerStateRunning { if targetServer.State == instance.ServerStateRunning {
fmt.Fprintf(os.Stdout, "🟣 Found %v on zone %v with ip %v\n", targetServer.Name, targetServer.Zone, ip) msgOut <- fmt.Sprintf("🟣 Found %v on zone %v with ip %v\n", targetServer.Name, targetServer.Zone, ip)
return nil return nil
} }
} else if err == instanceNotFound { } else if err == instanceNotFound {
@ -207,7 +223,7 @@ func (sp *spawner) onInstance(zone, machine, image, name string) error {
} }
ip := parseIP(targetServer) ip := parseIP(targetServer)
fmt.Fprintf(os.Stdout, "✅ Started %v on zone %v with ip %v\n", targetServer.Name, targetServer.Zone, ip) msgOut <- fmt.Sprintf("✅ Started %v on zone %v with ip %v\n", targetServer.Name, targetServer.Zone, ip)
return nil return nil
} }
@ -224,7 +240,7 @@ func (dt *destroyer) onInstance(zone, machine, image, name string) error {
targetServer, err := dt.getInstanceByName(z, name) targetServer, err := dt.getInstanceByName(z, name)
if err == instanceNotFound { if err == instanceNotFound {
fmt.Fprintf(os.Stdout, "🟣 %v is already destroyed\n", name) msgOut <- fmt.Sprintf("🟣 %v is already destroyed\n", name)
return nil return nil
} else if err != nil { } else if err != nil {
return err return err
@ -248,7 +264,7 @@ func (dt *destroyer) onInstance(zone, machine, image, name string) error {
} }
ip := parseIP(targetServer) ip := parseIP(targetServer)
fmt.Fprintf(os.Stdout, "✅ Destroyed %v on zone %v with ip %v\n", targetServer.Name, targetServer.Zone, ip) msgOut <- fmt.Sprintf("✅ Destroyed %v on zone %v with ip %v\n", targetServer.Name, targetServer.Zone, ip)
return nil return nil
} }
@ -296,7 +312,7 @@ func (r *runner) connect(zone, name string) (*ssh.Client, error) {
func (r *runner) send(sshClient *ssh.Client) error { func (r *runner) send(sshClient *ssh.Client) error {
// Source script // Source script
if len(os.Args) < 3 { if len(os.Args) < 3 {
return errors.New("Missing script to run on the command line") return errors.New("missing script to run on the command line")
} }
src, err := os.Open(os.Args[2]) src, err := os.Open(os.Args[2])
@ -327,6 +343,16 @@ func (r *runner) send(sshClient *ssh.Client) error {
return err return err
} }
func readerToChan(r io.Reader, c chan string) {
br := bufio.NewReader(r)
for {
s, err := br.ReadString('\n')
if err != nil {
break
}
c <- s
}
}
func (r *runner) exec(sshClient *ssh.Client) error { func (r *runner) exec(sshClient *ssh.Client) error {
// Run the script // Run the script
session, err := sshClient.NewSession() session, err := sshClient.NewSession()
@ -335,16 +361,21 @@ func (r *runner) exec(sshClient *ssh.Client) error {
} }
defer session.Close() defer session.Close()
var sshStdout, sshStderr bytes.Buffer if os.Getenv("VERBOSE") != "" {
session.Stdout = &sshStdout readErr, err := session.StderrPipe()
session.Stderr = &sshStderr if err != nil {
return err
}
readerToChan(readErr, msgErr)
readOut, err := session.StdoutPipe()
if err != nil {
return err
}
readerToChan(readOut, msgOut)
}
err = session.Run("/tmp/nuage") err = session.Run("/tmp/nuage")
if os.Getenv("VERBOSE") != "" {
fmt.Fprintf(os.Stdout, "logs\n")
io.Copy(os.Stdout, &sshStdout)
io.Copy(os.Stderr, &sshStderr)
}
if err != nil { if err != nil {
return err return err
} }
@ -369,7 +400,7 @@ func (r *runner) onInstance(zone, machine, image, name string) error {
return err return err
} }
fmt.Fprintf(os.Stdout, "✅ Successfully ran the script on %v (zone %v)\n", name, zone) msgOut <- fmt.Sprintf("✅ Successfully ran the script on %v (zone %v)\n", name, zone)
return nil return nil
} }