Skip to content

Commit 15ccc09

Browse files
committed
itest: make Litd arguments configurable on restart
Add new `WithoutLitArg` and `WithLitArg` functional options that can be passed to `GenArgs` when a node is being restarted. This makes it easy to change the arguments of a node on restart.
1 parent 0ec9508 commit 15ccc09

File tree

2 files changed

+122
-38
lines changed

2 files changed

+122
-38
lines changed

itest/litd_node.go

Lines changed: 118 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -103,63 +103,146 @@ func (cfg *LitNodeConfig) GenerateListeningPorts() {
103103
}
104104
}
105105

106+
// litArgs holds a key-value map of config option to config value. An empty
107+
// string value means that the config option is a boolean.
108+
type litArgs struct {
109+
args map[string]string
110+
111+
mu sync.Mutex
112+
}
113+
114+
// deleteArg deletes the argument with the given name from the set if it is
115+
// present.
116+
func (l *litArgs) deleteArg(argName string) {
117+
l.mu.Lock()
118+
defer l.mu.Unlock()
119+
120+
delete(l.args, argName)
121+
}
122+
123+
// addArg adds a new argument to the set. An empty value string will mean that
124+
// the key will be added as a boolean flag.
125+
func (l *litArgs) addArg(name, value string) {
126+
l.mu.Lock()
127+
defer l.mu.Unlock()
128+
129+
l.args[name] = value
130+
}
131+
132+
// toArgList converts the litArgs map to an arguments string slice.
133+
func (l *litArgs) toArgList() []string {
134+
l.mu.Lock()
135+
defer l.mu.Unlock()
136+
137+
args := make([]string, 0, len(l.args))
138+
for arg, setting := range l.args {
139+
if setting == "" {
140+
args = append(args, fmt.Sprintf("--%s", arg))
141+
continue
142+
}
143+
144+
args = append(args, fmt.Sprintf("--%s=%s", arg, setting))
145+
}
146+
147+
return args
148+
}
149+
150+
// LitArgOption defines the signature of a functional option that can be used
151+
// to tweak the default arguments of a Litd node.
152+
type LitArgOption func(args *litArgs)
153+
154+
// WithoutLitArg can be used to delete a litd config option.
155+
func WithoutLitArg(arg string) LitArgOption {
156+
return func(args *litArgs) {
157+
args.deleteArg(arg)
158+
}
159+
}
160+
161+
// WithLitArg can be used to set a Litd config option. An empty value string
162+
// will mean that the key will be added as a boolean flag.
163+
func WithLitArg(key, value string) LitArgOption {
164+
return func(args *litArgs) {
165+
args.addArg(key, value)
166+
}
167+
}
168+
106169
// GenArgs generates a slice of command line arguments from the lightning node
107170
// config struct.
108-
func (cfg *LitNodeConfig) GenArgs() []string {
171+
func (cfg *LitNodeConfig) GenArgs(opts ...LitArgOption) []string {
172+
args := cfg.defaultLitdArgs()
173+
174+
for _, opt := range opts {
175+
opt(args)
176+
}
177+
178+
return args.toArgList()
179+
}
180+
181+
// defaultLitArgs generates the default arguments to be used with a Litd node.
182+
func (cfg *LitNodeConfig) defaultLitdArgs() *litArgs {
109183
var (
110-
litArgs = []string{
111-
fmt.Sprintf("--httpslisten=%s", cfg.LitAddr()),
112-
fmt.Sprintf("--insecure-httplisten=%s", cfg.LitRESTAddr()),
113-
fmt.Sprintf("--lit-dir=%s", cfg.LitDir),
114-
fmt.Sprintf("--faraday.faradaydir=%s", cfg.FaradayDir),
115-
fmt.Sprintf("--loop.loopdir=%s", cfg.LoopDir),
116-
fmt.Sprintf("--pool.basedir=%s", cfg.PoolDir),
117-
fmt.Sprintf("--uipassword=%s", cfg.UIPassword),
118-
"--enablerest",
119-
"--restcors=*",
184+
args = map[string]string{
185+
"httpslisten": cfg.LitAddr(),
186+
"insecure-httplisten": cfg.LitRESTAddr(),
187+
"lit-dir": cfg.LitDir,
188+
"faraday.faradaydir": cfg.FaradayDir,
189+
"loop.loopdir": cfg.LoopDir,
190+
"pool.basedir": cfg.PoolDir,
191+
"uipassword": cfg.UIPassword,
192+
"enablerest": "",
193+
"restcors": "*",
120194
}
121195
)
122-
litArgs = append(litArgs, cfg.LitArgs...)
196+
for _, arg := range cfg.LitArgs {
197+
parts := strings.Split(arg, "=")
198+
option := strings.TrimLeft(parts[0], "--")
199+
switch len(parts) {
200+
case 1:
201+
args[option] = ""
202+
case 2:
203+
args[option] = parts[1]
204+
}
205+
}
123206

124207
switch cfg.NetParams {
125208
case &chaincfg.TestNet3Params:
126-
litArgs = append(litArgs, "--network=testnet")
209+
args["network"] = "testnet"
127210
case &chaincfg.SimNetParams:
128-
litArgs = append(litArgs, "--network=simnet")
211+
args["network"] = "simnet"
129212
case &chaincfg.RegressionNetParams:
130-
litArgs = append(litArgs, "--network=regtest")
213+
args["network"] = "regtest"
131214
}
132215

133216
// In remote mode, we don't need any lnd specific arguments other than
134217
// those we need to connect.
135218
if cfg.RemoteMode {
136-
litArgs = append(litArgs, "--lnd-mode=remote")
137-
litArgs = append(litArgs, fmt.Sprintf(
138-
"--remote.lnd.rpcserver=%s", cfg.RPCAddr()),
139-
)
140-
litArgs = append(litArgs, fmt.Sprintf(
141-
"--remote.lnd.tlscertpath=%s", cfg.TLSCertPath),
142-
)
143-
litArgs = append(litArgs, fmt.Sprintf(
144-
"--remote.lnd.macaroonpath=%s", cfg.AdminMacPath),
145-
)
219+
args["lnd-mode"] = "remote"
220+
args["remote.lnd.rpcserver"] = cfg.RPCAddr()
221+
args["remote.lnd.tlscertpath"] = cfg.TLSCertPath
222+
args["remote.lnd.macaroonpath"] = cfg.AdminMacPath
146223

147-
return litArgs
224+
return &litArgs{args: args}
148225
}
149226

150227
// All arguments so far were for lnd. Let's namespace them now so we can
151228
// add args for the other daemons and LiT itself afterwards.
152-
litArgs = append(litArgs, cfg.LitArgs...)
153-
litArgs = append(litArgs, "--lnd-mode=integrated")
229+
args["lnd-mode"] = "integrated"
230+
154231
lndArgs := cfg.BaseNodeConfig.GenArgs()
155232
for idx := range lndArgs {
156-
litArgs = append(
157-
litArgs,
158-
strings.ReplaceAll(lndArgs[idx], "--", "--lnd."),
159-
)
233+
arg := strings.ReplaceAll(lndArgs[idx], "--", "--lnd.")
234+
235+
parts := strings.Split(arg, "=")
236+
option := strings.TrimLeft(parts[0], "--")
237+
switch len(parts) {
238+
case 1:
239+
args[option] = ""
240+
case 2:
241+
args[option] = parts[1]
242+
}
160243
}
161244

162-
return litArgs
245+
return &litArgs{args: args}
163246
}
164247

165248
// policyUpdateMap defines a type to store channel policy updates. It has the
@@ -456,11 +539,11 @@ func renameFile(fromFileName, toFileName string) {
456539
// This may not clean up properly if an error is returned, so the caller should
457540
// call shutdown() regardless of the return value.
458541
func (hn *HarnessNode) start(litdBinary string, litdError chan<- error,
459-
wait bool) error {
542+
wait bool, litArgOpts ...LitArgOption) error {
460543

461544
hn.quit = make(chan struct{})
462545

463-
args := hn.Cfg.GenArgs()
546+
args := hn.Cfg.GenArgs(litArgOpts...)
464547
hn.cmd = exec.Command(litdBinary, args...)
465548

466549
// Redirect stderr output to buffer

itest/network_harness.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -606,9 +606,10 @@ func (n *NetworkHarness) DisconnectNodes(a, b *HarnessNode) error {
606606
// pass a set of SCBs to pass in via the Unlock method allowing them to restore
607607
// channels during restart.
608608
func (n *NetworkHarness) RestartNode(node *HarnessNode, callback func() error,
609+
litArgOpts []LitArgOption,
609610
chanBackups ...*lnrpc.ChanBackupSnapshot) error {
610611

611-
err := n.RestartNodeNoUnlock(node, callback, true)
612+
err := n.RestartNodeNoUnlock(node, callback, true, litArgOpts...)
612613
if err != nil {
613614
return err
614615
}
@@ -646,7 +647,7 @@ func (n *NetworkHarness) RestartNode(node *HarnessNode, callback func() error,
646647
// the callback parameter is non-nil, then the function will be executed after
647648
// the node shuts down, but *before* the process has been started up again.
648649
func (n *NetworkHarness) RestartNodeNoUnlock(node *HarnessNode,
649-
callback func() error, wait bool) error {
650+
callback func() error, wait bool, litArgOpts ...LitArgOption) error {
650651

651652
if err := node.stop(); err != nil {
652653
return err
@@ -658,7 +659,7 @@ func (n *NetworkHarness) RestartNodeNoUnlock(node *HarnessNode,
658659
}
659660
}
660661

661-
return node.start(n.litdBinary, n.lndErrorChan, wait)
662+
return node.start(n.litdBinary, n.lndErrorChan, wait, litArgOpts...)
662663
}
663664

664665
// SuspendNode stops the given node and returns a callback that can be used to

0 commit comments

Comments
 (0)