@centreon/js-config 24.10.17 → 24.10.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -65,8 +65,14 @@ module.exports = ({
65
65
  }
66
66
 
67
67
  // Save the testRetries object to a file in the e2e/results directory
68
+ const projectRoot = path.resolve(process.cwd());
69
+ const resolvedFolder = path.resolve(mainCypressFolder);
70
+ if (resolvedFolder !== projectRoot && !resolvedFolder.startsWith(projectRoot + path.sep)) {
71
+ throw new Error('mainCypressFolder is outside of the project directory');
72
+ }
73
+
68
74
  const resultFilePath = path.join(
69
- mainCypressFolder,
75
+ resolvedFolder,
70
76
  'results',
71
77
  'retries.json'
72
78
  );
@@ -32,12 +32,11 @@ Cypress.Commands.add(
32
32
  host,
33
33
  isForced = true
34
34
  }: ServiceCheck): Cypress.Chainable => {
35
- let query = `SELECT id FROM resources WHERE name = '${host}' AND type = 1`;
36
-
37
35
  return cy
38
36
  .requestOnDatabase({
39
37
  database: 'centreon_storage',
40
- query
38
+ query: 'SELECT id FROM resources WHERE name = ? AND type = 1',
39
+ params: [host]
41
40
  })
42
41
  .then(([rows]) => {
43
42
  if (rows.length === 0) {
@@ -84,12 +83,11 @@ Cypress.Commands.add(
84
83
  isForced = true,
85
84
  service
86
85
  }: ServiceCheck): Cypress.Chainable => {
87
- let query = `SELECT parent_id, id FROM resources WHERE parent_name = '${host}' AND name = '${service}'`;
88
-
89
86
  return cy
90
87
  .requestOnDatabase({
91
88
  database: 'centreon_storage',
92
- query
89
+ query: 'SELECT parent_id, id FROM resources WHERE parent_name = ? AND name = ?',
90
+ params: [host, service]
93
91
  })
94
92
  .then(([rows]) => {
95
93
  if (rows.length === 0) {
@@ -181,22 +179,23 @@ Cypress.Commands.add(
181
179
  cy.log('Checking hosts in database');
182
180
 
183
181
  let query = `SELECT COUNT(d.downtime_id) AS count_downtimes FROM downtimes as d
184
- INNER JOIN hosts as h ON h.host_id = d.host_id AND h.name = '${downtime.host}'`;
182
+ INNER JOIN hosts as h ON h.host_id = d.host_id AND h.name = ?`;
183
+ const params: Array<string> = [downtime.host];
185
184
  if (downtime.service) {
186
- query += ` INNER JOIN services as s ON s.service_id = d.service_id AND s.description = '${downtime.service}'`;
185
+ query += ` INNER JOIN services as s ON s.service_id = d.service_id AND s.description = ?`;
186
+ params.push(downtime.service);
187
187
  }
188
188
  query += ` WHERE d.started=1`;
189
189
  if (!downtime.service) {
190
190
  query += ` AND d.service_id = 0`;
191
191
  }
192
192
 
193
- cy.log(query);
194
-
195
193
  cy.waitUntil(() => {
196
194
  return cy
197
195
  .requestOnDatabase({
198
196
  database: 'centreon_storage',
199
- query
197
+ query,
198
+ params
200
199
  })
201
200
  .then(([rows]) => {
202
201
  const foundDowntimesCount = rows.length ? rows[0].count_downtimes : 0;
@@ -377,13 +377,14 @@ Output:\n${displayedOutput}`);
377
377
 
378
378
  interface RequestOnDatabaseProps {
379
379
  database: string;
380
+ params?: Array<string | number>;
380
381
  query: string;
381
382
  }
382
383
 
383
384
  Cypress.Commands.add(
384
385
  'requestOnDatabase',
385
- ({ database, query }: RequestOnDatabaseProps): Cypress.Chainable => {
386
- return cy.task('requestOnDatabase', { database, query });
386
+ ({ database, query, params }: RequestOnDatabaseProps): Cypress.Chainable => {
387
+ return cy.task('requestOnDatabase', { database, query, params });
387
388
  }
388
389
  );
389
390
 
@@ -449,6 +450,8 @@ Cypress.Commands.add(
449
450
  interface StartContainersProps {
450
451
  composeFile?: string;
451
452
  databaseImage?: string;
453
+ dbConfiguration?: string;
454
+ dbStorage?: string;
452
455
  moduleName?: string;
453
456
  openidImage?: string;
454
457
  profiles?: Array<string>;
@@ -463,6 +466,8 @@ Cypress.Commands.add(
463
466
  ({
464
467
  composeFile,
465
468
  databaseImage = Cypress.env('DATABASE_IMAGE'),
469
+ dbConfiguration = Cypress.env('MYSQL_DB_CONFIGURATION'),
470
+ dbStorage = Cypress.env('MYSQL_DB_STORAGE'),
466
471
  moduleName = 'centreon-web',
467
472
  openidImage = `ghcr.io/centreon/centreon/keycloak:${Cypress.env(
468
473
  'OPENID_IMAGE_VERSION'
@@ -493,6 +498,8 @@ Cypress.Commands.add(
493
498
  {
494
499
  composeFile: composeFilePath,
495
500
  databaseImage,
501
+ dbConfiguration,
502
+ dbStorage,
496
503
  openidImage,
497
504
  profiles,
498
505
  samlImage,
@@ -553,8 +560,8 @@ Cypress.Commands.add(
553
560
  cy.log(`Getting logs from container ${name} ...`);
554
561
 
555
562
  return cy.getLogDirectory().then((logDirectory) => {
556
- let sourcePhpLogs = '/var/log/php8.2-fpm-centreon-error.log';
557
- let targetPhpLogs = `${logDirectory}/php8.2-fpm-centreon-error.log`;
563
+ let sourcePhpLogs = '/var/log/centreon/prod.web.log';
564
+ let targetPhpLogs = `${logDirectory}/prod.web.log`;
558
565
  let sourceApacheLogs = '/var/log/apache2';
559
566
  let targetApacheLogs = `${logDirectory}/apache2`;
560
567
  if (Cypress.env('WEB_IMAGE_OS').includes('alma')) {
@@ -957,7 +964,8 @@ declare global {
957
964
  }: NavigateToProps) => Cypress.Chainable;
958
965
  requestOnDatabase: ({
959
966
  database,
960
- query
967
+ query,
968
+ params
961
969
  }: RequestOnDatabaseProps) => Cypress.Chainable;
962
970
  setUserTokenApiV1: ({
963
971
  login,
@@ -2,6 +2,7 @@
2
2
  import { execSync } from 'child_process';
3
3
  import { existsSync, mkdirSync } from 'fs';
4
4
  import path from 'path';
5
+ import fs from "fs";
5
6
 
6
7
  import tar from 'tar-fs';
7
8
  import {
@@ -154,7 +155,7 @@ export default (on: Cypress.PluginEvents): void => {
154
155
 
155
156
  return container.getMappedPort(containerPort);
156
157
  },
157
- requestOnDatabase: async ({ database, query }) => {
158
+ requestOnDatabase: async ({ database, query, params }) => {
158
159
  let container: StartedTestContainer | null = null;
159
160
 
160
161
  if (dockerEnvironment !== null) {
@@ -171,11 +172,15 @@ export default (on: Cypress.PluginEvents): void => {
171
172
  user: 'centreon'
172
173
  });
173
174
 
174
- const [rows, fields] = await client.query(query);
175
-
176
- await client.end();
175
+ try {
176
+ const [rows, fields] = params
177
+ ? await client.execute(query, params)
178
+ : await client.query(query);
177
179
 
178
- return [rows, fields];
180
+ return [rows, fields];
181
+ } finally {
182
+ await client.end();
183
+ }
179
184
  },
180
185
  startContainer: async ({
181
186
  command,
@@ -205,6 +210,8 @@ export default (on: Cypress.PluginEvents): void => {
205
210
  startContainers: async ({
206
211
  composeFile,
207
212
  databaseImage,
213
+ dbConfiguration,
214
+ dbStorage,
208
215
  openidImage,
209
216
  profiles,
210
217
  samlImage,
@@ -214,16 +221,24 @@ export default (on: Cypress.PluginEvents): void => {
214
221
  const composeFileDir = path.dirname(composeFile);
215
222
  const composeFileName = path.basename(composeFile);
216
223
 
224
+ const environment: Record<string, string> = {
225
+ MYSQL_IMAGE: databaseImage,
226
+ OPENID_IMAGE: openidImage,
227
+ SAML_IMAGE: samlImage,
228
+ WEB_IMAGE: webImage,
229
+ };
230
+ if (dbConfiguration) {
231
+ environment.MYSQL_DB_CONFIGURATION = dbConfiguration;
232
+ }
233
+ if (dbStorage) {
234
+ environment.MYSQL_DB_STORAGE = dbStorage;
235
+ }
236
+
217
237
  dockerEnvironment = await new DockerComposeEnvironment(
218
238
  composeFileDir,
219
239
  composeFileName
220
240
  )
221
- .withEnvironment({
222
- MYSQL_IMAGE: databaseImage,
223
- OPENID_IMAGE: openidImage,
224
- SAML_IMAGE: samlImage,
225
- WEB_IMAGE: webImage
226
- })
241
+ .withEnvironment(environment)
227
242
  .withProfiles(...profiles)
228
243
  .withStartupTimeout(120000)
229
244
  .withWaitStrategy(
@@ -277,6 +292,83 @@ export default (on: Cypress.PluginEvents): void => {
277
292
  execSync(`npx wait-on ${url}`);
278
293
 
279
294
  return null;
280
- }
295
+ },
296
+ listFilesInDirectory: async ( directoryPath ) => {
297
+ return new Promise((resolve, reject) => {
298
+ fs.readdir(directoryPath, (err, files) => {
299
+ if (err) {
300
+ reject(err);
301
+ } else {
302
+ resolve(files);
303
+ }
304
+ });
305
+ });
306
+ },
307
+ fileExists: async ( filePath ) => {
308
+ return fs.existsSync(filePath);
309
+ },
310
+ getExportedFile({ downloadsFolder }: { downloadsFolder: string }): string {
311
+ const files = fs
312
+ .readdirSync(downloadsFolder)
313
+ .filter((name) => name.startsWith("ResourceStatusExport_all") && name.endsWith(".csv"))
314
+ .map((name) => ({
315
+ name,
316
+ time: fs.statSync(path.join(downloadsFolder, name)).mtime.getTime()
317
+ }))
318
+ .sort((a, b) => b.time - a.time);
319
+
320
+ if (files.length === 0) {
321
+ throw new Error("No exported file found");
322
+ }
323
+
324
+ return path.join(downloadsFolder, files[0].name);
325
+ },
326
+ readCsvFile({ filePath }: { filePath: string }): Promise<string> {
327
+ const projectRoot = path.resolve(process.cwd());
328
+ const resolvedPath = path.resolve(filePath);
329
+ if (resolvedPath !== projectRoot && !resolvedPath.startsWith(projectRoot + path.sep)) {
330
+ return Promise.reject(new Error("Path is outside of the project directory"));
331
+ }
332
+
333
+ return new Promise((resolve, reject) => {
334
+ fs.readFile(resolvedPath, "utf8", (err, data) => {
335
+ if (err) return reject(err);
336
+ resolve(data);
337
+ });
338
+ });
339
+ },
340
+ clearDownloadsFolder({ downloadsFolder }: { downloadsFolder: string }): null {
341
+ const projectRoot = path.resolve(process.cwd());
342
+ const resolvedFolder = path.resolve(downloadsFolder);
343
+ if (resolvedFolder !== projectRoot && !resolvedFolder.startsWith(projectRoot + path.sep)) {
344
+ throw new Error("Path is outside of the project directory");
345
+ }
346
+
347
+ if (!fs.existsSync(resolvedFolder)) {
348
+ return null;
349
+ }
350
+
351
+ const files = fs.readdirSync(resolvedFolder);
352
+ for (const file of files) {
353
+ const filePath = path.join(resolvedFolder, file);
354
+ if (!filePath.startsWith(resolvedFolder + path.sep)) {
355
+ continue;
356
+ }
357
+ fs.unlinkSync(filePath);
358
+ }
359
+
360
+ return null;
361
+ },
362
+ isDownloadComplete({ downloadsFolder }: { downloadsFolder: string }): boolean {
363
+ if (!fs.existsSync(downloadsFolder)) return false;
364
+
365
+ const files = fs
366
+ .readdirSync(downloadsFolder)
367
+ .filter(
368
+ (name) => !name.endsWith(".crdownload") && !name.endsWith(".tmp")
369
+ );
370
+
371
+ return files.length > 0;
372
+ },
281
373
  });
282
374
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@centreon/js-config",
3
3
  "description": "Centreon Frontend shared build configuration",
4
- "version": "24.10.17",
4
+ "version": "24.10.19",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/centreon/centreon.git"