This repository has been archived by the owner on Jan 19, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathtestcmd.go
321 lines (294 loc) · 12.5 KB
/
testcmd.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
package main
import (
"fmt"
"io/ioutil"
"os/exec"
"strings"
log "github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
)
var (
// qctl test contract --private node1
testContractCmd = cli.Command{
Name: "contract",
Aliases: []string{"contracts"},
Usage: "deploy the test contract(s) on a node.",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "both",
Usage: "try to deploy a public and private test contract to the node.",
Value: true,
},
&cli.BoolFlag{
Name: "private",
Aliases: []string{"priv"},
Usage: "try to deploy a private test contract to the node.",
},
&cli.BoolFlag{
Name: "public",
Aliases: []string{"pub"},
Usage: "try to deploy a public test contract to the node.",
},
},
Action: func(c *cli.Context) error {
if c.Args().Len() < 1 {
c.App.Run([]string{"test", "help", "contract"})
return cli.Exit("wrong number of arguments", 2)
}
nodeName := c.Args().First()
namespace := c.String("namespace")
podName := podNameFromPrefix(nodeName, namespace)
fmt.Println(fmt.Sprintf("running test contract(s) on node [%s] pod [%s]", nodeName, podName))
isBothTest := c.Bool("both")
isPrivTest := c.Bool("private")
isPublicTest := c.Bool("public")
// if either of the specific priv or pub flags are set, only run the specified flags.
if isPrivTest || isPublicTest {
isBothTest = false
}
var cmd *exec.Cmd
// test private tx
if isPrivTest || isBothTest {
fmt.Println()
green.Println(" Trying to deploy the test private contract...")
cmd = exec.Command("kubectl", "--namespace="+namespace, "exec", "-it", podName, "-c", "quorum", "--", "/etc/quorum/qdata/contracts/runscript.sh", "/etc/quorum/qdata/contracts/private_contract.js")
dropIntoCmd(cmd)
}
// test public tx
if isPublicTest || isBothTest {
fmt.Println()
green.Println(" Trying to deploy the test public contract...")
cmd = exec.Command("kubectl", "--namespace="+namespace, "exec", "-it", podName, "-c", "quorum", "--", "/etc/quorum/qdata/contracts/runscript.sh", "/etc/quorum/qdata/contracts/public_contract.js")
dropIntoCmd(cmd)
}
return nil
},
}
// qctl test accepttest --node-ip=$(minikube ip)
acceptanceWriteConfigCmd = cli.Command{
Name: "accepttest",
Usage: "output the acceptance test config file",
Aliases: []string{"ac"},
Flags: []cli.Flag{
&cli.StringFlag{
Name: "config, c",
Usage: "Load configuration from `FULL_PATH_FILE`",
EnvVars: []string{"QUBE_CONFIG"},
Required: true,
},
&cli.StringFlag{
Name: "k8sdir",
Usage: "k8sdir where the resources are stored, acceptance test config stored here for now.",
EnvVars: []string{"QUBE_K8S_DIR"},
Required: true,
},
&cli.StringFlag{
Name: "node-ip",
Usage: "the IP of the K8s node, e.g. minikube ip ",
Value: "K8S_NODE_IP",
},
},
Action: func(c *cli.Context) error {
k8sNodeIp := c.String("node-ip")
// TODO: abstract out config check used everywhere
configFile := c.String("config")
k8sdir := c.String("k8sdir")
// get the current directory path, we'll use this in case the config file passed in was a relative path.
pwdCmd := exec.Command("pwd")
b, _ := runCmd(pwdCmd)
pwd := strings.TrimSpace(b.String())
if configFile == "" {
c.App.Run([]string{"qctl", "help", "accepttest"})
// QUBE_CONFIG or flag
fmt.Println()
fmt.Println()
red.Println(" --config flag must be provided.")
red.Println(" or ")
red.Println(" QUBE_CONFIG environment variable needs to be set to your config file.")
fmt.Println()
red.Println(" If you need to generate a qubernetes.yaml config use the command: ")
fmt.Println()
green.Println(" qctl generate config")
fmt.Println()
return cli.Exit("--config flag must be set to the fullpath of your config file.", 3)
}
// the config file must exist or this is an error.
if fileExists(configFile) {
// check if config file is full path or relative path.
if !strings.HasPrefix(configFile, "/") {
configFile = pwd + "/" + configFile
}
} else {
c.App.Run([]string{"qctl", "help", "init"})
return cli.Exit(fmt.Sprintf("ConfigFile must exist! Given configFile [%v]", configFile), 3)
}
configFileYaml, err := LoadYamlConfig(configFile)
if err != nil {
log.Fatal("config file [%v] could not be loaded into the valid qubernetes yaml. err: [%v]", configFile, err)
}
acceptanceTestYaml := createAcceptanceTestConfigString(configFileYaml, k8sNodeIp)
fmt.Println(acceptanceTestYaml)
//fmt.Println(config.ToString())
configBytes := []byte(acceptanceTestYaml)
acceptanceTestYamlFile := k8sdir + "/config/application-qctl-generated.yml"
// try writing the generated file out to disk this file will be used to initialize the network.
// TODO: it might be best to store in K8s itself
err = ioutil.WriteFile(acceptanceTestYamlFile, configBytes, 0644)
if err != nil {
log.Fatal("error writing acceptanceTestYamlFil to [%v]. err: [%v]", acceptanceTestYamlFile, err)
}
return nil
},
}
// qctl test accepttest --node-ip=$(minikube ip)
// docker run --rm -v $(pwd):/tmp/config -e "SPRING_CONFIG_ADDITIONALLOCATION=file:/tmp/config/" -e "SPRING_PROFILES_ACTIVE=${PROFILE}" quorumengineering/acctests:latest test -Dtags="basic && !externally-signed && !personal-api-signed && !eth-api-signed"
acceptanceTestRunCmd = cli.Command{
Name: "accepttest",
Aliases: []string{"accepttests, acceptancetest, acceptancetests"},
Usage: "run the acceptance tests.",
// TODO: pass in tags, and the config file, will also need the k8s ip...unless
// additionally pass in the file, and the tags, then no additional config needed
Flags: []cli.Flag{
&cli.StringFlag{
Name: "config, c",
Usage: "Load configuration from `FULL_PATH_FILE`",
EnvVars: []string{"QUBE_CONFIG"},
Required: true,
},
&cli.StringFlag{
Name: "k8sdir",
Usage: "k8sdir where the resources are stored, acceptance test config stored here for now.",
EnvVars: []string{"QUBE_K8S_DIR"},
Required: true,
},
&cli.StringFlag{
Name: "node-ip",
Usage: "the IP of the K8s node, e.g. minikube ip ",
Value: "K8S_NODE_IP",
Required: true,
},
&cli.StringFlag{
Name: "tags",
Aliases: []string{"t", "tag"},
Usage: "tags indicating which test to run, if not set, defaults to: (basic || basic-{CONSENSUS} || networks/typical::{CONSENSUS}) && !extension ",
},
},
Action: func(c *cli.Context) error {
k8sdir := c.String("k8sdir")
k8sNodeIp := c.String("node-ip")
if k8sdir == "" {
c.App.Run([]string{"qctl", "help", "accepttest"})
// QUBE_CONFIG or flag
fmt.Println()
fmt.Println()
red.Println(" --k8sdir flag must be provided.")
red.Println(" or ")
red.Println(" QUBE_K8S_DIR environment variable needs to be set to your k8sdir.")
fmt.Println()
}
// TODO: abstract out config check used everywhere
configFile := c.String("config")
// V1 keep the file on a known place on disc
// acceptanceTestYaml := k8sdir + "/config/application-qctl-generated.yml"
// end V1
configFileYaml, err := LoadYamlConfig(configFile)
if err != nil {
log.Fatal("config file [%v] could not be loaded into the valid qubernetes yaml. err: [%v]", configFile, err)
}
// acceptance test file must be prefixed with application, e.g. `application-$MYNAME.yaml`
// if an acceptance test config file wasn't provided, create one against the running network now.
acceptanceTestYaml := createAcceptanceTestConfigString(configFileYaml, k8sNodeIp)
configBytes := []byte(acceptanceTestYaml)
// try writing the generated file out to disk this file will be used to initialize the network.
// TODO: it might be best to store in K8s itself
acceptanceTestYamlFile := k8sdir + "/config/application-qctl-generated.yml"
err = ioutil.WriteFile(acceptanceTestYamlFile, configBytes, 0644)
if err != nil {
log.Fatal("error writing acceptanceTestYamlFil to [%v]. err: [%v]", acceptanceTestYamlFile, err)
}
acceptanceTestProfile := "qctl-generated"
// Depending on the consensus (raft or istanbul) of the network, set the tags accordingly.
tags := c.String("tags")
if tags == "" {
if configFileYaml.Genesis.Consensus == RaftConsensus {
tags = "(basic || basic-raft || networks/typical::raft) && !extension"
} else {
tags = "(basic || basic-istanbul || networks/typical::istanbul) && !extension"
}
}
green.Println("using profile file: " + acceptanceTestYamlFile)
// if debugging include -X for mvn output
cmd := exec.Command("docker", "run", "--rm", "-v", k8sdir+"/config:/tmp/config", "-e", "SPRING_CONFIG_ADDITIONALLOCATION=file:/tmp/config/", "-e", "SPRING_PROFILES_ACTIVE="+acceptanceTestProfile, "quorumengineering/acctests:latest", "test", "-Dtags="+tags)
// e.g. docker run --rm -v /Users/libby/Workspace.Quorum/qctl-config/out/config:/tmp/config -e SPRING_CONFIG_ADDITIONALLOCATION=file:/tmp/config/ -e SPRING_PROFILES_ACTIVE=qctl-generated quorumengineering/acctests:latest test -Dtags='(basic || basic-istanbul || networks/typical::istanbul) && !extension'
fmt.Println(cmd)
err = dropIntoCmd(cmd)
if err != nil {
fmt.Println()
red.Println(fmt.Sprintf("Error running trying to run acceptance test via the quorumengineering/acctests container ."))
red.Println(fmt.Sprintf("Command that failed:"))
red.Println(fmt.Sprintf(cmd.String()))
red.Println(fmt.Sprintf("Is Docker running on your machine? [%v]", err))
fmt.Println()
return cli.Exit(fmt.Sprintf("Docker must be running on host, cmd failed \n %v", cmd.String()), 3)
}
return nil
},
}
)
// acceptance test expects a config file with node names labelled in sequential order, Node1, Node2:
//quorum:
//nodes:
//Node1:
// privacy-address: WC6yWjDXG9uFQTTfV+bkTr5GbqjmH7DotcOYqeSajgs=
// url: http://192.168.64.49:32507
// third-party-url: http://192.168.64.49:31375
//Node2:
// privacy-address: t+lu+T9VoTWfQMyF7wiFsiEKARaQqgvOJynNfrsSbAk=
// url: http://192.168.64.49:32106
// third-party-url: http://192.168.64.49:30968
//
// TODO: can we update the format to use unique names, and yaml lists.
//quorum:
// nodes:
// - name: quorum-node1
// privacy-address: WC6yWjDXG9uFQTTfV+bkTr5GbqjmH7DotcOYqeSajgs=
// url: http://192.168.64.49:32507
// third-party-url: http://192.168.64.49:31375
// - name: quorum-node2
// privacy-address: t+lu+T9VoTWfQMyF7wiFsiEKARaQqgvOJynNfrsSbAk=
// url: http://192.168.64.49:32106
// third-party-url: http://192.168.64.49:30968
func createAcceptanceTestConfigString(configFileYaml QConfig, k8sNodeIp string) string {
acceptanceTestYaml := AcceptTestConfig{}
for _, node := range configFileYaml.Nodes {
// get nodes from config, and set the necessary tm public key, geth and tessera urls, using NodePort.
serviceNodePort := serviceInfoByPrefix(node.NodeUserIdent, ServiceTypeNodePort, "")
tmPublicKey := getTmPublicKey(node.NodeUserIdent)
nodeEntry := ATNodeEntry{}
nodeEntry.GethURL = "http://" + k8sNodeIp + ":" + serviceNodePort.NodePortGeth
nodeEntry.TmPublicKey = tmPublicKey
nodeEntry.TmURL = "http://" + k8sNodeIp + ":" + serviceNodePort.NodePortTm
acceptanceTestYaml.Quorum.Nodes = append(acceptanceTestYaml.Quorum.Nodes, nodeEntry)
}
// TODO this is really hideous, better to change the acceptance test to take a yaml file that has a list of node with a name attributes:
//quorum:
// nodes:
// - name: node1
// privacy-address: WC6yWjDXG9uFQTTfV+bkTr5GbqjmH7DotcOYqeSajgs=
// url: http://192.168.64.49:32507
// third-party-url: http://192.168.64.49:31375
// - name: node2
// privacy-address: t+lu+T9VoTWfQMyF7wiFsiEKARaQqgvOJynNfrsSbAk=
// url: http://192.168.64.49:32106
// third-party-url: http://192.168.64.49:30968
acceptanceTestUpdatedYaml := acceptanceTestYaml.ToString()
// since node name must be in the for form Node(i+1)
for i := 0; i < len(configFileYaml.Nodes); i++ {
//acceptanceTestUpdatedYaml = strings.Replace(acceptanceTestUpdatedYaml, "- privacy-address:", " " + node.NodeUserIdent + ": \n privacy-address:", 1)
nodeName := fmt.Sprintf("Node%d", i+1)
acceptanceTestUpdatedYaml = strings.Replace(acceptanceTestUpdatedYaml, "- privacy-address:", " "+nodeName+": \n privacy-address:", 1)
}
acceptanceTestUpdatedYaml = strings.ReplaceAll(acceptanceTestUpdatedYaml, " url:", " url:")
acceptanceTestUpdatedYaml = strings.ReplaceAll(acceptanceTestUpdatedYaml, "third-party-url:", " third-party-url:")
return acceptanceTestUpdatedYaml
}