com.yahoo.vespa.config.proxy.ConfigVerification Maven / Gradle / Ivy
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.config.proxy;
import ai.vespa.util.http.hc5.VespaHttpClientBuilder;
import com.yahoo.slime.ArrayTraverser;
import com.yahoo.slime.Slime;
import com.yahoo.slime.SlimeUtils;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.BasicHttpClientResponseHandler;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
/**
* Tool to verify that configs across multiple config servers are the same.
*
* @author Ulf Lilleengen
*/
public class ConfigVerification {
private final static int port = 19071;
private final static String prefix = "http://";
public static void main(String [] args) throws IOException {
List configservers = new ArrayList<>();
String tenant = "default";
String appName = "default";
String environment = "prod";
String region = "default";
String instance= "default";
for (String arg : args) {
configservers.add(prefix + arg + ":" + port + "/config/v2/tenant/" + tenant + "/application/" + appName + "/environment/" + environment + "/region/" + region + "/instance/" + instance + "/?recursive=true");
}
try (CloseableHttpClient httpClient = VespaHttpClientBuilder.create(BasicHttpClientConnectionManager::new).build()) {
System.exit(compareConfigs(listConfigs(configservers, httpClient), httpClient));
}
}
private static Map> listConfigs(List urls, CloseableHttpClient httpClient) throws IOException {
Map outputs = performRequests(urls, httpClient);
Map> recurseMappings = new LinkedHashMap<>();
for (Map.Entry entry : outputs.entrySet()) {
Slime slime = SlimeUtils.jsonToSlime(entry.getValue());
final List list = new ArrayList<>();
slime.get().field("configs").traverse((ArrayTraverser) (idx, inspector) -> list.add(inspector.asString()));
Stack stack = new Stack<>();
Collections.sort(list);
stack.addAll(list);
recurseMappings.put(entry.getKey(), stack);
}
return recurseMappings;
}
private static Map performRequests(List urls, CloseableHttpClient httpClient) throws IOException {
Map outputs = new LinkedHashMap<>();
for (String url : urls) {
outputs.put(url, performRequest(url, httpClient));
}
return outputs;
}
private static int compareConfigs(Map> mappings, CloseableHttpClient httpClient) throws IOException {
for (int n = 0; n < mappings.values().iterator().next().size(); n++) {
List recurseUrls = new ArrayList<>();
for (Map.Entry> entry : mappings.entrySet()) {
recurseUrls.add(entry.getValue().pop());
}
if ( ! equalOutputs(performRequests(recurseUrls, httpClient)))
return -1;
}
return 0;
}
private static boolean equalOutputs(Map outputs) {
Map.Entry firstEntry = outputs.entrySet().iterator().next();
for (Map.Entry entry : outputs.entrySet()) {
if (!entry.getValue().equals(firstEntry.getValue())) {
System.out.println("output from '" + entry.getKey() + "': '" + entry.getValue() +
"' did not equal output from '" + firstEntry.getKey() + "': '" + firstEntry.getValue() + "'");
return false;
}
}
return true;
}
private static String performRequest(String url, CloseableHttpClient httpClient) throws IOException {
return httpClient.execute(new HttpGet(url), new BasicHttpClientResponseHandler());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy