hs-test: handle error in config serialization
[vpp.git] / extras / hs-test / vppinstance.go
1 package main
2
3 import (
4         "encoding/json"
5         "fmt"
6         "github.com/edwarnicke/exechelper"
7 )
8
9 const vppConfigTemplate = `unix {
10   nodaemon
11   log %[1]s/var/log/vpp/vpp.log
12   full-coredump
13   cli-listen %[1]s%[2]s
14   runtime-dir %[1]s/var/run
15   gid vpp
16 }
17
18 api-trace {
19   on
20 }
21
22 api-segment {
23   gid vpp
24 }
25
26 socksvr {
27   socket-name %[1]s/var/run/vpp/api.sock
28 }
29
30 statseg {
31   socket-name %[1]s/var/run/vpp/stats.sock
32 }
33
34 plugins {
35   plugin unittest_plugin.so { enable }
36   plugin dpdk_plugin.so { disable }
37   plugin crypto_aesni_plugin.so { enable }
38   plugin quic_plugin.so { enable }
39 }
40
41 `
42
43 const (
44         defaultCliSocketFilePath = "/var/run/vpp/cli.sock"
45 )
46
47 type VppInstance struct {
48         container      *Container
49         config         VppConfig
50         actionFuncName string
51 }
52
53 type VppConfig struct {
54         Variant           string
55         CliSocketFilePath string
56 }
57
58 func (vc *VppConfig) getTemplate() string {
59         return fmt.Sprintf(vppConfigTemplate, "%[1]s", vc.CliSocketFilePath)
60 }
61
62 func (vpp *VppInstance) set2VethsServer() {
63         vpp.actionFuncName = "Configure2Veths"
64         vpp.config.Variant = "srv"
65 }
66
67 func (vpp *VppInstance) set2VethsClient() {
68         vpp.actionFuncName = "Configure2Veths"
69         vpp.config.Variant = "cln"
70 }
71
72 func (vpp *VppInstance) setVppProxy() {
73         vpp.actionFuncName = "ConfigureVppProxy"
74 }
75
76 func (vpp *VppInstance) setEnvoyProxy() {
77         vpp.actionFuncName = "ConfigureEnvoyProxy"
78 }
79
80 func (vpp *VppInstance) setCliSocket(filePath string) {
81         vpp.config.CliSocketFilePath = filePath
82 }
83
84 func (vpp *VppInstance) getCliSocket() string {
85         return fmt.Sprintf("%s%s", vpp.container.workDir, vpp.config.CliSocketFilePath)
86 }
87
88 func (vpp *VppInstance) start() error {
89         if vpp.actionFuncName == "" {
90                 return fmt.Errorf("vpp start failed: action function name must not be blank")
91         }
92
93         serializedConfig, err := serializeVppConfig(vpp.config)
94         if err != nil {
95                 return fmt.Errorf("serialize vpp config: %v", err)
96         }
97         args := fmt.Sprintf("%s '%s'", vpp.actionFuncName, serializedConfig)
98         _, err = vpp.container.execAction(args)
99         if err != nil {
100                 return fmt.Errorf("vpp start failed: %s", err)
101         }
102
103         return nil
104 }
105
106 func (vpp *VppInstance) vppctl(command string) (string, error) {
107         cliExecCommand := fmt.Sprintf("docker exec --detach=false %[1]s vppctl -s %[2]s %[3]s",
108                 vpp.container.name, vpp.getCliSocket(), command)
109         output, err := exechelper.CombinedOutput(cliExecCommand)
110         if err != nil {
111                 return "", fmt.Errorf("vppctl failed: %s", err)
112         }
113
114         return string(output), nil
115 }
116
117 func NewVppInstance(c *Container) *VppInstance {
118         var vppConfig VppConfig
119         vppConfig.CliSocketFilePath = defaultCliSocketFilePath
120         vpp := new(VppInstance)
121         vpp.container = c
122         vpp.config = vppConfig
123         return vpp
124 }
125
126 func serializeVppConfig(vppConfig VppConfig) (string, error) {
127         serializedConfig, err := json.Marshal(vppConfig)
128         if err != nil {
129                 return "", fmt.Errorf("vpp start failed: serializing configuration failed: %s", err)
130         }
131         return string(serializedConfig), nil
132 }
133
134 func deserializeVppConfig(input string) (VppConfig, error) {
135         var vppConfig VppConfig
136         err := json.Unmarshal([]byte(input), &vppConfig)
137         if err != nil {
138                 // Since input is not a  valid JSON it is going be used as a variant value
139                 // for compatibility reasons
140                 vppConfig.Variant = input
141                 vppConfig.CliSocketFilePath = defaultCliSocketFilePath
142         }
143         return vppConfig, nil
144 }