private static void invokeWith(Mapping entries, ConfiguratorOperation function) throws ConfiguratorException {

        // Run configurators by order, consuming entries until all have found a matching configurator.
        // Configurators order is important so that io.jenkins.plugins.casc.plugins.PluginManagerConfigurator run
        // before any other, and can install plugins required by other configuration to successfully parse yaml data
        for (RootElementConfigurator configurator : RootElementConfigurator.all()) {
            final Iterator<Map.Entry<String, CNode>> it = entries.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String, CNode> entry = it.next();
                if (!entry.getKey().equalsIgnoreCase(configurator.getName())) {
                    continue;
                }
                function.apply(configurator, entry.getValue());
                it.remove();
                break;
            }
        }

        if (!entries.isEmpty()) {
            List<String> unknownKeys = new ArrayList<>();
            entries.entrySet().iterator().forEachRemaining(next -> {
                String key = next.getKey();
                if (isNotAliasEntry(key)) {
                    unknownKeys.add(key);
                }
            });

            if (!unknownKeys.isEmpty()) {
                throw new UnknownConfiguratorException(unknownKeys, "No configurator for the following root elements:");
            }
        }
    }
Configuration with help of {@link RootElementConfigurator}s.
Corresponding configurator is searched by entry key, passing entry value as object with all required properties.

@param entries key-value pairs, where key should match to root configurator and value have all required properties
@throws ConfiguratorException configuration error
plugin/src/main/java/io/jenkins/plugins/casc/ConfigurationAsCode.java