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
import (
"bytes"
"bufio"
"io"
"net"
"os"
@ -21,11 +21,19 @@ import (
const PARALLELIZE = 16
const instanceNotFound = Error("instance not found")
var msgOut chan string
var msgErr chan string
func main() {
if len(os.Args) < 2 {
usage()
}
msgOut = make(chan string, PARALLELIZE)
msgErr = make(chan string, PARALLELIZE)
go logger(os.Stdout, msgOut)
go logger(os.Stderr, msgErr)
var err error
switch os.Args[1] {
case "spawn":
@ -37,17 +45,23 @@ func main() {
}
if err != nil {
fmt.Fprintf(os.Stderr, "cmd failed: %v\n", err)
msgErr <- fmt.Sprintf("cmd failed: %v\n", err)
os.Exit(1)
}
}
func logger(o *os.File, c chan string) {
for m := range c {
fmt.Fprint(o, m)
}
}
func usage() {
var programName = "swtool"
if len(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)
}
@ -70,6 +84,7 @@ type instanceReceiver interface {
func passInstanceTo(r io.Reader, d instanceReceiver) error {
com := make(chan error, PARALLELIZE)
count := 0
failed := 0
@ -87,14 +102,15 @@ func passInstanceTo(r io.Reader, d instanceReceiver) error {
go func(zone, machine, image, name string) {
err := d.onInstance(zone, machine, image, name)
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
}(zone, machine, image, name)
count += 1
}
fmt.Fprintf(os.Stdout, " Waiting for %v servers\n", count)
msgOut <- fmt.Sprintf(" Waiting for %v servers\n", count)
for count > 0 {
err := <- com
count -= 1
@ -170,7 +186,7 @@ func (sp *spawner) onInstance(zone, machine, image, name string) error {
if err == nil {
ip := parseIP(targetServer)
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
}
} else if err == instanceNotFound {
@ -207,7 +223,7 @@ func (sp *spawner) onInstance(zone, machine, image, name string) error {
}
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
}
@ -224,7 +240,7 @@ func (dt *destroyer) onInstance(zone, machine, image, name string) error {
targetServer, err := dt.getInstanceByName(z, name)
if err == instanceNotFound {
fmt.Fprintf(os.Stdout, "🟣 %v is already destroyed\n", name)
msgOut <- fmt.Sprintf("🟣 %v is already destroyed\n", name)
return nil
} else if err != nil {
return err
@ -248,7 +264,7 @@ func (dt *destroyer) onInstance(zone, machine, image, name string) error {
}
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
}
@ -296,7 +312,7 @@ func (r *runner) connect(zone, name string) (*ssh.Client, error) {
func (r *runner) send(sshClient *ssh.Client) error {
// Source script
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])
@ -327,6 +343,16 @@ func (r *runner) send(sshClient *ssh.Client) error {
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 {
// Run the script
session, err := sshClient.NewSession()
@ -335,16 +361,21 @@ func (r *runner) exec(sshClient *ssh.Client) error {
}
defer session.Close()
var sshStdout, sshStderr bytes.Buffer
session.Stdout = &sshStdout
session.Stderr = &sshStderr
if os.Getenv("VERBOSE") != "" {
readErr, err := session.StderrPipe()
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")
if os.Getenv("VERBOSE") != "" {
fmt.Fprintf(os.Stdout, "logs\n")
io.Copy(os.Stdout, &sshStdout)
io.Copy(os.Stderr, &sshStderr)
}
if err != nil {
return err
}
@ -369,7 +400,7 @@ func (r *runner) onInstance(zone, machine, image, name string) error {
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
}