fix(core): tenant migration scripts now update keys

* chore(core): add keyboard shortcuts icon to flow editor tab (#8925)

fix(core): don't send empty operations when migrating roles (#3807)

Co-authored-by: nKwiatkowski <nkwiatkowski@kestra.io>

* fix(core): migrate key that required tenant id to avoid duplication

---------

Co-authored-by: Miloš Paunović <paun992@hotmail.com>
Co-authored-by: nKwiatkowski <nkwiatkowski@kestra.io>
This commit is contained in:
Nicolas K.
2025-05-23 16:44:53 +02:00
committed by GitHub
parent 2601df3de2
commit 29c3bd7dec
4 changed files with 74 additions and 10 deletions

View File

@@ -1,5 +1,7 @@
package io.kestra.repository.h2;
import static io.kestra.core.tenant.TenantService.MAIN_TENANT;
import io.kestra.jdbc.JooqDSLContextWrapper;
import io.kestra.jdbc.repository.AbstractJdbcTenantMigration;
import jakarta.inject.Singleton;
@@ -15,7 +17,7 @@ public class H2TenantMigration extends AbstractJdbcTenantMigration {
}
@Override
protected int updateTenantId(Table<?> table, DSLContext context) {
protected int updateTenantIdField(Table<?> table, DSLContext context) {
String query = """
UPDATE "%s"
SET "value" = '{"tenantId":"%s",' || SUBSTRING("value", 2)
@@ -24,4 +26,17 @@ public class H2TenantMigration extends AbstractJdbcTenantMigration {
return context.execute(query, "main");
}
@Override
protected int updateTenantIdFieldAndKey(Table<?> table, DSLContext context) {
String query = """
UPDATE "%s"
SET
"key" = '%s_' || "key",
"value" = '{"tenantId":"%s",' || SUBSTRING("value", 2)
WHERE JQ_STRING("value", '.tenantId') IS NULL
""".formatted(table.getName(), MAIN_TENANT, MAIN_TENANT);
return context.execute(query);
}
}

View File

@@ -1,5 +1,7 @@
package io.kestra.repository.mysql;
import static io.kestra.core.tenant.TenantService.MAIN_TENANT;
import io.kestra.jdbc.JooqDSLContextWrapper;
import io.kestra.jdbc.repository.AbstractJdbcTenantMigration;
import jakarta.inject.Singleton;
@@ -15,11 +17,24 @@ public class MysqlTenantMigration extends AbstractJdbcTenantMigration {
}
@Override
protected int updateTenantId(Table<?> table, DSLContext context) {
protected int updateTenantIdField(Table<?> table, DSLContext context) {
String query = "UPDATE `" + table.getName() + "` " +
"SET `value` = JSON_SET(`value`, '$.tenantId', ?) " +
"WHERE JSON_UNQUOTE(JSON_EXTRACT(`value`, '$.tenantId')) IS NULL";
return context.execute(query, "main");
return context.execute(query, MAIN_TENANT);
}
@Override
protected int updateTenantIdFieldAndKey(Table<?> table, DSLContext context) {
String query = """
UPDATE `%s`
SET
`key` = CONCAT(?, '_', `key`),
`value` = JSON_SET(`value`, '$.tenantId', ?)
WHERE JSON_UNQUOTE(JSON_EXTRACT(`value`, '$.tenantId')) IS NULL
""".formatted(table.getName());
return context.execute(query, MAIN_TENANT, MAIN_TENANT);
}
}

View File

@@ -1,5 +1,7 @@
package io.kestra.repository.postgres;
import static io.kestra.core.tenant.TenantService.MAIN_TENANT;
import io.kestra.jdbc.JooqDSLContextWrapper;
import io.kestra.jdbc.repository.AbstractJdbcTenantMigration;
import jakarta.inject.Singleton;
@@ -16,11 +18,24 @@ public class PostgresTenantMigration extends AbstractJdbcTenantMigration {
}
@Override
protected int updateTenantId(Table<?> table, DSLContext context) {
protected int updateTenantIdField(Table<?> table, DSLContext context) {
String query = "UPDATE " + table.getQualifiedName() + " " +
"SET value = jsonb_set(value, '{tenantId}', ?::jsonb) " +
"WHERE (value->>'tenantId') IS NULL";
return context.execute(query, "\"main\"");
return context.execute(query, "\"" + MAIN_TENANT + "\"");
}
@Override
protected int updateTenantIdFieldAndKey(Table<?> table, DSLContext context) {
String query = """
UPDATE %s
SET
key = ? || '_' || key,
value = jsonb_set(value, '{tenantId}', to_jsonb(?::text))
WHERE (value->>'tenantId') IS NULL
""".formatted(table.getQualifiedName());
return context.execute(query, MAIN_TENANT, MAIN_TENANT);
}
}

View File

@@ -3,6 +3,7 @@ package io.kestra.jdbc.repository;
import io.kestra.core.repositories.TenantMigrationInterface;
import io.kestra.jdbc.JooqDSLContextWrapper;
import java.util.List;
import java.util.Locale;
import lombok.extern.slf4j.Slf4j;
import org.jooq.Condition;
import org.jooq.DSLContext;
@@ -13,6 +14,9 @@ import org.jooq.impl.DSL;
@Slf4j
public abstract class AbstractJdbcTenantMigration implements TenantMigrationInterface {
private static final List<String> KEY_TABLES = List.of("dashboards", "flows", "multipleconditions",
"namespaces", "testsuites", "triggers", "templates");
protected final JooqDSLContextWrapper dslContextWrapper;
protected AbstractJdbcTenantMigration(JooqDSLContextWrapper dslContextWrapper) {
@@ -41,10 +45,18 @@ public abstract class AbstractJdbcTenantMigration implements TenantMigrationInte
}
if (!dryRun) {
int updated = dslContextWrapper.transactionResult(configuration -> {
DSLContext context = DSL.using(configuration);
return updateTenantId(table, context);
});
int updated;
if (tableWithKey(table.getName())){
updated = dslContextWrapper.transactionResult(configuration -> {
DSLContext context = DSL.using(configuration);
return updateTenantIdFieldAndKey(table, context);
});
} else {
updated = dslContextWrapper.transactionResult(configuration -> {
DSLContext context = DSL.using(configuration);
return updateTenantIdField(table, context);
});
}
totalAffected += updated;
log.info("✅ Updated {} row(s) in {}", updated, table.getName());
} else {
@@ -72,6 +84,13 @@ public abstract class AbstractJdbcTenantMigration implements TenantMigrationInte
}
}
protected abstract int updateTenantId(Table<?> table, DSLContext context);
private static boolean tableWithKey(String tableName){
return KEY_TABLES.stream().anyMatch(name -> tableName.toLowerCase(Locale.ROOT).contains(name));
}
protected abstract int updateTenantIdField(Table<?> table, DSLContext context);
protected abstract int updateTenantIdFieldAndKey(Table<?> table, DSLContext context);
}