Skip to content

Commit ad38fcb

Browse files
authored
Merge pull request #955 from ellemouton/sql8Accounts8
[sql-8]: run itests against all DB types
2 parents a06bade + 5eba328 commit ad38fcb

File tree

8 files changed

+239
-15
lines changed

8 files changed

+239
-15
lines changed

.github/workflows/main.yml

+13-2
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,17 @@ jobs:
275275
itest:
276276
name: integration test
277277
runs-on: ubuntu-latest
278+
strategy:
279+
# Allow other tests in the matrix to continue if one fails.
280+
fail-fast: false
281+
matrix:
282+
include:
283+
- name: bbolt
284+
args: dbbackend=bbolt
285+
- name: sqlite
286+
args: dbbackend=sqlite
287+
- name: postgres
288+
args: dbbackend=postgres
278289
steps:
279290
- name: git checkout
280291
uses: actions/checkout@v4
@@ -295,8 +306,8 @@ jobs:
295306
working-directory: ./app
296307
run: yarn
297308

298-
- name: run check
299-
run: make itest
309+
- name: run itest ${{ matrix.name }}
310+
run: make itest ${{ matrix.args }}
300311

301312
- name: Zip log files on failure
302313
if: ${{ failure() }}

.golangci.yml

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ run:
1111
- watchtowerrpc
1212
- neutrinorpc
1313
- peersrpc
14+
- dev
1415

1516
linters-settings:
1617
govet:

config.go

+15-2
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,13 @@ type Config struct {
237237
// over an in-memory connection on startup. This is only set in
238238
// integrated lnd mode.
239239
lndAdminMacaroon []byte
240+
241+
// DevConfig is a config struct that is empty if lit is built without
242+
// the `dev` flag (in other words when it is build for a production
243+
// environment). This allows us to have config values that are then
244+
// only available in development mode which lets us run itests against
245+
// features not yet available in production.
246+
*DevConfig
240247
}
241248

242249
// lndConnectParams returns the connection parameters to connect to the local
@@ -337,8 +344,9 @@ func defaultConfig() *Config {
337344
Autopilot: &autopilotserver.Config{
338345
PingCadence: time.Hour,
339346
},
340-
Firewall: firewall.DefaultConfig(),
341-
Accounts: &accounts.Config{},
347+
Firewall: firewall.DefaultConfig(),
348+
Accounts: &accounts.Config{},
349+
DevConfig: defaultDevConfig(),
342350
}
343351
}
344352

@@ -467,6 +475,11 @@ func loadAndValidateConfig(interceptor signal.Interceptor) (*Config, error) {
467475
)
468476
}
469477

478+
err = cfg.DevConfig.Validate(litDir, cfg.Network)
479+
if err != nil {
480+
return nil, err
481+
}
482+
470483
// Initiate our listeners. For now, we only support listening on one
471484
// port at a time because we can only pass in one pre-configured RPC
472485
// listener into lnd.

