mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2025-02-25 18:55:28 -06:00
auto create apikey
This commit is contained in:
parent
cfa92eabcc
commit
3d2ff55f1c
@ -21,17 +21,28 @@ public class GrafanaClientConfig {
|
|||||||
@JsonProperty("baseuri")
|
@JsonProperty("baseuri")
|
||||||
private URI baseUrl;
|
private URI baseUrl;
|
||||||
|
|
||||||
@JsonProperty("timeoutms")
|
@JsonProperty("timeoutms" )
|
||||||
private int timeoutms;
|
private int timeoutms;
|
||||||
|
|
||||||
private final List<Authenticator> authenticators = new ArrayList<>();
|
private final List<Authenticator> authenticators = new ArrayList<>();
|
||||||
// private LinkedHashMap<String,String> headers = new LinkedHashMap<>();
|
|
||||||
private final List<Supplier<Map<String, String>>> headerSources = new ArrayList<>();
|
private final List<Supplier<Map<String, String>>> headerSources = new ArrayList<>();
|
||||||
|
|
||||||
public GrafanaClientConfig() {
|
public GrafanaClientConfig() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void basicAuth(String username, String pw) {
|
private GrafanaClientConfig(URI baseUrl, int timeoutms, List<Authenticator> authenticators,
|
||||||
|
List<Supplier<Map<String, String>>> headerSources) {
|
||||||
|
this.baseUrl = baseUrl;
|
||||||
|
this.timeoutms = timeoutms;
|
||||||
|
this.authenticators.addAll(authenticators);
|
||||||
|
this.headerSources.addAll(headerSources);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GrafanaClientConfig copy() {
|
||||||
|
return new GrafanaClientConfig(baseUrl, timeoutms, authenticators, headerSources);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GrafanaClientConfig basicAuth(String username, String pw) {
|
||||||
Objects.requireNonNull(username);
|
Objects.requireNonNull(username);
|
||||||
String authPw = pw != null ? pw : "";
|
String authPw = pw != null ? pw : "";
|
||||||
|
|
||||||
@ -44,9 +55,9 @@ public class GrafanaClientConfig {
|
|||||||
|
|
||||||
addAuthenticator(basicAuth);
|
addAuthenticator(basicAuth);
|
||||||
addHeader("Authorization", encodeBasicAuth(username, authPw));
|
addHeader("Authorization", encodeBasicAuth(username, authPw));
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public GrafanaClientConfig addAuthenticator(Authenticator authenticator) {
|
public GrafanaClientConfig addAuthenticator(Authenticator authenticator) {
|
||||||
authenticators.add(authenticator);
|
authenticators.add(authenticator);
|
||||||
return this;
|
return this;
|
||||||
@ -87,7 +98,9 @@ public class GrafanaClientConfig {
|
|||||||
|
|
||||||
public HttpClient newClient() {
|
public HttpClient newClient() {
|
||||||
HttpClient.Builder cb = HttpClient.newBuilder();
|
HttpClient.Builder cb = HttpClient.newBuilder();
|
||||||
|
if (timeoutms > 0) {
|
||||||
cb.connectTimeout(Duration.ofMillis(timeoutms));
|
cb.connectTimeout(Duration.ofMillis(timeoutms));
|
||||||
|
}
|
||||||
for (Authenticator authenticator : authenticators) {
|
for (Authenticator authenticator : authenticators) {
|
||||||
cb.authenticator(authenticator);
|
cb.authenticator(authenticator);
|
||||||
}
|
}
|
||||||
@ -106,8 +119,11 @@ public class GrafanaClientConfig {
|
|||||||
public HttpRequest.Builder newRequest(String path) {
|
public HttpRequest.Builder newRequest(String path) {
|
||||||
URI requestUri = makeUri(path);
|
URI requestUri = makeUri(path);
|
||||||
HttpRequest.Builder rqb = HttpRequest.newBuilder(requestUri);
|
HttpRequest.Builder rqb = HttpRequest.newBuilder(requestUri);
|
||||||
|
if (timeoutms > 0) {
|
||||||
rqb.timeout(Duration.ofMillis(timeoutms));
|
rqb.timeout(Duration.ofMillis(timeoutms));
|
||||||
|
}
|
||||||
getHeaders().forEach(rqb::setHeader);
|
getHeaders().forEach(rqb::setHeader);
|
||||||
|
|
||||||
return rqb;
|
return rqb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package io.nosqlbench.engine.core.metrics;
|
package io.nosqlbench.engine.clients.grafana;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
@ -10,15 +10,18 @@ import java.nio.file.Path;
|
|||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class GrafanaKeyFileReader implements Supplier<String> {
|
public class GrafanaKeyFileReader implements Supplier<String> {
|
||||||
private final static Logger logger = LogManager.getLogger("ANNOTATORS");
|
private final static Logger logger = LogManager.getLogger("ANNOTATORS" );
|
||||||
|
|
||||||
private final Path keyfilePath;
|
private final Path keyfilePath;
|
||||||
|
|
||||||
|
public GrafanaKeyFileReader(Path path) {
|
||||||
|
this.keyfilePath = path;
|
||||||
|
}
|
||||||
|
|
||||||
public GrafanaKeyFileReader(String sourcePath) {
|
public GrafanaKeyFileReader(String sourcePath) {
|
||||||
this.keyfilePath = Path.of(sourcePath);
|
this.keyfilePath = Path.of(sourcePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String get() {
|
public String get() {
|
||||||
if (!Files.exists(keyfilePath)) {
|
if (!Files.exists(keyfilePath)) {
|
||||||
@ -27,6 +30,7 @@ public class GrafanaKeyFileReader implements Supplier<String> {
|
|||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
String apikey = Files.readString(keyfilePath, StandardCharsets.UTF_8);
|
String apikey = Files.readString(keyfilePath, StandardCharsets.UTF_8);
|
||||||
|
apikey = apikey.trim();
|
||||||
return apikey;
|
return apikey;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
@ -1,26 +1,29 @@
|
|||||||
package io.nosqlbench.engine.core.metrics;
|
package io.nosqlbench.engine.clients.grafana;
|
||||||
|
|
||||||
import io.nosqlbench.engine.clients.grafana.GrafanaClient;
|
|
||||||
import io.nosqlbench.engine.clients.grafana.GrafanaClientConfig;
|
|
||||||
import io.nosqlbench.engine.clients.grafana.transfer.GrafanaAnnotation;
|
import io.nosqlbench.engine.clients.grafana.transfer.GrafanaAnnotation;
|
||||||
import io.nosqlbench.nb.annotations.Service;
|
import io.nosqlbench.nb.annotations.Service;
|
||||||
|
import io.nosqlbench.nb.api.Environment;
|
||||||
|
import io.nosqlbench.nb.api.OnError;
|
||||||
|
import io.nosqlbench.nb.api.SystemId;
|
||||||
import io.nosqlbench.nb.api.annotations.Annotation;
|
import io.nosqlbench.nb.api.annotations.Annotation;
|
||||||
import io.nosqlbench.nb.api.annotations.Annotator;
|
import io.nosqlbench.nb.api.annotations.Annotator;
|
||||||
import io.nosqlbench.nb.api.config.*;
|
import io.nosqlbench.nb.api.config.*;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@Service(value = Annotator.class, selector = "grafana")
|
@Service(value = Annotator.class, selector = "grafana" )
|
||||||
public class GrafanaMetricsAnnotator implements Annotator, ConfigAware {
|
public class GrafanaMetricsAnnotator implements Annotator, ConfigAware {
|
||||||
|
|
||||||
private final static Logger logger = LogManager.getLogger("ANNOTATORS");
|
private final static Logger logger = LogManager.getLogger("ANNOTATORS" );
|
||||||
private final static Logger annotationsLog = LogManager.getLogger("ANNOTATIONS");
|
private final static Logger annotationsLog = LogManager.getLogger("ANNOTATIONS" );
|
||||||
private OnError onError = OnError.Warn;
|
private OnError onError = OnError.Warn;
|
||||||
|
|
||||||
private GrafanaClient client;
|
private GrafanaClient client;
|
||||||
@ -38,43 +41,43 @@ public class GrafanaMetricsAnnotator implements Annotator, ConfigAware {
|
|||||||
ga.setTimeEnd(annotation.getEnd());
|
ga.setTimeEnd(annotation.getEnd());
|
||||||
|
|
||||||
annotation.getLabels().forEach((k, v) -> {
|
annotation.getLabels().forEach((k, v) -> {
|
||||||
ga.getTags().put(k, v);
|
ga.getTags().add(k + ":" + v);
|
||||||
});
|
});
|
||||||
ga.getTags().put("layer", annotation.getLayer().toString());
|
ga.getTags().add("layer:" + annotation.getLayer().toString());
|
||||||
|
|
||||||
Map<String, String> labels = annotation.getLabels();
|
Map<String, String> labels = annotation.getLabels();
|
||||||
|
|
||||||
Optional.ofNullable(labels.get("alertId"))
|
Optional.ofNullable(labels.get("alertId" ))
|
||||||
.map(Integer::parseInt).ifPresent(ga::setAlertId);
|
.map(Integer::parseInt).ifPresent(ga::setAlertId);
|
||||||
|
|
||||||
ga.setData(annotation.toString());
|
ga.setText(annotation.toString());
|
||||||
|
|
||||||
annotation.getSession();
|
annotation.getSession();
|
||||||
|
|
||||||
|
|
||||||
// Target
|
// Target
|
||||||
Optional.ofNullable(labels.get("type"))
|
Optional.ofNullable(labels.get("type" ))
|
||||||
.ifPresent(ga::setType);
|
.ifPresent(ga::setType);
|
||||||
|
|
||||||
Optional.ofNullable(labels.get("id")).map(Integer::valueOf)
|
Optional.ofNullable(labels.get("id" )).map(Integer::valueOf)
|
||||||
.ifPresent(ga::setId);
|
.ifPresent(ga::setId);
|
||||||
|
|
||||||
Optional.ofNullable(labels.get("alertId")).map(Integer::valueOf)
|
Optional.ofNullable(labels.get("alertId" )).map(Integer::valueOf)
|
||||||
.ifPresent(ga::setAlertId);
|
.ifPresent(ga::setAlertId);
|
||||||
|
|
||||||
Optional.ofNullable(labels.get("dashboardId")).map(Integer::valueOf)
|
Optional.ofNullable(labels.get("dashboardId" )).map(Integer::valueOf)
|
||||||
.ifPresent(ga::setDashboardId);
|
.ifPresent(ga::setDashboardId);
|
||||||
|
|
||||||
Optional.ofNullable(labels.get("panelId")).map(Integer::valueOf)
|
Optional.ofNullable(labels.get("panelId" )).map(Integer::valueOf)
|
||||||
.ifPresent(ga::setPanelId);
|
.ifPresent(ga::setPanelId);
|
||||||
|
|
||||||
Optional.ofNullable(labels.get("userId")).map(Integer::valueOf)
|
Optional.ofNullable(labels.get("userId" )).map(Integer::valueOf)
|
||||||
.ifPresent(ga::setUserId);
|
.ifPresent(ga::setUserId);
|
||||||
|
|
||||||
Optional.ofNullable(labels.get("userName"))
|
Optional.ofNullable(labels.get("userName" ))
|
||||||
.ifPresent(ga::setUserName);
|
.ifPresent(ga::setUserName);
|
||||||
|
|
||||||
Optional.ofNullable(labels.get("metric"))
|
Optional.ofNullable(labels.get("metric" ))
|
||||||
.ifPresent(ga::setMetric);
|
.ifPresent(ga::setMetric);
|
||||||
|
|
||||||
// Details
|
// Details
|
||||||
@ -107,60 +110,81 @@ public class GrafanaMetricsAnnotator implements Annotator, ConfigAware {
|
|||||||
GrafanaClientConfig gc = new GrafanaClientConfig();
|
GrafanaClientConfig gc = new GrafanaClientConfig();
|
||||||
gc.setBaseUri(cfg.param("baseurl", String.class));
|
gc.setBaseUri(cfg.param("baseurl", String.class));
|
||||||
|
|
||||||
if (cfg.containsKey("tags")) {
|
if (cfg.containsKey("tags" )) {
|
||||||
this.tags = ParamsParser.parse(cfg.param("tags", String.class), false);
|
this.tags = ParamsParser.parse(cfg.param("tags", String.class), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cfg.containsKey("apikeyfile")) {
|
if (cfg.containsKey("username" )) {
|
||||||
String apikeyfile = cfg.paramEnv("apikeyfile", String.class);
|
if (cfg.containsKey("password" )) {
|
||||||
AuthWrapper authHeaderSupplier = new AuthWrapper(
|
|
||||||
"Authorization",
|
|
||||||
new GrafanaKeyFileReader(apikeyfile),
|
|
||||||
s -> "Bearer " + s + ";"
|
|
||||||
);
|
|
||||||
gc.addHeaderSource(authHeaderSupplier);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cfg.containsKey("apikey")) {
|
|
||||||
gc.addHeaderSource(() -> Map.of("Authorization", "Bearer " + cfg.param("apikey", String.class)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cfg.containsKey("username")) {
|
|
||||||
if (cfg.containsKey("password")) {
|
|
||||||
gc.basicAuth(
|
gc.basicAuth(
|
||||||
cfg.param("username", String.class),
|
cfg.param("username", String.class),
|
||||||
cfg.param("password", String.class)
|
cfg.param("password", String.class)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
gc.basicAuth(cfg.param("username", String.class), "");
|
gc.basicAuth(cfg.param("username", String.class), "" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.onError = OnError.valueOfName(cfg.get("onerror").toString());
|
Path keyfilePath = null;
|
||||||
|
if (cfg.containsKey("apikeyfile" )) {
|
||||||
|
String apikeyfile = cfg.paramEnv("apikeyfile", String.class);
|
||||||
|
keyfilePath = Path.of(apikeyfile);
|
||||||
|
} else if (cfg.containsKey("apikey" )) {
|
||||||
|
gc.addHeaderSource(() -> Map.of("Authorization", "Bearer " + cfg.param("apikey", String.class)));
|
||||||
|
} else {
|
||||||
|
Optional<String> apikeyLocation = Environment.INSTANCE.interpolate("$NBSTATEDIR/grafana_apikey" );
|
||||||
|
keyfilePath = apikeyLocation.map(Path::of).orElseThrow();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Files.exists(keyfilePath)) {
|
||||||
|
logger.info("Auto-configuring grafana apikey." );
|
||||||
|
GrafanaClientConfig apiClientConf = gc.copy().basicAuth("admin", "admin" );
|
||||||
|
GrafanaClient apiClient = new GrafanaClient(apiClientConf);
|
||||||
|
try {
|
||||||
|
String nodeId = SystemId.getNodeId();
|
||||||
|
|
||||||
|
String keyName = "nosqlbench-" + nodeId + "-" + System.currentTimeMillis();
|
||||||
|
ApiToken apiToken = apiClient.createApiToken(keyName, "Admin", Long.MAX_VALUE);
|
||||||
|
Files.writeString(keyfilePath, apiToken.getKey());
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthWrapper authHeaderSupplier = new AuthWrapper(
|
||||||
|
"Authorization",
|
||||||
|
new GrafanaKeyFileReader(keyfilePath),
|
||||||
|
s -> "Bearer " + s
|
||||||
|
);
|
||||||
|
gc.addHeaderSource(authHeaderSupplier);
|
||||||
|
|
||||||
|
this.onError = OnError.valueOfName(cfg.get("onerror" ).toString());
|
||||||
|
|
||||||
this.client = new GrafanaClient(gc);
|
this.client = new GrafanaClient(gc);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConfigModel getConfigModel() {
|
public ConfigModel getConfigModel() {
|
||||||
return new MutableConfigModel(this)
|
return new MutableConfigModel(this)
|
||||||
.required("baseurl", String.class,
|
.required("baseurl", String.class,
|
||||||
"The base url of the grafana node, like http://localhost:3000/")
|
"The base url of the grafana node, like http://localhost:3000/" )
|
||||||
.defaultto("apikeyfile", "$NBSTATEDIR/grafana_key",
|
.defaultto("apikeyfile", "$NBSTATEDIR/grafana_apikey",
|
||||||
"The file that contains the api key, supersedes apikey")
|
"The file that contains the api key, supersedes apikey" )
|
||||||
.optional("apikey", String.class,
|
.optional("apikey", String.class,
|
||||||
"The api key to use, supersedes basic username and password")
|
"The api key to use, supersedes basic username and password" )
|
||||||
.optional("username", String.class,
|
.optional("username", String.class,
|
||||||
"The username to use for basic auth")
|
"The username to use for basic auth" )
|
||||||
.optional("password", String.class,
|
.optional("password", String.class,
|
||||||
"The password to use for basic auth")
|
"The password to use for basic auth" )
|
||||||
.defaultto("tags", "source:nosqlbench",
|
.defaultto("tags", "source:nosqlbench",
|
||||||
"The tags that identify the annotations, in k:v,... form")
|
"The tags that identify the annotations, in k:v,... form" )
|
||||||
// .defaultto("onerror", OnError.Warn)
|
// .defaultto("onerror", OnError.Warn)
|
||||||
.defaultto("onerror", "warn",
|
.defaultto("onerror", "warn",
|
||||||
"What to do when an error occurs while posting an annotation")
|
"What to do when an error occurs while posting an annotation" )
|
||||||
.defaultto("timeoutms", 5000,
|
.defaultto("timeoutms", 5000,
|
||||||
"connect and transport timeout for the HTTP client")
|
"connect and transport timeout for the HTTP client" )
|
||||||
.asReadOnly();
|
.asReadOnly();
|
||||||
}
|
}
|
||||||
|
|
@ -17,7 +17,8 @@ public class GrafanaAnnotation {
|
|||||||
private String text;
|
private String text;
|
||||||
private String metric;
|
private String metric;
|
||||||
private String type;
|
private String type;
|
||||||
private Map<String, String> tags = new LinkedHashMap<>();
|
private final List<String> tags = new ArrayList<>();
|
||||||
|
// private Map<String, String> tags = new LinkedHashMap<>();
|
||||||
private Object data;
|
private Object data;
|
||||||
|
|
||||||
public Integer getId() {
|
public Integer getId() {
|
||||||
@ -124,12 +125,22 @@ public class GrafanaAnnotation {
|
|||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getTags() {
|
public List<String> getTags() {
|
||||||
return tags;
|
return tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addTag(String tag) {
|
||||||
|
this.tags.add(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTags(List<String> tags) {
|
||||||
|
tags.forEach(this::addTag);
|
||||||
|
}
|
||||||
|
|
||||||
public void setTags(Map<String, String> tags) {
|
public void setTags(Map<String, String> tags) {
|
||||||
this.tags = tags;
|
tags.forEach((k, v) -> {
|
||||||
|
this.addTag(k + ":" + v);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getData() {
|
public Object getData() {
|
||||||
|
@ -31,10 +31,18 @@ public class ConfigReader extends LinkedHashMap<String, Object> {
|
|||||||
Object o = get(name);
|
Object o = get(name);
|
||||||
ConfigElement<?> elem = configModel.getElements().get(name);
|
ConfigElement<?> elem = configModel.getElements().get(name);
|
||||||
if (elem == null) {
|
if (elem == null) {
|
||||||
throw new RuntimeException("Invalid config element named '" + name + "'");
|
throw new RuntimeException("Invalid config element named '" + name + "'" );
|
||||||
}
|
}
|
||||||
Class<T> type = (Class<T>) elem.getType();
|
Class<T> type = (Class<T>) elem.getType();
|
||||||
T typeCastedValue = type.cast(o);
|
T typeCastedValue = type.cast(o);
|
||||||
return typeCastedValue;
|
return typeCastedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(this.configModel.getOf().getSimpleName()).append(":" );
|
||||||
|
sb.append(this.configModel.toString());
|
||||||
|
return sb.toString();
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user