blob: 98627a53e1264bcf61ecd7354ae90b46779552b5 [file] [log] [blame]
package main
import (
"context"
"encoding/json"
"fmt"
"os"
"os/exec"
"os/signal"
"reflect"
)
var actions Actions
func newVppContext() (context.Context, context.CancelFunc) {
ctx, cancel := signal.NotifyContext(
context.Background(),
os.Interrupt,
)
return ctx, cancel
}
func Vppcli(runDir, command string) (string, error) {
cmd := exec.Command("vppctl", "-s", fmt.Sprintf("%s/var/run/vpp/cli.sock", runDir), command)
o, err := cmd.CombinedOutput()
if err != nil {
fmt.Printf("failed to execute command: '%v'.\n", err)
}
fmt.Printf("Command output %s", string(o))
return string(o), err
}
func exitOnErrCh(ctx context.Context, cancel context.CancelFunc, errCh <-chan error) {
// If we already have an error, log it and exit
select {
case err := <-errCh:
fmt.Printf("%v", err)
default:
}
go func(ctx context.Context, errCh <-chan error) {
<-errCh
cancel()
}(ctx, errCh)
}
func writeSyncFile(res *ActionResult) error {
syncFile := "/tmp/sync/rc"
var jsonRes JsonResult
jsonRes.ErrOutput = res.ErrOutput
jsonRes.StdOutput = res.StdOutput
if res.Err != nil {
jsonRes.Code = 1
jsonRes.Desc = fmt.Sprintf("%s :%v", res.Desc, res.Err)
} else {
jsonRes.Code = 0
}
str, err := json.Marshal(jsonRes)
if err != nil {
return fmt.Errorf("error marshaling json result data! %v", err)
}
_, err = os.Open(syncFile)
if err != nil {
// expecting the file does not exist
f, e := os.Create(syncFile)
if e != nil {
return fmt.Errorf("failed to open sync file")
}
defer f.Close()
f.Write([]byte(str))
} else {
return fmt.Errorf("sync file exists, delete the file first")
}
return nil
}
func NewActionResult(err error, opts ...ActionResultOptionFn) *ActionResult {
res := &ActionResult{
Err: err,
}
for _, o := range opts {
o(res)
}
return res
}
type ActionResultOptionFn func(res *ActionResult)
func ActionResultWithDesc(s string) ActionResultOptionFn {
return func(res *ActionResult) {
res.Desc = s
}
}
func ActionResultWithStderr(s string) ActionResultOptionFn {
return func(res *ActionResult) {
res.ErrOutput = s
}
}
func ActionResultWithStdout(s string) ActionResultOptionFn {
return func(res *ActionResult) {
res.StdOutput = s
}
}
func OkResult() *ActionResult {
return NewActionResult(nil)
}
func processArgs() *ActionResult {
nArgs := len(os.Args) - 1 // skip program name
if nArgs < 1 {
return NewActionResult(fmt.Errorf("internal: no action specified!"))
}
action := os.Args[1]
methodValue := reflect.ValueOf(&actions).MethodByName(action)
if !methodValue.IsValid() {
return NewActionResult(fmt.Errorf("internal unknown action %s!", action))
}
methodIface := methodValue.Interface()
fn := methodIface.(func([]string) *ActionResult)
return fn(os.Args)
}
func main() {
if len(os.Args) == 0 {
fmt.Println("args required")
return
}
if os.Args[1] == "rm" {
topology, err := LoadTopology(NetworkTopologyDir, os.Args[2])
if err != nil {
fmt.Printf("falied to load topologies: %v\n", err)
os.Exit(1)
}
topology.Unconfigure()
os.Exit(0)
}
var err error
res := processArgs()
err = writeSyncFile(res)
if err != nil {
fmt.Printf("failed to write to sync file: %v\n", err)
}
}