config_dev.go

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
//go:build dev
2+
3+
package terminal
4+
5+
import (
6+
"path/filepath"
7+
8+
"github.com/lightninglabs/lightning-terminal/accounts"
9+
"github.com/lightninglabs/lightning-terminal/db"
10+
"github.com/lightningnetwork/lnd/clock"
11+
)
12+
13+
const (
14+
// DatabaseBackendSqlite is the name of the SQLite database backend.
15+
DatabaseBackendSqlite = "sqlite"
16+
17+
// DatabaseBackendPostgres is the name of the Postgres database backend.
18+
DatabaseBackendPostgres = "postgres"
19+
20+
// DatabaseBackendBbolt is the name of the bbolt database backend.
21+
DatabaseBackendBbolt = "bbolt"
22+
23+
// defaultSqliteDatabaseFileName is the default name of the SQLite
24+
// database file.
25+
defaultSqliteDatabaseFileName = "litd.db"
26+
)
27+
28+
// defaultSqliteDatabasePath is the default path under which we store
29+
// the SQLite database file.
30+
var defaultSqliteDatabasePath = filepath.Join(
31+
DefaultLitDir, DefaultNetwork, defaultSqliteDatabaseFileName,
32+
)
33+
34+
// DevConfig is a struct that holds the configuration options for a development
35+
// environment. The purpose of this struct is to hold config options for
36+
// features not yet available in production. Since our itests are built with
37+
// the dev tag, we can test these features in our itests.
38+
//
39+
// nolint:lll
40+
type DevConfig struct {
41+
// DatabaseBackend is the database backend we will use for storing all
42+
// account related data. While this feature is still in development, we
43+
// include the bbolt type here so that our itests can continue to be
44+
// tested against a bbolt backend. Once the full bbolt to SQL migration
45+
// is complete, however, we will remove the bbolt option.
46+
DatabaseBackend string `long:"databasebackend" description:"The database backend to use for storing all account related data." choice:"bbolt" choice:"sqlite" choice:"postgres"`
47+
48+
// Sqlite holds the configuration options for a SQLite database
49+
// backend.
50+
Sqlite *db.SqliteConfig `group:"sqlite" namespace:"sqlite"`
51+
52+
// Postgres holds the configuration options for a Postgres database
53+
Postgres *db.PostgresConfig `group:"postgres" namespace:"postgres"`
54+
}
55+
56+
// Validate checks that all the values set in our DevConfig are valid and uses
57+
// the passed parameters to override any defaults if necessary.
58+
func (c *DevConfig) Validate(dbDir, network string) error {
59+
// We'll update the database file location if it wasn't set.
60+
if c.Sqlite.DatabaseFileName == defaultSqliteDatabasePath {
61+
c.Sqlite.DatabaseFileName = filepath.Join(
62+
dbDir, network, defaultSqliteDatabaseFileName,
63+
)
64+
}
65+
66+
return nil
67+
}
68+
69+
// defaultDevConfig returns a new DevConfig with default values set.
70+
func defaultDevConfig() *DevConfig {
71+
return &DevConfig{
72+
Sqlite: &db.SqliteConfig{
73+
DatabaseFileName: defaultSqliteDatabasePath,
74+
},
75+
Postgres: &db.PostgresConfig{
76+
Host: "localhost",
77+
Port: 5432,
78+
MaxOpenConnections: 10,
79+
},
80+
}
81+
}
82+
83+
// NewAccountStore creates a new account store based on the chosen database
84+
// backend.
85+
func NewAccountStore(cfg *Config, clock clock.Clock) (accounts.Store, error) {
86+
switch cfg.DatabaseBackend {
87+
case DatabaseBackendSqlite:
88+
// Before we initialize the SQLite store, we'll make sure that
89+
// the directory where we will store the database file exists.
90+
networkDir := filepath.Join(cfg.LitDir, cfg.Network)
91+
err := makeDirectories(networkDir)
92+
if err != nil {
93+
return nil, err
94+
}
95+
96+
sqlStore, err := db.NewSqliteStore(cfg.Sqlite)
97+
if err != nil {
98+
return nil, err
99+
}
100+
101+
return accounts.NewSQLStore(sqlStore.BaseDB, clock), nil
102+
103+
case DatabaseBackendPostgres:
104+
sqlStore, err := db.NewPostgresStore(cfg.Postgres)
105+
if err != nil {
106+
return nil, err
107+
}
108+
109+
return accounts.NewSQLStore(sqlStore.BaseDB, clock), nil
110+
111+
default:
112+
return accounts.NewBoltStore(
113+
filepath.Dir(cfg.MacaroonPath), accounts.DBFilename,
114+
clock,
115+
)
116+
}
117+
}

config_prod.go

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//go:build !dev
2+
3+
package terminal
4+
5+
import (
6+
"path/filepath"
7+
8+
"github.com/lightninglabs/lightning-terminal/accounts"
9+
"github.com/lightningnetwork/lnd/clock"
10+
)
11+
12+
// DevConfig is an empty shell struct that allows us to build without the dev
13+
// tag. This struct is embedded in the main Config struct, and it adds no new
14+
// functionality in a production build.
15+
type DevConfig struct{}
16+
17+
// defaultDevConfig returns an empty DevConfig struct.
18+
func defaultDevConfig() *DevConfig {
19+
return &DevConfig{}
20+
}
21+
22+
// Validate is a no-op function during a production build.
23+
func (c *DevConfig) Validate(_, _ string) error {
24+
return nil
25+
}
26+
27+
// NewAccountStore creates a new account store using the default Bolt backend
28+
// since in production, this is the only backend supported currently.
29+
func NewAccountStore(cfg *Config, clock clock.Clock) (accounts.Store, error) {
30+
return accounts.NewBoltStore(
31+
filepath.Dir(cfg.MacaroonPath), accounts.DBFilename, clock,
32+
)
33+
}

itest/litd_node.go

