diff --git a/services/api/database/migrations/20231222000000_delete_orphaned_insights.js b/services/api/database/migrations/20231222000000_delete_orphaned_insights.js new file mode 100644 index 0000000000..1f3a279b73 --- /dev/null +++ b/services/api/database/migrations/20231222000000_delete_orphaned_insights.js @@ -0,0 +1,28 @@ +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = function(knex) { + return Promise.all([ + knex.schema.raw(` + DELETE ef + FROM environment_fact ef + LEFT JOIN environment e ON ef.environment = e.id + WHERE e.id IS NULL OR e.deleted != '0000-00-00 00:00:00' OR e.project not in (select id from project) + `), + knex.schema.raw(` + DELETE ep + FROM environment_problem ep + LEFT JOIN environment e ON ep.environment = e.id + WHERE e.id IS NULL OR e.deleted != '0000-00-00 00:00:00' OR e.project not in (select id from project) + `), + ]); + }; + + /** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ + exports.down = function(knex) { + return knex.schema; + }; diff --git a/services/api/database/migrations/20240108000000_fix_env_orphans.js b/services/api/database/migrations/20240108000000_fix_env_orphans.js new file mode 100644 index 0000000000..7bb0072a31 --- /dev/null +++ b/services/api/database/migrations/20240108000000_fix_env_orphans.js @@ -0,0 +1,19 @@ +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = async function(knex) { + return knex('environment') + .leftJoin('project', 'environment.project', 'project.id') + .whereNull('project.id') + .andWhere('environment.deleted','0000-00-00 00:00:00') + .update('deleted', knex.raw('NOW()')); +}; + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = async function(knex) { + return knex.schema +}; diff --git a/services/api/src/resources/environment/helpers.ts b/services/api/src/resources/environment/helpers.ts index 3f1d6d65e3..a55f2bc38c 100644 --- a/services/api/src/resources/environment/helpers.ts +++ b/services/api/src/resources/environment/helpers.ts @@ -3,6 +3,8 @@ import { Pool } from 'mariadb'; import { asyncPipe } from '@lagoon/commons/dist/util/func'; import { query } from '../../util/db'; import { Sql } from './sql'; +import { Sql as problemSql } from '../problem/sql'; +import { Sql as factSql } from '../fact/sql'; import { Helpers as projectHelpers } from '../project/helpers'; // import { logger } from '../../loggers/logger'; @@ -48,6 +50,19 @@ export const Helpers = (sqlClientPool: Pool) => { sqlClientPool, Sql.deleteEnvironment(name, pid) ); + + // Here we clean up insights attached to the environment + + await query( + sqlClientPool, + factSql.deleteFactsForEnvironment(eid) + ); + + await query( + sqlClientPool, + problemSql.deleteProblemsForEnvironment(eid) + ); + }, getEnvironmentsDeploytarget: async (eid) => { const rows = await query( diff --git a/services/api/src/resources/fact/sql.ts b/services/api/src/resources/fact/sql.ts index 33a06ce918..25121d000f 100644 --- a/services/api/src/resources/fact/sql.ts +++ b/services/api/src/resources/fact/sql.ts @@ -48,6 +48,13 @@ export const Sql = { }) .del() .toString(), + deleteFactsForEnvironment: (environment) => // Used when removing environments. + knex('environment_fact') + .where({ + environment + }) + .del() + .toString(), deleteFactsFromSource: (environment, source, service) => { let query = knex('environment_fact') .where({ environment, source }); diff --git a/services/api/src/resources/problem/sql.ts b/services/api/src/resources/problem/sql.ts index afa9afd34f..0607b7705a 100644 --- a/services/api/src/resources/problem/sql.ts +++ b/services/api/src/resources/problem/sql.ts @@ -139,6 +139,13 @@ export const Sql = { } return q.del().toString(); }, + deleteProblemsForEnvironment: (environment) => { // This should be used primarily to remove problems when deleting an environment + let q = knex('environment_problem') + .where({ + environment: environment + }); + return q.del().toString(); + }, deleteProblemsFromSource: (environment, source, service) => knex('environment_problem') .where({ diff --git a/services/api/src/typeDefs.js b/services/api/src/typeDefs.js index d0d913c47d..a45ef2fda8 100644 --- a/services/api/src/typeDefs.js +++ b/services/api/src/typeDefs.js @@ -976,7 +976,7 @@ const typeDefs = gql` """ The size of the restored file in bytes """ - restoreSize: Int + restoreSize: Float created: String } diff --git a/services/logs2notifications/internal/handler/email_events.go b/services/logs2notifications/internal/handler/email_events.go index 3e16e85fd9..f26c19e463 100644 --- a/services/logs2notifications/internal/handler/email_events.go +++ b/services/logs2notifications/internal/handler/email_events.go @@ -60,7 +60,7 @@ func (h *Messaging) processEmailTemplates(notification *Notification) (string, s if err != nil { eventSplit := strings.Split(notification.Event, ":") if eventSplit[0] != "problem" { - return "", "", "", "", "", nil + return "", "", "", "", "", fmt.Errorf("no matching event") } if eventSplit[1] == "insert" { tpl = "problemNotification" @@ -127,7 +127,7 @@ func (h *Messaging) processEmailTemplates(notification *Notification) (string, s case "problemNotification": eventSplit := strings.Split(notification.Event, ":") if eventSplit[0] != "problem" && eventSplit[1] == "insert" { - return "", "", "", "", "", nil + return "", "", "", "", "", fmt.Errorf("no matching event") } mainHTMLTpl = `[{{.ProjectName}}] New problem found for {{.EnvironmentName}}
  • * Service: {{.ServiceName}}
  • {{ if ne .Severity "" }} @@ -142,7 +142,7 @@ func (h *Messaging) processEmailTemplates(notification *Notification) (string, s notification.Meta.EnvironmentName, ) default: - return "", "", "", "", "", nil + return "", "", "", "", "", fmt.Errorf("no matching event") } var body bytes.Buffer