diff --git a/cli/src/main/java/io/kestra/cli/commands/migrations/metadata/MetadataMigrationService.java b/cli/src/main/java/io/kestra/cli/commands/migrations/metadata/MetadataMigrationService.java index 91cf1d9292..851ef9b089 100644 --- a/cli/src/main/java/io/kestra/cli/commands/migrations/metadata/MetadataMigrationService.java +++ b/cli/src/main/java/io/kestra/cli/commands/migrations/metadata/MetadataMigrationService.java @@ -1,5 +1,6 @@ package io.kestra.cli.commands.migrations.metadata; +import com.google.common.annotations.VisibleForTesting; import io.kestra.core.models.kv.PersistedKvMetadata; import io.kestra.core.models.namespaces.files.NamespaceFileMetadata; import io.kestra.core.repositories.FlowRepositoryInterface; @@ -11,18 +12,16 @@ import io.kestra.core.storages.StorageInterface; import io.kestra.core.storages.kv.InternalKVStore; import io.kestra.core.storages.kv.KVEntry; import io.kestra.core.tenant.TenantService; -import jakarta.inject.Inject; +import io.kestra.core.utils.NamespaceUtils; import jakarta.inject.Singleton; +import lombok.AllArgsConstructor; import java.io.FileNotFoundException; import java.io.IOException; import java.net.URI; -import java.nio.file.Path; +import java.nio.file.NoSuchFileException; import java.time.Instant; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -30,25 +29,18 @@ import static io.kestra.core.utils.Rethrow.throwConsumer; import static io.kestra.core.utils.Rethrow.throwFunction; @Singleton +@AllArgsConstructor public class MetadataMigrationService { - @Inject - private TenantService tenantService; + protected FlowRepositoryInterface flowRepository; + protected TenantService tenantService; + protected KvMetadataRepositoryInterface kvMetadataRepository; + protected NamespaceFileMetadataRepositoryInterface namespaceFileMetadataRepository; + protected StorageInterface storageInterface; - @Inject - private FlowRepositoryInterface flowRepository; - - @Inject - private KvMetadataRepositoryInterface kvMetadataRepository; - - @Inject - private NamespaceFileMetadataRepositoryInterface namespaceFileMetadataRepository; - - @Inject - private StorageInterface storageInterface; - - protected Map> namespacesPerTenant() { + @VisibleForTesting + public Map> namespacesPerTenant() { String tenantId = tenantService.resolveTenant(); - return Map.of(tenantId, flowRepository.findDistinctNamespace(tenantId)); + return Map.of(tenantId, flowRepository.findDistinctNamespace(tenantId).stream().map(NamespaceUtils::asTree).flatMap(Collection::stream).distinct().toList()); } public void kvMigration() throws IOException { diff --git a/cli/src/test/java/io/kestra/cli/commands/migrations/metadata/MetadataMigrationServiceTest.java b/cli/src/test/java/io/kestra/cli/commands/migrations/metadata/MetadataMigrationServiceTest.java new file mode 100644 index 0000000000..e2b22e30b9 --- /dev/null +++ b/cli/src/test/java/io/kestra/cli/commands/migrations/metadata/MetadataMigrationServiceTest.java @@ -0,0 +1,47 @@ +package io.kestra.cli.commands.migrations.metadata; + +import io.kestra.core.repositories.FlowRepositoryInterface; +import io.kestra.core.tenant.TenantService; +import io.kestra.core.utils.NamespaceUtils; +import io.kestra.core.utils.TestsUtils; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +public class MetadataMigrationServiceTest { + private static final String TENANT_ID = TestsUtils.randomTenant(); + + @Test + void namespacesPerTenant() { + Map> expected = getNamespacesPerTenant(); + Map> result = metadataMigrationService( + expected + ).namespacesPerTenant(); + + assertThat(result).hasSize(expected.size()); + expected.forEach((tenantId, namespaces) -> {; + assertThat(result.get(tenantId)).containsExactlyInAnyOrderElementsOf(namespaces.stream().map(NamespaceUtils::asTree).flatMap(Collection::stream).distinct().toList()); + }); + } + + protected Map> getNamespacesPerTenant() { + return Map.of(TENANT_ID, List.of("my.first.namespace", "my.second.namespace", "another.namespace")); + } + + protected T metadataMigrationService(Map> namespacesPerTenant) { + FlowRepositoryInterface mockedFlowRepository = Mockito.mock(FlowRepositoryInterface.class); + Mockito.doAnswer((params) -> namespacesPerTenant.get(params.getArgument(0).toString())).when(mockedFlowRepository).findDistinctNamespace(Mockito.anyString()); + //noinspection unchecked + return ((T) new MetadataMigrationService(mockedFlowRepository, new TenantService() { + @Override + public String resolveTenant() { + return TENANT_ID; + } + }, null, null, null)); + } +} diff --git a/tests/src/main/java/io/kestra/core/utils/TestsUtils.java b/tests/src/main/java/io/kestra/core/utils/TestsUtils.java index ce0a753e9f..58ffd83f58 100644 --- a/tests/src/main/java/io/kestra/core/utils/TestsUtils.java +++ b/tests/src/main/java/io/kestra/core/utils/TestsUtils.java @@ -80,7 +80,7 @@ abstract public class TestsUtils { } var tenantRegex = "^[a-z0-9][a-z0-9_-]*"; var validTenantPrefixes = Arrays.stream(prefix) - .map(s -> s.replace(".", "-").replace("$", "-")) + .map(s -> s.replaceAll("[.$<>]", "-")) .map(String::toLowerCase) .peek(p -> { if (!p.matches(tenantRegex)) {