This commit is contained in:
lucio 2023-03-31 14:16:23 +02:00
parent 766238c8e3
commit be3d37d6c3
22 changed files with 157 additions and 192 deletions

View File

@ -0,0 +1,2 @@
[smartgears]
version = ${version}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<smartgears version="${project.version}"/>

15
pom.xml
View File

@ -28,8 +28,8 @@
<tomcat.version>8.0.42</tomcat.version>
<jersey.version>2.25.1</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<scm>
<connection>scm:git:https://code-repo.d4science.org/gCubeSystem/common-smartgears.git</connection>
@ -106,10 +106,6 @@
<groupId>org.gcube.common.security</groupId>
<artifactId>gcube-secrets</artifactId>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
@ -151,12 +147,7 @@
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
<version>2.25.1</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -0,0 +1,15 @@
package org.gcube.smartgears.configuration;
public class SmartgearsConfiguration {
private String version;
public SmartgearsConfiguration(String version) {
super();
this.version = version;
}
public String getVersion() {
return version;
}
}

View File

@ -48,9 +48,9 @@ public class ApplicationConfiguration {
private boolean proxable = true;
Set<GCubeExclude> excludes= null;
Set<GCubeExclude> excludes= new HashSet<>();
Set<GCubeInclude> includes= null;
Set<GCubeInclude> includes= new HashSet<>();
@NotEmpty @JsonProperty("persistence")
PersistenceConfiguration persistenceConfiguration;
@ -103,12 +103,12 @@ public class ApplicationConfiguration {
return this;
}
public String serviceClass() {
public String group() {
return group;
}
public ApplicationConfiguration serviceClass(String group) {
public ApplicationConfiguration group(String group) {
this.group=group;
return this;
}

View File

@ -1,16 +1,21 @@
package org.gcube.smartgears.configuration.application;
import java.io.File;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
import org.gcube.smartgears.configuration.PersistenceConfiguration;
import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler;
import org.gcube.smartgears.handlers.application.RequestHandler;
import org.gcube.smartgears.handlers.application.lifecycle.ApplicationProfileManager;
import org.gcube.smartgears.handlers.application.request.RequestAccounting;
import org.gcube.smartgears.handlers.application.request.RequestMetrics;
import org.gcube.smartgears.handlers.application.request.RequestValidator;
import org.gcube.smartgears.persistence.LocalWriter;
import org.gcube.smartgears.persistence.LocalWriterConfiguration;
import org.gcube.smartgears.utils.Utils;
import org.yaml.snakeyaml.Yaml;
/**
@ -33,9 +38,22 @@ public class ApplicationConfigurationBinder {
Yaml yaml = new Yaml();
ObjectMapper mapper = new ObjectMapper();
String mapAsString = mapper.writeValueAsString(yaml.load(stream));
return mapper.readValue(mapAsString, ApplicationConfiguration.class);
}catch (Exception e) {
ApplicationConfiguration conf = mapper.readValue(mapAsString, ApplicationConfiguration.class);
if (conf.persistenceConfiguration() == null) {
String location = String.format("%s/state/%s_%s", Utils.home(), conf.group(), conf.name());
File dir = new File(location);
if (!dir.exists())
dir.mkdirs();
conf.persistenceConfiguration(
new PersistenceConfiguration(LocalWriter.class, new LocalWriterConfiguration(location)));
}
return conf;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@ -50,80 +68,79 @@ public class ApplicationConfigurationBinder {
public ApplicationHandlers bindHandlers(ClassLoader classLoader) {
List<RequestHandler> requestHandlers = new LinkedList<RequestHandler>();
//ADDING BASE Handler (order is important)
// ADDING BASE Handler (order is important)
requestHandlers.add(new RequestMetrics());
requestHandlers.add(new RequestValidator());
requestHandlers.add(new RequestAccounting());
//TODO scan RequestHAndler form classloader
// TODO scan RequestHAndler form classloader
List<ApplicationLifecycleHandler> lifecycleHandlers = new LinkedList<ApplicationLifecycleHandler>();
//ADDING BASE Handler (order is important)
// ADDING BASE Handler (order is important)
lifecycleHandlers.add(new ApplicationProfileManager());
//TODO scan ApplicationLifecycleHandler form classloader
// TODO scan ApplicationLifecycleHandler form classloader
return new ApplicationHandlers(lifecycleHandlers, requestHandlers);
}
/**
* Returns the extensions of the application from their XML serialisation.
*
* @param stream the serialisation
* @return the extensions
* @throws RuntimeException if the serialisation is invalid
public ApplicationExtensions bindExtensions(InputStream stream) {
*
* public ApplicationExtensions
* bindExtensions(InputStream stream) {
*
* //collects handler classes Set<Class<?>> classes =
* scanForExtensions();
*
* try {
*
* JAXBContext ctx =
* JAXBContext.newInstance(classes.toArray(new
* Class<?>[0]));
*
* return (ApplicationExtensions)
* ctx.createUnmarshaller().unmarshal(stream);
*
* } catch (JAXBException e) {
*
* throw unchecked(e);
*
* } finally { closeSafely(stream); } }
*
*
*
* private Set<Class<?>> scanForExtensions() throws
* RuntimeException {
*
* @SuppressWarnings("all")
* ServiceLoader<ApplicationExtension> handlerLoader =
* (ServiceLoader)
* ServiceLoader.load(ApplicationExtension.class);
*
* Set<Class<?>> scanned = new HashSet<Class<?>>();
*
* for (ApplicationExtension handler : handlerLoader) {
* Class<?> handlerClass = handler.getClass(); if
* (handlerClass.isInterface() ||
* handlerClass.getModifiers() == Modifier.ABSTRACT)
* continue; else scanned.add(handlerClass); }
*
* //add top-level configuration
* scanned.add(ApplicationExtensions.class);
*
* return scanned; }
*/
//collects handler classes
Set<Class<?>> classes = scanForExtensions();
try {
JAXBContext ctx = JAXBContext.newInstance(classes.toArray(new Class<?>[0]));
return (ApplicationExtensions) ctx.createUnmarshaller().unmarshal(stream);
} catch (JAXBException e) {
throw unchecked(e);
}
finally {
closeSafely(stream);
}
}
private Set<Class<?>> scanForExtensions() throws RuntimeException {
@SuppressWarnings("all")
ServiceLoader<ApplicationExtension> handlerLoader = (ServiceLoader) ServiceLoader.load(ApplicationExtension.class);
Set<Class<?>> scanned = new HashSet<Class<?>>();
for (ApplicationExtension handler : handlerLoader) {
Class<?> handlerClass = handler.getClass();
if (handlerClass.isInterface() || handlerClass.getModifiers() == Modifier.ABSTRACT)
continue;
else
scanned.add(handlerClass);
}
//add top-level configuration
scanned.add(ApplicationExtensions.class);
return scanned;
}
*/
public void scanForApplicationHandlers(ClassLoader currentClassLoader) {
// TODO Auto-generated method stub
}
}

View File

@ -14,6 +14,7 @@ import org.gcube.smartgears.configuration.ComponentConfiguration;
import org.gcube.smartgears.configuration.ConfiguredWith;
import org.gcube.smartgears.configuration.PersistenceConfiguration;
import org.gcube.smartgears.configuration.ProxyAddress;
import org.gcube.smartgears.configuration.SmartgearsConfiguration;
import org.gcube.smartgears.handlers.container.ContainerHandler;
import org.gcube.smartgears.handlers.container.lifecycle.AccountingManager;
import org.gcube.smartgears.handlers.container.lifecycle.ContainerProfileManager;
@ -194,4 +195,14 @@ public class ContainerConfigurationBinder {
return Collections.emptyList();
}
public SmartgearsConfiguration loadSmartgearsProperty() {
try {
Ini configurator = new Ini(this.getClass().getResourceAsStream("smartgears-config.ini"));
String version = configurator.get("smartgears").get("version");
return new SmartgearsConfiguration(version);
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@ -1,75 +0,0 @@
package org.gcube.smartgears.configuration.library;
import java.util.ArrayList;
import java.util.List;
import org.gcube.common.validator.ValidationError;
import org.gcube.common.validator.Validator;
import org.gcube.common.validator.ValidatorFactory;
import org.gcube.common.validator.annotations.NotEmpty;
public class SmartGearsConfiguration {
@NotEmpty
private String version;
public SmartGearsConfiguration(){
}
public String version() {
return version;
}
public SmartGearsConfiguration version(String version) {
this.version=version;
return this;
}
/**
* Validates this configuration
*
* @throws IllegalStateException if the configuration is invalid
*/
public void validate() {
List<String> msgs = new ArrayList<String>();
Validator validator = ValidatorFactory.validator();
for (ValidationError error : validator.validate(this))
msgs.add(error.toString());
if (!msgs.isEmpty())
throw new IllegalStateException("invalid configuration: "+msgs);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((version == null) ? 0 : version.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SmartGearsConfiguration other = (SmartGearsConfiguration) obj;
if (version == null) {
if (other.version != null)
return false;
} else if (!version.equals(other.version))
return false;
return true;
}
}

View File

@ -75,7 +75,6 @@ public class HttpController extends HttpExtension {
@Override
public void stop(){
super.stop();
for (ApiResource resource : resources.values())
resource.stop();

View File

@ -6,7 +6,6 @@ import java.util.HashSet;
import java.util.Set;
import javax.servlet.http.HttpServlet;
import javax.ws.rs.HttpMethod;
import org.gcube.common.validator.annotations.NotEmpty;
import org.gcube.smartgears.configuration.application.GCubeExclude;
@ -26,12 +25,12 @@ public abstract class HttpExtension extends HttpServlet implements ApplicationEx
*
*/
public static enum Method {
GET(HttpMethod.GET),
PUT(HttpMethod.PUT),
POST(HttpMethod.POST),
HEAD(HttpMethod.HEAD),
DELETE(HttpMethod.DELETE),
OPTIONS(HttpMethod.OPTIONS);
GET("GET"),
PUT("PUT"),
POST("POST"),
HEAD("HEAD"),
DELETE("DELETE"),
OPTIONS("OPTIONS");
private String value;

View File

@ -1,6 +1,6 @@
package org.gcube.smartgears.extensions.resource;
import static org.gcube.smartgears.Constants.application_xml;
import static org.gcube.smartgears.Constants.application_json;
import static org.gcube.smartgears.extensions.HttpExtension.Method.GET;
import java.io.IOException;
@ -9,7 +9,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.gcube.common.resources.gcore.Resources;
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
import org.gcube.smartgears.configuration.application.ApplicationConfiguration;
import org.gcube.smartgears.extensions.ApiResource;
import org.gcube.smartgears.extensions.ApiSignature;
@ -26,7 +26,7 @@ public class ConfigurationResource extends ApiResource {
public static final String mapping = "/configuration";
private static final ApiSignature signature = handles(mapping).with(method(GET).produces(application_xml));
private static final ApiSignature signature = handles(mapping).with(method(GET).produces(application_json));
ConfigurationResource() {
super(signature);
@ -37,7 +37,7 @@ public class ConfigurationResource extends ApiResource {
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ApplicationConfiguration config = context().configuration();
Resources.marshal(config,resp.getWriter());
new ObjectMapper().writeValue(resp.getWriter(), config);
}
}

View File

@ -21,6 +21,7 @@ import javax.servlet.http.HttpServletResponse;
import org.gcube.smartgears.extensions.ApiResource;
import org.gcube.smartgears.extensions.ApiSignature;
import org.gcube.smartgears.provider.ProviderFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -92,7 +93,7 @@ public class FrontPageResource extends ApiResource {
values.put("status", context().lifecycle().state().toString());
//values.put("smartgears-version", provider().smartgearsConfiguration().version());
values.put("smartgears-version", ProviderFactory.provider().smartgearsConfiguration().getVersion());
return values;
}

View File

@ -19,7 +19,6 @@ import org.gcube.common.health.api.ReadinessChecker;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.extensions.ApiResource;
import org.gcube.smartgears.extensions.ApiSignature;
import org.gcube.smartgears.handlers.application.request.RequestError;
import org.gcube.smartgears.health.HealthManager;
import org.gcube.smartgears.health.HealthResponse;
import org.gcube.smartgears.health.HealthTask;
@ -39,8 +38,6 @@ public class HealthResource extends ApiResource {
public static final String mapping = "/health";
public static final String readiness_mapping = "/readiness";
private static final ApiSignature signature = handles(mapping).with(method(GET).produces(application_json));
private HealthManager manager;
@ -71,14 +68,14 @@ public class HealthResource extends ApiResource {
manager.register((HealthCheck) readnessClass.getDeclaredConstructor().newInstance());
log.info("added class {} to health manager", readnessClass.getCanonicalName());
} catch (Throwable e) {
log.error("healthChecher class {} cannot be instantiated", readnessClass.getCanonicalName(), e);
log.error("healthChecker class {} cannot be instantiated", readnessClass.getCanonicalName(), e);
}
task = new HealthTask(manager);
timer = new Timer(true);
timer.scheduleAtFixedRate(task, 0, 10000);
timer.scheduleAtFixedRate(task, 10000, 60000);
super.init(context);
}
@ -93,14 +90,7 @@ public class HealthResource extends ApiResource {
PrintWriter out = resp.getWriter();
resp.setContentType("application/json");
resp.setCharacterEncoding("UTF-8");
Object response = null;
String contextpath = req.getContextPath();
log.info("context path is {}", req.getContextPath());
if (contextpath.endsWith(readiness_mapping))
response = readiness();
else
RequestError.resource_notfound_error.fire();
HealthResponse response = readiness();
new ObjectMapper().writeValue(out, response);
@ -110,5 +100,6 @@ public class HealthResource extends ApiResource {
public HealthResponse readiness() {
return task.getResponse();
}
}

View File

@ -48,7 +48,7 @@ public class RequestAccounting extends RequestHandler {
startCallThreadLocal.set(System.currentTimeMillis());
log.info("REQUEST START ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} ", appContext.configuration().name(),
appContext.configuration().serviceClass(), InnerMethodName.instance.get(), caller,
appContext.configuration().group(), InnerMethodName.instance.get(), caller,
e.request().getRemoteHost(), context);
}
@ -90,7 +90,7 @@ public class RequestAccounting extends RequestHandler {
*/
log.info("REQUEST SERVED ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} {}(CODE {}) IN {} millis",
appContext.configuration().name(), appContext.configuration().serviceClass(),
appContext.configuration().name(), appContext.configuration().group(),
InnerMethodName.instance.get(), caller, callerIp, context, success ? "SUCCEDED" : "FAILED",
e.response().getStatus(), durationInMillis);
@ -115,7 +115,7 @@ public class RequestAccounting extends RequestHandler {
serviceUsageRecord.setConsumerId(caller);
serviceUsageRecord.setCallerQualifier(callerQualifier);
serviceUsageRecord.setScope(gcubeContext);
serviceUsageRecord.setServiceClass(appContext.configuration().serviceClass());
serviceUsageRecord.setServiceClass(appContext.configuration().group());
serviceUsageRecord.setServiceName(appContext.configuration().name());
serviceUsageRecord.setHost(appContext.container().configuration().hostname() + ":"

View File

@ -38,7 +38,6 @@ public class RequestMetrics extends RequestHandler {
public void handleResponse(ResponseEvent e) {
String statusCode = Integer.toString(e.response().getStatus());
Metrics.globalRegistry.timer(HTTP_REQUEST_METRICS_NAME, "status", statusCode).record(Duration.ofMillis(System.currentTimeMillis() - startCallThreadLocal.get()));
Metrics.globalRegistry.counter(HTTP_REQUEST_METRICS_NAME, "status", statusCode);
startCallThreadLocal.remove();
log.debug("metrics for current call saved");
}

View File

@ -1,12 +1,13 @@
package org.gcube.smartgears.health;
import java.util.LinkedList;
import java.util.List;
import org.gcube.common.health.api.HealthCheck;
public class HealthManager {
private List<HealthCheck> checks;
private List<HealthCheck> checks = new LinkedList<>();
public void register(HealthCheck check){
checks.add(check);

View File

@ -7,9 +7,13 @@ import java.util.stream.Collectors;
import org.gcube.common.health.api.HealthCheck;
import org.gcube.common.health.api.Status;
import org.gcube.common.health.api.response.HealthCheckResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HealthTask extends TimerTask{
private static final Logger log = LoggerFactory.getLogger(HealthTask.class);
private HealthResponse response;
private HealthManager healthManager;
@ -20,12 +24,14 @@ public class HealthTask extends TimerTask{
@Override
public void run() {
List<HealthCheck> checks = healthManager.getChecks();
List<HealthCheckResponse> responses = checks.stream().map(c -> this.wrap(c)).collect(Collectors.toList());
Status totalStatus = responses.stream().anyMatch(r -> r.getStatus().equals(Status.DOWN)) ? Status.DOWN : Status.UP;
this.response = new HealthResponse(totalStatus, responses);
log.debug("health task executed with total status {}",totalStatus);
}
public HealthResponse getResponse() {
@ -36,7 +42,7 @@ public class HealthTask extends TimerTask{
try {
return check.check();
}catch (Throwable t) {
return HealthCheckResponse.builder(check.getName()).down().withMessage("unexpected error executing check").build();
return HealthCheckResponse.builder(check.getName()).down().withMessage(t.getMessage()).build();
}
}

View File

@ -18,6 +18,7 @@ import javax.servlet.ServletContext;
import org.gcube.common.events.Hub;
import org.gcube.common.events.impl.DefaultHub;
import org.gcube.common.security.credentials.Credentials;
import org.gcube.smartgears.configuration.SmartgearsConfiguration;
import org.gcube.smartgears.configuration.application.ApplicationConfiguration;
import org.gcube.smartgears.configuration.application.ApplicationConfigurationBinder;
import org.gcube.smartgears.configuration.application.ApplicationHandlers;
@ -276,9 +277,17 @@ public class DefaultProvider implements Provider {
return this.publishers;
}
@Override
public SmartgearsConfiguration smartgearsConfiguration() {
ContainerConfigurationBinder binder = new ContainerConfigurationBinder();
return binder.loadSmartgearsProperty();
}
/*
* @Override public AuthorizationProvider authorizationProvider() { return
* containerContext.authorizationProvider(); }
*/
}

View File

@ -4,6 +4,7 @@ import java.util.List;
import javax.servlet.ServletContext;
import org.gcube.smartgears.configuration.SmartgearsConfiguration;
import org.gcube.smartgears.configuration.application.ApplicationHandlers;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.context.container.ContainerContext;
@ -67,5 +68,6 @@ public interface Provider {
List<ApplicationExtension> extensionsFor(ApplicationContext application);
SmartgearsConfiguration smartgearsConfiguration();
}

View File

@ -214,7 +214,7 @@ public class Utils {
public static ServiceInfo getServiceInfo(ApplicationContext application){
String hostedin = String.format("%s_%d", application.container().configuration().hostname(), application.container().configuration().port());
return
new ServiceInfo(new ServiceIdentifier(application.configuration().serviceClass(), application.configuration().name(), hostedin));
new ServiceInfo(new ServiceIdentifier(application.configuration().group(), application.configuration().name(), hostedin));
}
public static Throwable getCause(Throwable e) {

View File

@ -1 +0,0 @@
org.gcube.smartgears.extensions.resource.RemoteResource

View File

@ -42,14 +42,14 @@ public class ConfigurationTest {
InputStream inputStream = this.getClass()
.getClassLoader()
.getResourceAsStream("applicationTest.yaml");
ApplicationConfiguration customer = yaml.load(inputStream);
yaml.load(inputStream);
}
@Test
public void serialize() throws Exception{
ApplicationConfiguration configuration =new ApplicationConfiguration();
configuration.name("test").serviceClass("group").description("pippo").version("1.0.0").excludes(new GCubeExclude("/pippo/*"), new GCubeExclude(List.of("H1","H2"), "/trip"));
configuration.name("test").group("group").description("pippo").version("1.0.0").excludes(new GCubeExclude("/pippo/*"), new GCubeExclude(List.of("H1","H2"), "/trip"));
configuration.persistenceConfiguration(new PersistenceConfiguration(LocalWriter.class, new LocalWriterConfiguration("/tmp")));
/*
ObjectMapper mapper = new ObjectMapper();