+45-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"encoding/hex"
99
"encoding/json"
1010
"errors"
11+
"flag"
1112
"fmt"
1213
"io"
1314
"io/ioutil"
@@ -25,6 +26,7 @@ import (
2526
"github.com/btcsuite/btcd/wire"
2627
"github.com/lightninglabs/faraday/frdrpc"
2728
terminal "github.com/lightninglabs/lightning-terminal"
29+
"github.com/lightninglabs/lightning-terminal/db"
2830
"github.com/lightninglabs/lightning-terminal/litrpc"
2931
"github.com/lightninglabs/lightning-terminal/subservers"
3032
"github.com/lightninglabs/loop/looprpc"
@@ -60,7 +62,12 @@ var (
6062
numActiveNodes = 0
6163
numActiveNodesMtx sync.Mutex
6264

63-
defaultLndPassphrase = []byte("default-wallet-password")
65+
// litDBBackend is a command line flag for specifying the database
66+
// backend to use when starting a LiT daemon.
67+
litDBBackend = flag.String(
68+
"litdbbackend", terminal.DatabaseBackendBbolt, "Set the "+
69+
"database backend to use when starting a LiT daemon.",
70+
)
6471
)
6572

6673
type LitNodeConfig struct {
@@ -80,6 +87,9 @@ type LitNodeConfig struct {
8087
LitTLSCertPath string
8188
LitMacPath string
8289

90+
DBBackend string
91+
PostgresConfig *db.PostgresConfig
92+
8393
UIPassword string
8494
LitDir string
8595
FaradayDir string
@@ -220,8 +230,20 @@ func (cfg *LitNodeConfig) defaultLitdArgs() *litArgs {
220230
"restcors": "*",
221231
"lnd.debuglevel": "trace,GRPC=error,PEER=info",
222232
"lndconnectinterval": "200ms",
233+
"databasebackend": cfg.DBBackend,
223234
}
224235
)
236+
237+
if cfg.DBBackend == terminal.DatabaseBackendPostgres {
238+
args["postgres.host"] = cfg.PostgresConfig.Host
239+
args["postgres.port"] = fmt.Sprintf(
240+
"%d", cfg.PostgresConfig.Port,
241+
)
242+
args["postgres.user"] = cfg.PostgresConfig.User
243+
args["postgres.password"] = cfg.PostgresConfig.Password
244+
args["postgres.dbname"] = cfg.PostgresConfig.DBName
245+
}
246+
225247
for _, arg := range cfg.LitArgs {
226248
parts := strings.Split(arg, "=")
227249
option := strings.TrimLeft(parts[0], "--")
@@ -417,6 +439,28 @@ func NewNode(t *testing.T, cfg *LitNodeConfig,
417439
cfg.LitTLSCertPath = filepath.Join(cfg.LitDir, "tls.cert")
418440
cfg.GenerateListeningPorts()
419441

442+
// Decide which DB backend to use.
443+
switch *litDBBackend {
444+
case terminal.DatabaseBackendSqlite:
445+
cfg.DBBackend = terminal.DatabaseBackendSqlite
446+
447+
case terminal.DatabaseBackendPostgres:
448+
fixture := db.NewTestPgFixture(
449+
t, db.DefaultPostgresFixtureLifetime, true,
450+
)
451+
t.Cleanup(func() {
452+
fixture.TearDown(t)
453+
})
454+
455+
cfg.DBBackend = terminal.DatabaseBackendPostgres
456+
cfg.PostgresConfig = fixture.GetConfig()
457+
458+
default:
459+
cfg.DBBackend = terminal.DatabaseBackendBbolt
460+
}
461+
462+
t.Logf("Using %v database backend", cfg.DBBackend)
463+
420464
// Generate a random UI password by reading 16 random bytes and base64
421465
// encoding them.
422466
var randomBytes [16]byte

make/testing_flags.mk

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
include make/compile_flags.mk
22

3-
ITEST_FLAGS =
43
TEST_FLAGS =
54
DEV_TAGS = dev
65

@@ -9,6 +8,11 @@ ifneq ($(icase),)
98
ITEST_FLAGS += -test.run="TestLightningTerminal/$(icase)"
109
endif
1110

11+
# Run itests with specified db backend.
12+
ifneq ($(dbbackend),)
13+
ITEST_FLAGS += -litdbbackend=$(dbbackend)
14+
endif
15+
1216
# If a specific unit test case is being targeted, construct test.run filter.
1317
ifneq ($(case),)
1418
TEST_FLAGS += -test.run=$(case)

terminal.go

+10-9
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ type LightningTerminal struct {
216216
middleware *mid.Manager
217217
middlewareStarted bool
218218

219-
accountsStore *accounts.BoltStore
219+
accountsStore accounts.Store
220220
accountService *accounts.InterceptorService
221221
accountServiceStarted bool
222222

@@ -415,10 +415,14 @@ func (g *LightningTerminal) start(ctx context.Context) error {
415415
)
416416
}
417417

418-
g.accountsStore, err = accounts.NewBoltStore(
419-
filepath.Dir(g.cfg.MacaroonPath), accounts.DBFilename,
420-
clock.NewDefaultClock(),
421-
)
418+
networkDir := filepath.Join(g.cfg.LitDir, g.cfg.Network)
419+
err = makeDirectories(networkDir)
420+
if err != nil {
421+
return fmt.Errorf("could not create network directory: %v", err)
422+
}
423+
424+
clock := clock.NewDefaultClock()
425+
g.accountsStore, err = NewAccountStore(g.cfg, clock)
422426
if err != nil {
423427
return fmt.Errorf("error creating accounts store: %w", err)
424428
}
@@ -445,10 +449,7 @@ func (g *LightningTerminal) start(ctx context.Context) error {
445449
g.ruleMgrs = rules.NewRuleManagerSet()
446450

447451
// Create an instance of the local Terminal Connect session store DB.
448-
networkDir := filepath.Join(g.cfg.LitDir, g.cfg.Network)
449-
g.sessionDB, err = session.NewDB(
450-
networkDir, session.DBFilename, clock.NewDefaultClock(),
451-
)
452+
g.sessionDB, err = session.NewDB(networkDir, session.DBFilename, clock)
452453
if err != nil {
453454
return fmt.Errorf("error creating session DB: %v", err)
454455
}

0 commit comments

Comments
 (0)