Skip to content

Commit 931bda0

Browse files
RI-5929 initial implementation of pre setup databases (#4367)
* RI-5929 initial implementation of pre setup databases * RI-5929 UTests * RI-5929 ITests * RI-5929 fix the rest of ITests * RI-5929 change env name RI_REDIS_NAME -> RI_REDIS_ALIAS * RI-5929 re-generate migrations
1 parent dfd528e commit 931bda0

File tree

56 files changed

+1941
-193
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1941
-193
lines changed

redisinsight/api/config/default.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export default {
4545
defaultsDir,
4646
logs: join(homedir, 'logs'),
4747
customConfig: join(homedir, 'config.json'),
48+
preSetupDatabases: process.env.RI_PRE_SETUP_DATABASES_PATH || join(homedir, 'databases.json'),
4849
defaultPlugins: join(staticDir, 'plugins'),
4950
customPlugins: join(homedir, 'plugins'),
5051
customTutorials: join(homedir, 'custom-tutorials'),

redisinsight/api/config/production.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export default {
1212
prevHomedir,
1313
logs: join(homedir, 'logs'),
1414
customConfig: join(homedir, 'config.json'),
15+
preSetupDatabases: process.env.RI_PRE_SETUP_DATABASES_PATH || join(homedir, 'databases.json'),
1516
customPlugins: join(homedir, 'plugins'),
1617
customTutorials: join(homedir, 'custom-tutorials'),
1718
commands: join(homedir, 'commands'),

redisinsight/api/config/staging.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export default {
1212
prevHomedir,
1313
logs: join(homedir, 'logs'),
1414
customConfig: join(homedir, 'config.json'),
15+
preSetupDatabases: process.env.RI_PRE_SETUP_DATABASES_PATH || join(homedir, 'databases.json'),
1516
customPlugins: join(homedir, 'plugins'),
1617
customTutorials: join(homedir, 'custom-tutorials'),
1718
commands: join(homedir, 'commands'),
@@ -23,7 +24,7 @@ export default {
2324
process.env.RI_GUIDES_PATH || join(homedir, 'guides'),
2425
join(os.homedir(), '.redisinsight-preview-stage'),
2526
join(os.homedir(), '.redisinsight-v2-stage'),
26-
]
27+
],
2728
},
2829
server: {
2930
env: 'staging',
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { MigrationInterface, QueryRunner } from "typeorm";
2+
3+
export class PreSetupDatabases1741786803681 implements MigrationInterface {
4+
name = 'PreSetupDatabases1741786803681'
5+
6+
public async up(queryRunner: QueryRunner): Promise<void> {
7+
await queryRunner.query(`CREATE TABLE "temporary_ca_certificate" ("id" varchar PRIMARY KEY NOT NULL, "name" varchar NOT NULL, "encryption" varchar, "certificate" varchar, "isPreSetup" boolean, CONSTRAINT "UQ_23be613e4fb204fd5a66916b0b3" UNIQUE ("name"))`);
8+
await queryRunner.query(`INSERT INTO "temporary_ca_certificate"("id", "name", "encryption", "certificate") SELECT "id", "name", "encryption", "certificate" FROM "ca_certificate"`);
9+
await queryRunner.query(`DROP TABLE "ca_certificate"`);
10+
await queryRunner.query(`ALTER TABLE "temporary_ca_certificate" RENAME TO "ca_certificate"`);
11+
await queryRunner.query(`CREATE TABLE "temporary_client_certificate" ("id" varchar PRIMARY KEY NOT NULL, "name" varchar NOT NULL, "encryption" varchar, "certificate" varchar, "key" varchar, "isPreSetup" boolean, CONSTRAINT "UQ_4966cf1c0e299df01049ebd53a5" UNIQUE ("name"))`);
12+
await queryRunner.query(`INSERT INTO "temporary_client_certificate"("id", "name", "encryption", "certificate", "key") SELECT "id", "name", "encryption", "certificate", "key" FROM "client_certificate"`);
13+
await queryRunner.query(`DROP TABLE "client_certificate"`);
14+
await queryRunner.query(`ALTER TABLE "temporary_client_certificate" RENAME TO "client_certificate"`);
15+
await queryRunner.query(`CREATE TABLE "temporary_database_instance" ("id" varchar PRIMARY KEY NOT NULL, "host" varchar NOT NULL, "port" integer NOT NULL, "name" varchar NOT NULL, "username" varchar, "password" varchar, "tls" boolean, "verifyServerCert" boolean, "lastConnection" datetime, "caCertId" varchar, "clientCertId" varchar, "connectionType" varchar NOT NULL DEFAULT ('STANDALONE'), "nodes" varchar DEFAULT ('[]'), "nameFromProvider" varchar, "sentinelMasterName" varchar, "sentinelMasterUsername" varchar, "sentinelMasterPassword" varchar, "provider" varchar DEFAULT ('UNKNOWN'), "modules" varchar NOT NULL DEFAULT ('[]'), "db" integer, "encryption" varchar, "tlsServername" varchar, "new" boolean, "ssh" boolean, "timeout" integer, "compressor" varchar NOT NULL DEFAULT ('NONE'), "version" varchar, "createdAt" datetime DEFAULT (datetime('now')), "forceStandalone" boolean, "isPreSetup" boolean, CONSTRAINT "FK_d1bc747b5938e22b4b708d8e9a5" FOREIGN KEY ("caCertId") REFERENCES "ca_certificate" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_3b9b625266c00feb2d66a9f36e4" FOREIGN KEY ("clientCertId") REFERENCES "client_certificate" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)`);
16+
await queryRunner.query(`INSERT INTO "temporary_database_instance"("id", "host", "port", "name", "username", "password", "tls", "verifyServerCert", "lastConnection", "caCertId", "clientCertId", "connectionType", "nodes", "nameFromProvider", "sentinelMasterName", "sentinelMasterUsername", "sentinelMasterPassword", "provider", "modules", "db", "encryption", "tlsServername", "new", "ssh", "timeout", "compressor", "version", "createdAt", "forceStandalone") SELECT "id", "host", "port", "name", "username", "password", "tls", "verifyServerCert", "lastConnection", "caCertId", "clientCertId", "connectionType", "nodes", "nameFromProvider", "sentinelMasterName", "sentinelMasterUsername", "sentinelMasterPassword", "provider", "modules", "db", "encryption", "tlsServername", "new", "ssh", "timeout", "compressor", "version", "createdAt", "forceStandalone" FROM "database_instance"`);
17+
await queryRunner.query(`DROP TABLE "database_instance"`);
18+
await queryRunner.query(`ALTER TABLE "temporary_database_instance" RENAME TO "database_instance"`);
19+
}
20+
21+
public async down(queryRunner: QueryRunner): Promise<void> {
22+
await queryRunner.query(`ALTER TABLE "database_instance" RENAME TO "temporary_database_instance"`);
23+
await queryRunner.query(`CREATE TABLE "database_instance" ("id" varchar PRIMARY KEY NOT NULL, "host" varchar NOT NULL, "port" integer NOT NULL, "name" varchar NOT NULL, "username" varchar, "password" varchar, "tls" boolean, "verifyServerCert" boolean, "lastConnection" datetime, "caCertId" varchar, "clientCertId" varchar, "connectionType" varchar NOT NULL DEFAULT ('STANDALONE'), "nodes" varchar DEFAULT ('[]'), "nameFromProvider" varchar, "sentinelMasterName" varchar, "sentinelMasterUsername" varchar, "sentinelMasterPassword" varchar, "provider" varchar DEFAULT ('UNKNOWN'), "modules" varchar NOT NULL DEFAULT ('[]'), "db" integer, "encryption" varchar, "tlsServername" varchar, "new" boolean, "ssh" boolean, "timeout" integer, "compressor" varchar NOT NULL DEFAULT ('NONE'), "version" varchar, "createdAt" datetime DEFAULT (datetime('now')), "forceStandalone" boolean, CONSTRAINT "FK_d1bc747b5938e22b4b708d8e9a5" FOREIGN KEY ("caCertId") REFERENCES "ca_certificate" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_3b9b625266c00feb2d66a9f36e4" FOREIGN KEY ("clientCertId") REFERENCES "client_certificate" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)`);
24+
await queryRunner.query(`INSERT INTO "database_instance"("id", "host", "port", "name", "username", "password", "tls", "verifyServerCert", "lastConnection", "caCertId", "clientCertId", "connectionType", "nodes", "nameFromProvider", "sentinelMasterName", "sentinelMasterUsername", "sentinelMasterPassword", "provider", "modules", "db", "encryption", "tlsServername", "new", "ssh", "timeout", "compressor", "version", "createdAt", "forceStandalone") SELECT "id", "host", "port", "name", "username", "password", "tls", "verifyServerCert", "lastConnection", "caCertId", "clientCertId", "connectionType", "nodes", "nameFromProvider", "sentinelMasterName", "sentinelMasterUsername", "sentinelMasterPassword", "provider", "modules", "db", "encryption", "tlsServername", "new", "ssh", "timeout", "compressor", "version", "createdAt", "forceStandalone" FROM "temporary_database_instance"`);
25+
await queryRunner.query(`DROP TABLE "temporary_database_instance"`);
26+
await queryRunner.query(`ALTER TABLE "client_certificate" RENAME TO "temporary_client_certificate"`);
27+
await queryRunner.query(`CREATE TABLE "client_certificate" ("id" varchar PRIMARY KEY NOT NULL, "name" varchar NOT NULL, "encryption" varchar, "certificate" varchar, "key" varchar, CONSTRAINT "UQ_4966cf1c0e299df01049ebd53a5" UNIQUE ("name"))`);
28+
await queryRunner.query(`INSERT INTO "client_certificate"("id", "name", "encryption", "certificate", "key") SELECT "id", "name", "encryption", "certificate", "key" FROM "temporary_client_certificate"`);
29+
await queryRunner.query(`DROP TABLE "temporary_client_certificate"`);
30+
await queryRunner.query(`ALTER TABLE "ca_certificate" RENAME TO "temporary_ca_certificate"`);
31+
await queryRunner.query(`CREATE TABLE "ca_certificate" ("id" varchar PRIMARY KEY NOT NULL, "name" varchar NOT NULL, "encryption" varchar, "certificate" varchar, CONSTRAINT "UQ_23be613e4fb204fd5a66916b0b3" UNIQUE ("name"))`);
32+
await queryRunner.query(`INSERT INTO "ca_certificate"("id", "name", "encryption", "certificate") SELECT "id", "name", "encryption", "certificate" FROM "temporary_ca_certificate"`);
33+
await queryRunner.query(`DROP TABLE "temporary_ca_certificate"`);
34+
}
35+
36+
}

redisinsight/api/migration/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import { DatabaseCreatedAt1733740794737 } from './1733740794737-database-created
4848
import { DbSettings1737362130798 } from './1737362130798-db-settings';
4949
import { DatabaseForceStandalone1738829743482 } from './1738829743482-database-forceStandalone';
5050
import { RdiOptionalAuth1740579711635 } from './1740579711635-rdi-optional-auth';
51+
import { PreSetupDatabases1741786803681 } from './1741786803681-pre-setup-databases';
5152

5253
export default [
5354
initialMigration1614164490968,
@@ -100,4 +101,5 @@ export default [
100101
DbSettings1737362130798,
101102
DatabaseForceStandalone1738829743482,
102103
RdiOptionalAuth1740579711635,
104+
PreSetupDatabases1741786803681,
103105
];

redisinsight/api/src/__mocks__/certificates.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export const mockCaCertificateRepository = jest.fn(() => ({
3838
]),
3939
create: jest.fn().mockResolvedValue(mockCaCertificate),
4040
delete: jest.fn().mockResolvedValue(undefined),
41+
cleanupPreSetup: jest.fn().mockResolvedValue({ affected: 0 }),
4142
}));
4243

4344
export const mockCaCertificateService = jest.fn(() => ({
@@ -81,6 +82,7 @@ export const mockClientCertificateRepository = jest.fn(() => ({
8182
]),
8283
create: jest.fn().mockResolvedValue(mockClientCertificate),
8384
delete: jest.fn().mockResolvedValue(undefined),
85+
cleanupPreSetup: jest.fn().mockResolvedValue({ affected: 0 }),
8486
}));
8587

8688
export const mockClientCertificateService = jest.fn(() => ({
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
import { Database } from 'src/modules/database/models/database';
2+
3+
export const mockDefaultDatabaseFields = {
4+
isPreSetup: true,
5+
compressor: 'NONE',
6+
connectionType: 'NOT CONNECTED',
7+
modules: [],
8+
caCert: null,
9+
clientCert: null,
10+
db: null,
11+
nameFromProvider: null,
12+
password: null,
13+
provider: null,
14+
ssh: null,
15+
sshOptions: null,
16+
tls: false,
17+
tlsServername: null,
18+
username: null,
19+
verifyServerCert: null,
20+
};
21+
22+
export const mockDatabaseToImportFromEnvsInput = {
23+
id: '0',
24+
host: 'localhost',
25+
port: 6379,
26+
name: 'local database',
27+
} as Partial<Database>;
28+
29+
export const mockDatabaseToImportFromEnvsPrepared = {
30+
...mockDefaultDatabaseFields,
31+
...mockDatabaseToImportFromEnvsInput,
32+
} as Database;
33+
34+
export const mockDatabaseToImportWithCertsFromEnvsInput = {
35+
id: '_1',
36+
host: 'host1',
37+
port: 6370,
38+
name: 'local database',
39+
tls: true,
40+
caCert: {
41+
certificate: 'CA cert',
42+
},
43+
clientCert: {
44+
certificate: 'User cert',
45+
key: 'User key',
46+
},
47+
verifyServerCert: true,
48+
} as Partial<Database>;
49+
50+
export const mockDatabaseToImportWithCertsFromEnvsPrepared = {
51+
...mockDefaultDatabaseFields,
52+
...mockDatabaseToImportWithCertsFromEnvsInput,
53+
caCert: {
54+
id: mockDatabaseToImportWithCertsFromEnvsInput.id,
55+
name: `${mockDatabaseToImportWithCertsFromEnvsInput.id}_${mockDatabaseToImportWithCertsFromEnvsInput.name}`,
56+
certificate: mockDatabaseToImportWithCertsFromEnvsInput.caCert.certificate,
57+
isPreSetup: true,
58+
},
59+
clientCert: {
60+
id: mockDatabaseToImportWithCertsFromEnvsInput.id,
61+
name: `${mockDatabaseToImportWithCertsFromEnvsInput.id}_${mockDatabaseToImportWithCertsFromEnvsInput.name}`,
62+
certificate: mockDatabaseToImportWithCertsFromEnvsInput.clientCert.certificate,
63+
key: mockDatabaseToImportWithCertsFromEnvsInput.clientCert.key,
64+
isPreSetup: true,
65+
},
66+
} as Database;
67+
68+
export const mockDatabaseToImportFromFileInput = {
69+
compressor: 'NONE',
70+
id: '_3',
71+
host: '172.30.100.102',
72+
port: 6379,
73+
name: 'standalone-auth',
74+
db: null,
75+
username: null,
76+
password: null,
77+
connectionType: 'NOT CONNECTED',
78+
nameFromProvider: null,
79+
provider: null,
80+
lastConnection: null,
81+
modules: [],
82+
tls: false,
83+
tlsServername: null,
84+
verifyServerCert: null,
85+
caCert: null,
86+
clientCert: null,
87+
ssh: null,
88+
sshOptions: null,
89+
} as Partial<Database>;
90+
91+
export const mockDatabaseToImportFromFilePrepared = {
92+
...mockDefaultDatabaseFields,
93+
...mockDatabaseToImportFromFileInput,
94+
isPreSetup: true,
95+
} as Database;
96+
97+
export const mockDatabaseToImportWithCertsFromFileInput = {
98+
compressor: 'Brotli',
99+
id: '_5',
100+
host: '172.30.100.103',
101+
port: 6379,
102+
name: 'standalone-tls-auth',
103+
db: null,
104+
username: 'admin',
105+
password: 'pass',
106+
connectionType: 'STANDALONE', // will be overwritten
107+
nameFromProvider: null,
108+
provider: null,
109+
lastConnection: null,
110+
modules: [],
111+
tls: true,
112+
tlsServername: null,
113+
verifyServerCert: true,
114+
caCert: {
115+
id: 'will be overwritten',
116+
name: 'will be overwritten',
117+
certificate:
118+
'-----BEGIN CERTIFICATE-----\nMIIFHzCCAwegAwIBAgIUKeAfHPO6uJBW...',
119+
isPreSetup: false, // will be overwritten
120+
},
121+
clientCert: {
122+
id: 'will be overwritten',
123+
name: 'will be overwritten',
124+
certificate:
125+
'-----BEGIN CERTIFICATE-----\nMIIEzTCCArWgAwIBAgIUALiX/81ndGTG...',
126+
key: '-----BEGIN PRIVATE KEY-----\nMIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggko...',
127+
isPreSetup: false, // will be overwritten
128+
},
129+
ssh: null,
130+
sshOptions: null,
131+
isPreSetup: false, // will be overwritten
132+
} as Partial<Database>;
133+
134+
export const mockDatabaseToImportWithCertsFromFilePrepared = {
135+
...mockDatabaseToImportWithCertsFromFileInput,
136+
isPreSetup: true,
137+
compressor: 'Brotli',
138+
connectionType: 'NOT CONNECTED',
139+
modules: [],
140+
caCert: {
141+
id: mockDatabaseToImportWithCertsFromFileInput.id,
142+
name: `${mockDatabaseToImportWithCertsFromFileInput.id}_${mockDatabaseToImportWithCertsFromFileInput.name}`,
143+
certificate: mockDatabaseToImportWithCertsFromFileInput.caCert.certificate,
144+
isPreSetup: true,
145+
},
146+
clientCert: {
147+
id: mockDatabaseToImportWithCertsFromFileInput.id,
148+
name: `${mockDatabaseToImportWithCertsFromFileInput.id}_${mockDatabaseToImportWithCertsFromFileInput.name}`,
149+
certificate: mockDatabaseToImportWithCertsFromFileInput.clientCert.certificate,
150+
key: mockDatabaseToImportWithCertsFromFileInput.clientCert.key,
151+
isPreSetup: true,
152+
},
153+
db: null,
154+
nameFromProvider: null,
155+
provider: null,
156+
ssh: null,
157+
sshOptions: null,
158+
tlsServername: null,
159+
} as Database;
160+
161+
export const cleanupTestEnvs = () => {
162+
delete process.env.RI_REDIS_HOST;
163+
delete process.env.RI_REDIS_PORT;
164+
delete process.env.RI_REDIS_ALIAS;
165+
delete process.env.RI_REDIS_USENAME;
166+
delete process.env.RI_REDIS_PASSWORD;
167+
168+
delete process.env.RI_REDIS_HOST_1;
169+
delete process.env.RI_REDIS_PORT_1;
170+
delete process.env.RI_REDIS_ALIAS_1;
171+
delete process.env.RI_REDIS_TLS_1;
172+
delete process.env.RI_REDIS_TLS_CA_PATH_1;
173+
delete process.env.RI_REDIS_TLS_CA_BASE64_1;
174+
delete process.env.RI_REDIS_TLS_CERT_PATH_1;
175+
delete process.env.RI_REDIS_TLS_CERT_BASE64_1;
176+
delete process.env.RI_REDIS_TLS_KEY_PATH_1;
177+
delete process.env.RI_REDIS_TLS_KEY_BASE64_1;
178+
179+
delete process.env.RI_REDIS_HOST_2;
180+
delete process.env.RI_REDIS_HHOST;
181+
};
182+
183+
export const mockPreSetupDatabaseDiscoveryService = () => ({
184+
discover: jest.fn().mockResolvedValue({ discovered: 0 }),
185+
});
186+
187+
export const mockAutoDatabaseDiscoveryService = () => ({
188+
discover: jest.fn(),
189+
});
190+
191+
export const mockDatabaseDiscoveryService = () => ({
192+
discover: jest.fn(),
193+
});

redisinsight/api/src/__mocks__/databases.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ export const mockDatabaseRepository = jest.fn(() => ({
261261
pick(mockDatabase, 'id', 'name'),
262262
pick(mockDatabase, 'id', 'name'),
263263
]),
264+
cleanupPreSetup: jest.fn().mockResolvedValue({ affected: 0 }),
264265
}));
265266

266267
export const mockDatabaseService = jest.fn(() => ({

redisinsight/api/src/__mocks__/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export * from './redis';
2121
export * from './server';
2222
export * from './redis-enterprise';
2323
export * from './redis-sentinel';
24+
export * from './database-discovery';
2425
export * from './database-import';
2526
export * from './redis-client';
2627
export * from './redis-utils';

redisinsight/api/src/app.module.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import { ClusterMonitorModule } from 'src/modules/cluster-monitor/cluster-monito
1515
import { DatabaseAnalysisModule } from 'src/modules/database-analysis/database-analysis.module';
1616
import { LocalDatabaseModule } from 'src/local-database.module';
1717
import { CoreModule } from 'src/core.module';
18-
import { AutodiscoveryModule } from 'src/modules/autodiscovery/autodiscovery.module';
1918
import { DatabaseImportModule } from 'src/modules/database-import/database-import.module';
2019
import { SingleUserAuthMiddleware } from 'src/common/middlewares/single-user-auth.middleware';
2120
import { CustomTutorialModule } from 'src/modules/custom-tutorial/custom-tutorial.module';
@@ -47,7 +46,6 @@ const STATICS_CONFIG = config.get('statics') as Config['statics'];
4746
LocalDatabaseModule,
4847
CoreModule,
4948
RouterModule.register(routes),
50-
AutodiscoveryModule,
5149
RedisEnterpriseModule,
5250
CloudModule.register(),
5351
RedisSentinelModule,
@@ -73,7 +71,7 @@ const STATICS_CONFIG = config.get('statics') as Config['statics'];
7371
initDefaults: STATICS_CONFIG.initDefaults,
7472
autoUpdate: STATICS_CONFIG.autoUpdate,
7573
}),
76-
InitModule.register([AutodiscoveryModule, AnalyticsModule]),
74+
InitModule.register([AnalyticsModule]),
7775
DatabaseSettingsModule.register(),
7876
],
7977
controllers: [],

0 commit comments

Comments
 (0)