Add unit test to grant that production aliases correspond to a published RubyGem (#12993) (#13009)

Loads the production plugin_aliases.yml definition file and check that every alias has
a properly published gem on RubyGems.

Adds clean up of plugin_aliases.yml files
Fixed task dependency for copyPluginAlias

(cherry picked from commit a5f3153a8f)
This commit is contained in:
Andrea Selva 2021-06-28 16:54:08 +02:00 committed by GitHub
parent c30559269e
commit c081985782
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 14 deletions

View file

@ -246,7 +246,7 @@ tasks.register("copyPluginTestAlias", Copy) {
}
}
processResources.dependsOn(copyPluginAlias)
tasks.findByPath(':logstash-core:processResources').dependsOn(copyPluginAlias)
tasks.findByPath(':logstash-core:processTestResources').dependsOn(copyPluginTestAlias)
@ -261,6 +261,13 @@ clean {
delete "${projectDir}/qa/integration/.bundle"
delete "${projectDir}/build/licenseReportFolders.txt"
delete "${projectDir}/build/rubyDependencies.csv"
delete "${projectDir}/lib/pluginmanager/plugin_aliases.yml"
delete "${projectDir}/spec/unit/plugin_manager/plugin_aliases.yml"
delete "${projectDir}/logstash-core/build/resources/test/org/logstash/plugins/plugin_aliases.yml"
delete "${projectDir}/logstash-core/build/resources/main/org/logstash/plugins/plugin_aliases.yml"
delete "${projectDir}/logstash-core/src/test/resources/org/logstash/plugins/plugin_aliases.yml"
delete "${projectDir}/logstash-core/src/main/resources/org/logstash/plugins/plugin_aliases.yml"
}
def assemblyDeps = [downloadAndInstallJRuby, assemble] + subprojects.collect {

View file

@ -7,9 +7,12 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.logstash.plugins.PluginLookup.PluginType;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@ -22,7 +25,7 @@ public class AliasRegistry {
private static final Logger LOGGER = LogManager.getLogger(AliasRegistry.class);
private final static class PluginCoordinate {
final static class PluginCoordinate {
private final PluginType type;
private final String name;
@ -47,16 +50,20 @@ public class AliasRegistry {
PluginCoordinate withName(String name) {
return new PluginCoordinate(this.type, name);
}
@Override
public String toString() {
return "PluginCoordinate{type=" + type + ", name='" + name + "'}";
}
public String fullName() {
return "logstash-" + type.rubyLabel().toString().toLowerCase() + "-" + name;
}
}
private static class YamlWithChecksum {
static YamlWithChecksum load(final String filePath) {
final InputStream in = YamlWithChecksum.class.getClassLoader().getResourceAsStream(filePath);
if (in == null) {
throw new IllegalArgumentException("Can't find aliases yml definition file in jar resources: " + filePath);
}
private static YamlWithChecksum load(InputStream in) {
try (Scanner scanner = new Scanner(in, StandardCharsets.UTF_8.name())) {
// read the header line
final String header = scanner.nextLine();
@ -98,17 +105,33 @@ public class AliasRegistry {
}
}
private static class AliasYamlLoader {
static class AliasYamlLoader {
private Map<PluginCoordinate, String> loadAliasesDefinitions() {
final YamlWithChecksum aliasYml;
Map<PluginCoordinate, String> loadAliasesDefinitions(Path yamlPath) {
final FileInputStream in;
try {
aliasYml = YamlWithChecksum.load("org/logstash/plugins/plugin_aliases.yml");
} catch (IllegalArgumentException badSyntaxExcp) {
LOGGER.warn("Malformed yaml file", badSyntaxExcp);
in = new FileInputStream(yamlPath.toFile());
} catch (FileNotFoundException e) {
LOGGER.warn("Can't find aliases yml definition file in in path: " + yamlPath, e);
return Collections.emptyMap();
}
return loadAliasesDefinitionsFromInputStream(in);
}
Map<PluginCoordinate, String> loadAliasesDefinitions() {
final String filePath = "org/logstash/plugins/plugin_aliases.yml";
final InputStream in = AliasYamlLoader.class.getClassLoader().getResourceAsStream(filePath);
if (in == null) {
LOGGER.warn("Malformed yaml file in yml definition file in jar resources: {}", filePath);
return Collections.emptyMap();
}
return loadAliasesDefinitionsFromInputStream(in);
}
private Map<PluginCoordinate, String> loadAliasesDefinitionsFromInputStream(InputStream in) {
final YamlWithChecksum aliasYml = YamlWithChecksum.load(in);
final String calculatedHash = aliasYml.computeHashFromContent();
if (!calculatedHash.equals(aliasYml.checksumHash)) {
LOGGER.warn("Bad checksum value, expected {} but found {}", calculatedHash, aliasYml.checksumHash);

View file

@ -3,6 +3,13 @@ package org.logstash.plugins;
import org.junit.Test;
import org.logstash.plugins.PluginLookup.PluginType;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import static org.junit.Assert.*;
public class AliasRegistryTest {
@ -18,4 +25,22 @@ public class AliasRegistryTest {
assertEquals("aliased_filter should be the alias for json filter",
"json", sut.originalFromAlias(PluginType.FILTER, "aliased_filter"));
}
@Test
public void testProductionConfigAliasesGemsExists() throws IOException {
final Path currentPath = Paths.get("./src/main/resources/org/logstash/plugins/plugin_aliases.yml").toAbsolutePath();
final AliasRegistry.AliasYamlLoader aliasLoader = new AliasRegistry.AliasYamlLoader();
final Map<AliasRegistry.PluginCoordinate, String> aliasesDefinitions = aliasLoader.loadAliasesDefinitions(currentPath);
for (AliasRegistry.PluginCoordinate alias : aliasesDefinitions.keySet()) {
final String gemName = alias.fullName();
URL url = new URL("https://rubygems.org/api/v1/gems/" + gemName +".json");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/json");
final String errorMsg = "Aliased plugin " + gemName + "specified in " + currentPath + " MUST be published on RubyGems";
assertEquals(errorMsg, 200, connection.getResponseCode());
}
}
}