@Get(uri = "icons")
    @ExecuteOn(TaskExecutors.IO)
    @Operation(tags = {"Plugins"}, summary = "Get plugins icons")
    public MutableHttpResponse<Map<String, PluginIcon>> icons() {
        Map<String, PluginIcon> icons = pluginRegistry.plugins()
            .stream()
            .flatMap(plugin -> Stream.of(
                    plugin.getTasks().stream(),
                    plugin.getTriggers().stream(),
                    plugin.getConditions().stream(),
                    plugin.getTaskRunners().stream()
                )
                .flatMap(i -> i)
                .map(e -> new AbstractMap.SimpleEntry<>(
                    e.getName(),
                    new PluginIcon(
                        e.getSimpleName(),
                        plugin.icon(e),
                        FlowableTask.class.isAssignableFrom(e)
                    )
                ))
            )
            .filter(entry -> entry.getKey() != null)
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a1, a2) -> a1));

        // add aliases
        Map<String, PluginIcon> aliasIcons = pluginRegistry.plugins().stream()
            .flatMap(plugin -> plugin.getAliases().values().stream().map(e -> new AbstractMap.SimpleEntry<>(
                e.getKey(),
                new PluginIcon(
                    e.getKey().substring(e.getKey().lastIndexOf('.') + 1),
                    plugin.icon(e.getValue()),
                    FlowableTask.class.isAssignableFrom(e.getValue())
                ))))
            .filter(entry -> entry.getKey() != null)
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a1, a2) -> a1));
        icons.putAll(aliasIcons);

        return HttpResponse.ok(icons).header(HttpHeaders.CACHE_CONTROL, CACHE_DIRECTIVE);
    }
@Test
    void icons() throws URISyntaxException {
        Helpers.runApplicationContext((applicationContext, embeddedServer) -> {
            ReactorHttpClient client = ReactorHttpClient.create(embeddedServer.getURL());

            Map<String, PluginIcon> list = client.toBlocking().retrieve(
                HttpRequest.GET("/api/v1/plugins/icons"),
                Argument.mapOf(String.class, PluginIcon.class)
            );

            assertThat(list.entrySet().stream().filter(e -> e.getKey().equals(Log.class.getName())).findFirst().orElseThrow().getValue().getIcon(), is(notNullValue()));
            // test an alias
            assertThat(list.entrySet().stream().filter(e -> e.getKey().equals("io.kestra.core.tasks.log.Log")).findFirst().orElseThrow().getValue().getIcon(), is(notNullValue()));
        });
    }