Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test webhooks & fixes #48

Merged
merged 13 commits into from
Dec 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ Note that this docker-compose script is intended for developer use; for producti
If you are using Podman (and podman-compose) rather than Docker, please use

```bash
podman-compose -f podman-compose.yaml -d
podman-compose -f podman-compose.yml up -d
```

> :warning: **If postgres fails to start**: clear any cached data in the postgresl container mounted volume `podman volume inspect Horreum_horreum_pg12 | jq -r '.[0].Mountpoint'`

Due to subtleties in Podman's rootless network configuration it's not possible to use `docker-compose.yaml`.

## Getting Started
Expand All @@ -29,6 +31,7 @@ cd webapp && npm install && cd ..

`localhost:3000` to access the create-react-app live code server and `localhost:8080` to access the quarkus development server.

> :warning: *If npm install fails*: please try clearing the node module cache `npm cache clean`
## Creating jar
```bash
./mvnw clean package -Dui
Expand Down
1 change: 1 addition & 0 deletions podman-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ services:
- -Dkeycloak.migration.strategy=IGNORE_EXISTING
- -Djboss.socket.binding.port-offset=100
- -Djboss.bind.address=127.0.0.1
- -Djboss.bind.address.private=127.0.0.1
environment:
- KEYCLOAK_USER=admin
- KEYCLOAK_PASSWORD=secret
Expand Down
4 changes: 4 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-image-jib</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-openapi</artifactId>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import io.hyperfoil.tools.yaup.StringUtil;
import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.rest.client.inject.RestClient;
Expand Down Expand Up @@ -188,7 +189,7 @@ private void onNewRun(Run run, boolean notify) {
extractionQuery.append("$.*");
}
// four colons to escape it for Hibernate
extractionQuery.append(jsonpath).append("'::::jsonpath)::::text as ").append(accessor);
extractionQuery.append(jsonpath).append("'::::jsonpath)::::text as ").append(StringUtil.quote(accessor, "\""));
var.accessors.add(accessor);
}
extractionQuery.append(" FROM current_run");
Expand Down Expand Up @@ -474,12 +475,12 @@ public void afterCompletion(int status) {
@PermitAll
@GET
@Path("variables")
public Response variables(@QueryParam("test") Integer testId) {
public List<Variable> variables(@QueryParam("test") Integer testId) {
try (@SuppressWarnings("unused") CloseMe closeMe = sqlService.withRoles(em, identity)) {
if (testId != null) {
return Response.ok(Variable.list("testid", testId)).build();
return Variable.list("testid", testId);
} else {
return Response.ok(Variable.listAll()).build();
return Variable.listAll();
}
}
}
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/io/hyperfoil/tools/horreum/api/HookService.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package io.hyperfoil.tools.horreum.api;

import io.hyperfoil.tools.horreum.JsonAdapter;
import io.hyperfoil.tools.horreum.entity.alerting.Change;
import io.hyperfoil.tools.horreum.entity.alerting.Variable;
import io.hyperfoil.tools.horreum.entity.json.Hook;
import io.hyperfoil.tools.horreum.entity.json.Run;
import io.hyperfoil.tools.horreum.entity.json.Test;
Expand All @@ -18,6 +20,7 @@
import org.jboss.logging.Logger;

import javax.annotation.PostConstruct;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
Expand Down Expand Up @@ -141,6 +144,14 @@ public void newRun(Run run) {
tellHooks(Run.EVENT_NEW, testId, run);
}

@Transactional
@ConsumeEvent(value = Change.EVENT_NEW, blocking = true)
public void newChange(Change.Event changeEvent) {
Integer runId = changeEvent.change.runId;
Run run = Run.find("id", runId).firstResult();
tellHooks(Change.EVENT_NEW, run.testid, changeEvent.change);
}

@RolesAllowed(Roles.ADMIN)
@POST
@Transactional
Expand Down Expand Up @@ -216,4 +227,16 @@ public List<Hook> list(@QueryParam("limit") Integer limit,
}
}

@RolesAllowed(Roles.ADMIN)
@GET
@Path("test/{id}")
public List<Hook> variables(@PathParam("id") Integer testId) {
try (@SuppressWarnings("unused") CloseMe closeMe = sqlService.withRoles(em, identity)) {
if (testId != null) {
return Hook.list("target", testId);
} else {
return Variable.listAll();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,18 @@ public void onNewChange(Change.Event event) {
log.infof("Received new change in test %d (%s), run %d, variable %d (%s)", variable.testId, testName, event.change.runId, variable.id, variable.name);

StringBuilder sb = new StringBuilder();
Json tagsObject = Json.fromString(String.valueOf(em.createNativeQuery("SELECT tags::::text FROM run_tags WHERE runid = ?")
.setParameter(1, event.change.runId)
.getSingleResult()));
tagsObject.forEach((key, value) -> {
if (sb.length() != 0) {
sb.append(';');
}
sb.append(key).append(':').append(value);
});
List<Object> tagsList = em.createNativeQuery("SELECT tags::::text FROM run_tags WHERE runid = ?")
.setParameter(1, event.change.runId)
.getResultList();
if( tagsList.size() > 0) {
Json tagsObject = Json.fromString(String.valueOf(tagsList.stream().findFirst().get()));
tagsObject.forEach((key, value) -> {
if (sb.length() != 0) {
sb.append(';');
}
sb.append(key).append(':').append(value);
});
}
String tags = sb.toString();

@SuppressWarnings("unchecked")
Expand Down
36 changes: 31 additions & 5 deletions src/main/java/io/hyperfoil/tools/horreum/api/TestService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@

import io.agroal.api.AgroalDataSource;
import io.hyperfoil.tools.horreum.entity.converter.JsonResultTransformer;
import io.hyperfoil.tools.horreum.entity.json.Access;
import io.hyperfoil.tools.horreum.entity.json.Test;
import io.hyperfoil.tools.horreum.entity.json.View;
import io.hyperfoil.tools.horreum.entity.json.ViewComponent;
import io.hyperfoil.tools.horreum.entity.json.*;
import io.quarkus.panache.common.Page;
import io.quarkus.panache.common.Sort;
import io.quarkus.security.identity.SecurityIdentity;
Expand Down Expand Up @@ -113,7 +110,7 @@ public Response add(Test test){
}

Response addAuthenticated(Test test) {
Test existing = Test.find("name", test.name).firstResult();
Test existing = Test.find("id", test.id).firstResult();
if (test.id != null && test.id <= 0) {
test.id = null;
}
Expand Down Expand Up @@ -260,4 +257,33 @@ public Response updateView(@PathParam("testId") Integer testId, View view) {
}
return Response.noContent().build();
}

@RolesAllowed("tester")
@POST
@Path("{testId}/hook")
public Response updateHook(@PathParam("testId") Integer testId, Hook hook) {
if (testId == null || testId <= 0) {
return Response.status(Response.Status.BAD_REQUEST).entity("Missing test id").build();
}
try (@SuppressWarnings("unused") CloseMe closeMe = sqlService.withRoles(em, identity)) {
Test test = Test.findById(testId);
if (test == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
hook.target = testId;

if (hook.id == null) {
em.persist(hook);
} else {
if (!hook.active) {
Hook toDelete = em.find(Hook.class, hook.id);
em.remove(toDelete);
} else {
em.merge(hook);
}
}
test.persist();
}
return Response.noContent().build();
}
}
11 changes: 3 additions & 8 deletions src/main/java/io/hyperfoil/tools/horreum/entity/json/Hook.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,8 @@
import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import io.quarkus.runtime.annotations.RegisterForReflection;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.json.bind.annotation.JsonbTransient;
import javax.persistence.*;
import javax.validation.constraints.NotNull;

@Entity
Expand Down Expand Up @@ -48,4 +42,5 @@ public class Hook extends PanacheEntityBase {

@NotNull
public boolean active;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.hyperfoil.tools.horreum.entity.json;

import io.hyperfoil.tools.horreum.entity.converter.AccessSerializer;
import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import io.quarkus.runtime.annotations.RegisterForReflection;

import javax.json.bind.annotation.JsonbTypeDeserializer;
import javax.json.bind.annotation.JsonbTypeSerializer;
import javax.persistence.MappedSuperclass;
import javax.validation.constraints.NotNull;

@RegisterForReflection
@MappedSuperclass
public abstract class ProtectedBaseEntity extends PanacheEntityBase {

@NotNull
public String owner;

public String token;

@NotNull
@JsonbTypeSerializer(AccessSerializer.class)
@JsonbTypeDeserializer(AccessSerializer.class)
public Access access = Access.PUBLIC;

}
21 changes: 7 additions & 14 deletions src/main/java/io/hyperfoil/tools/horreum/entity/json/Run.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
package io.hyperfoil.tools.horreum.entity.json;

import io.hyperfoil.tools.horreum.entity.converter.AccessSerializer;
import io.hyperfoil.tools.horreum.entity.converter.InstantSerializer;
import io.hyperfoil.tools.yaup.json.Json;
import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import io.quarkus.runtime.annotations.RegisterForReflection;
import org.hibernate.annotations.Type;

import javax.json.bind.annotation.JsonbTypeDeserializer;
import javax.json.bind.annotation.JsonbTypeSerializer;
import javax.persistence.*;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.validation.constraints.NotNull;
import java.time.Instant;

@Entity(name = "run")
@RegisterForReflection
public class Run extends PanacheEntityBase {
public class Run extends ProtectedBaseEntity {
public static final String EVENT_NEW = "run/new";
public static final String EVENT_TRASHED = "run/trashed";

Expand Down Expand Up @@ -49,16 +52,6 @@ public class Run extends PanacheEntityBase {
@Type(type = "io.hyperfoil.tools.horreum.entity.converter.JsonUserType")
public Json data;

@NotNull
public String owner;

public String token;

@NotNull
@JsonbTypeSerializer(AccessSerializer.class)
@JsonbTypeDeserializer(AccessSerializer.class)
public Access access = Access.PUBLIC;

@NotNull
@Column(columnDefinition = "boolean default false")
public boolean trashed;
Expand Down
15 changes: 1 addition & 14 deletions src/main/java/io/hyperfoil/tools/horreum/entity/json/Schema.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
package io.hyperfoil.tools.horreum.entity.json;

import io.hyperfoil.tools.horreum.entity.converter.AccessSerializer;
import io.hyperfoil.tools.yaup.json.Json;
import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import io.quarkus.runtime.annotations.RegisterForReflection;
import org.hibernate.annotations.Type;

import javax.json.bind.annotation.JsonbTypeDeserializer;
import javax.json.bind.annotation.JsonbTypeSerializer;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
Expand All @@ -24,7 +20,7 @@
name = "schema",
uniqueConstraints = @UniqueConstraint(columnNames = {"owner", "uri"})
)
public class Schema extends PanacheEntityBase {
public class Schema extends ProtectedBaseEntity {

@Id
@SequenceGenerator(
Expand Down Expand Up @@ -66,13 +62,4 @@ public class Schema extends PanacheEntityBase {
*/
public String descriptionPath;

@NotNull
public String owner;

public String token;

@NotNull
@JsonbTypeSerializer(AccessSerializer.class)
@JsonbTypeDeserializer(AccessSerializer.class)
public Access access;
}
25 changes: 9 additions & 16 deletions src/main/java/io/hyperfoil/tools/horreum/entity/json/Test.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
package io.hyperfoil.tools.horreum.entity.json;

import io.hyperfoil.tools.horreum.entity.converter.AccessSerializer;
import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import io.quarkus.runtime.annotations.RegisterForReflection;

import javax.json.bind.annotation.JsonbTypeDeserializer;
import javax.json.bind.annotation.JsonbTypeSerializer;
import javax.persistence.*;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.validation.constraints.NotNull;

@Entity(name="test")
@RegisterForReflection
public class Test extends PanacheEntityBase {
public class Test extends ProtectedBaseEntity {
public static final String EVENT_NEW = "test/new";

@Id
Expand All @@ -36,16 +39,6 @@ public class Test extends PanacheEntityBase {
@OneToOne(cascade = { CascadeType.REMOVE, CascadeType.MERGE })
public View defaultView;

@NotNull
public String owner;

public String token;

@NotNull
@JsonbTypeSerializer(AccessSerializer.class)
@JsonbTypeDeserializer(AccessSerializer.class)
public Access access = Access.PUBLIC;

public String compareUrl;

public void ensureLinked() {
Expand Down
Loading