Compare commits

..

No commits in common. "9414d5f07fbb780072ba25c35029a643510a7f0b" and "c8ecdce0e0881041f644d9107d5582bea8451363" have entirely different histories.

19 changed files with 64 additions and 143 deletions

4
Jenkinsfile vendored
View File

@ -3,8 +3,8 @@ pipeline {
environment { environment {
HARBOR_HOST = "harbor.dinauer.dev" HARBOR_HOST = "harbor.dinauer.dev"
PROJECT = "big-bucket" PROJECT = "metrics-service"
REPO = "core" REPO = "backend"
} }
stages { stages {

View File

@ -5,17 +5,18 @@ meta {
} }
get { get {
url: http://localhost:8080/api/metrics/POD-2/WORKLOAD?bucket-unit=TOTAL url: http://localhost:8080/api/metrics/POD-545444456/WORKLOAD?bucket-unit=TOTAL
body: none body: none
auth: bearer auth: basic
} }
params:query { params:query {
bucket-unit: TOTAL bucket-unit: TOTAL
} }
auth:bearer { auth:basic {
token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1cG4iOiJiMzk2ODFiMy0zMjNjLTQ3ZDctYjdmYS04MjM4NDc2MjlhZWMiLCJleHAiOjE3NjM5MzI4MjksImdyb3VwcyI6WyJBRE1JTiJdLCJpYXQiOjE3NjI2MzY4MjksImp0aSI6IjczY2UyZjQ2LTUwY2YtNGIyMS04MDMwLTRhY2YyNjQ3MzhiYSIsImlzcyI6Imh0dHBzOi8vcXVhcmt1cy5pby9pc3N1ZXIifQ.ihikbyPyg8Km2JYa6T0OW5O9fEaEHRcubJHBhbzLp5f068wA2PFqjJ5iJ81-v946OwahAZxv2zoiElt6F-e5kLGhnMAlZu55B1l7VuGQxNCsjw9CWE3d74LEcytzCbtzgs5hIR2111aP0YFMLgsCc8cvPBdXlEXDZaOCznPBW--dLDooNsrwmeA4j4kCYaFn2mcBfplIifNjxxwRajhRmXGKRw5_U1YMa-gjQ1O5vXcvlhijxPHT3C-BeR4Y8QEvjWmX-844K-ga1pt98eDU4Es51Lw5KVCkOJhgeibS0CllzZf0h95keTYCEseSFST-ldPDcBAUpsmwrcrDmTJPCQ username: kubooboo
password: 3749832748923748923
} }
settings { settings {

View File

@ -5,7 +5,7 @@ meta {
} }
post { post {
url: http://localhost:8080/api/metrics/POD-2/WORKLOAD url: http://localhost:8080/api/metrics/POD-545444456/WORKLOAD
body: json body: json
auth: basic auth: basic
} }
@ -15,18 +15,15 @@ headers {
} }
auth:basic { auth:basic {
username: michaeltheduck username: kubooboo
password: blabla password: 3749832748923748923
} }
body:json { body:json {
{ {
"owner": "kubooboo", "RELATIVE_CPU": "20",
"values": { "RELATIVE_MEMORY": "23",
"RELATIVE_CPU": "20", "RELATIVE_DISK_USAGE": "56"
"RELATIVE_MEMORY": "23",
"RELATIVE_DISK_USAGE": "56"
}
} }
} }

View File

@ -2,7 +2,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>dev.dinauer</groupId> <groupId>dev.dinauer</groupId>
<artifactId>big-bucket</artifactId> <artifactId>metrics-service</artifactId>
<version>1.0.0-SNAPSHOT</version> <version>1.0.0-SNAPSHOT</version>
<properties> <properties>

View File

@ -1,9 +0,0 @@
package dev.dinauer.metrics.service;
import java.util.Map;
import jakarta.validation.constraints.Size;
public record Insert(String owner, @Size(min = 1) Map<String, Double> values)
{
}

View File

@ -8,23 +8,23 @@ import jakarta.enterprise.context.ApplicationScoped;
import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase; import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase;
import io.quarkus.panache.common.Parameters; import io.quarkus.panache.common.Parameters;
import dev.dinauer.metrics.service.model.Bucket;
import dev.dinauer.metrics.service.model.BucketUnit; import dev.dinauer.metrics.service.model.BucketUnit;
import dev.dinauer.metrics.service.model.Collection;
@ApplicationScoped @ApplicationScoped
public class Repo implements PanacheRepositoryBase<Bucket, String> public class Repo implements PanacheRepositoryBase<Collection, String>
{ {
public Optional<Bucket> findByProperties(String resource, String name, String timestamp, BucketUnit bucketUnit) public Optional<Collection> findByProperties(String resource, String name, String timestamp, BucketUnit bucketUnit)
{ {
return find("resource = :resource AND name = :name AND timestamp = :timestamp AND bucketUnit = :bucketUnit", Parameters.with("resource", resource).and("name", name).and("timestamp", timestamp).and("bucketUnit", bucketUnit)).firstResultOptional(); return find("resource = :resource AND name = :name AND timestamp = :timestamp AND bucketUnit = :bucketUnit", Parameters.with("resource", resource).and("name", name).and("timestamp", timestamp).and("bucketUnit", bucketUnit)).firstResultOptional();
} }
public List<Bucket> findByResourceAndMetricAndTimeUnit(String resource, String name, BucketUnit bucketUnit) public List<Collection> findByResourceAndMetricAndTimeUnit(String resource, String name, BucketUnit bucketUnit)
{ {
return list("resource = :resource AND name = :name AND bucketUnit = :bucketUnit ORDER BY timestamp ASC", Parameters.with("resource", resource).and("name", name).and("bucketUnit", bucketUnit)); return list("resource = :resource AND name = :name AND bucketUnit = :bucketUnit ORDER BY timestamp ASC", Parameters.with("resource", resource).and("name", name).and("bucketUnit", bucketUnit));
} }
public List<Bucket> findByResourceAndMetricAndTimeUnitAndPeriod(String resource, String name, BucketUnit bucketUnit, Long from, Long to) public List<Collection> findByResourceAndMetricAndTimeUnitAndPeriod(String resource, String name, BucketUnit bucketUnit, Long from, Long to)
{ {
return list("resource = :resource AND name = :name AND bucketUnit = :bucketUnit AND (unix >= :from AND unix <= :to) ORDER BY timestamp ASC", Parameters.with("resource", resource).and("name", name).and("bucketUnit", bucketUnit).and("from", from).and("to", to)); return list("resource = :resource AND name = :name AND bucketUnit = :bucketUnit AND (unix >= :from AND unix <= :to) ORDER BY timestamp ASC", Parameters.with("resource", resource).and("name", name).and("bucketUnit", bucketUnit).and("from", from).and("to", to));
} }

View File

@ -1,14 +1,15 @@
package dev.dinauer.metrics.service; package dev.dinauer.metrics.service;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.ws.rs.*; import jakarta.ws.rs.*;
import dev.dinauer.metrics.service.client.auth.AuthenticationService; import dev.dinauer.metrics.service.client.auth.AuthenticationService;
import dev.dinauer.metrics.service.model.Bucket;
import dev.dinauer.metrics.service.model.BucketUnit; import dev.dinauer.metrics.service.model.BucketUnit;
import dev.dinauer.metrics.service.model.Collection;
@Path("/{resource}/{metric}") @Path("/{resource}/{metric}")
public class Resource public class Resource
@ -20,11 +21,11 @@ public class Resource
Service service; Service service;
@POST @POST
public void insert(@PathParam("resource") String resource, @PathParam("metric") String metric, Insert insert) public void insert(@PathParam("resource") String resource, @PathParam("metric") String metric, Map<String, Double> values)
{ {
if (authenticationService.canWrite()) if (authenticationService.canWrite())
{ {
service.index(resource, metric, insert.owner(), insert.values()); service.index(resource, metric, values);
} }
else else
{ {
@ -33,7 +34,7 @@ public class Resource
} }
@GET @GET
public List<Bucket> get(@PathParam("resource") String resource, @PathParam("metric") String metric, @QueryParam("bucket-unit") Optional<BucketUnit> bucketUnit) public List<Collection> get(@PathParam("resource") String resource, @PathParam("metric") String metric, @QueryParam("bucket-unit") Optional<BucketUnit> bucketUnit)
{ {
if (authenticationService.canRead()) if (authenticationService.canRead())
{ {

View File

@ -4,17 +4,13 @@ import java.time.Clock;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.transaction.Transactional; import jakarta.transaction.Transactional;
import jakarta.ws.rs.ForbiddenException;
import org.jboss.logging.Logger;
import dev.dinauer.metrics.service.model.Bucket;
import dev.dinauer.metrics.service.model.BucketUnit; import dev.dinauer.metrics.service.model.BucketUnit;
import dev.dinauer.metrics.service.model.Collection;
import dev.dinauer.metrics.service.utils.BucketConfigProvider; import dev.dinauer.metrics.service.utils.BucketConfigProvider;
import dev.dinauer.metrics.service.utils.TimestampGenerator; import dev.dinauer.metrics.service.utils.TimestampGenerator;
@ -27,43 +23,31 @@ public class Service
@Inject @Inject
BucketConfigProvider bucketConfigProvider; BucketConfigProvider bucketConfigProvider;
@Inject public void index(String resource, String metric, Map<String, Double> values)
Logger LOG;
public void index(String resource, String metric, String owner, Map<String, Double> values)
{ {
index(resource, metric, owner, values, ZonedDateTime.now(Clock.systemUTC())); index(resource, metric, values, ZonedDateTime.now(Clock.systemUTC()));
} }
@Transactional @Transactional
public void index(String resource, String name, String owner, Map<String, Double> values, ZonedDateTime now) public void index(String resource, String metric, Map<String, Double> values, ZonedDateTime now)
{ {
for (BucketUnit unit : bucketConfigProvider.get()) for (BucketUnit unit : bucketConfigProvider.get())
{ {
String timestamp = TimestampGenerator.generateTimestamp(now, unit); String timestamp = TimestampGenerator.generateTimestamp(now, unit);
Bucket bucket = repo.findByProperties(resource, name, timestamp, unit).orElse(new Bucket(resource, name, timestamp, now.toEpochSecond(), owner, unit)); Collection metrics = repo.findByProperties(resource, metric, timestamp, unit).orElse(new Collection(resource, metric, timestamp, now.toEpochSecond(), unit));
String bucketOwner = bucket.getOwner(); for (Map.Entry<String, Double> entry : values.entrySet())
if (Objects.isNull(bucketOwner) || Objects.equals(bucketOwner, owner))
{ {
for (Map.Entry<String, Double> entry : values.entrySet()) Double value = entry.getValue();
if (value != null)
{ {
Double value = entry.getValue(); metrics.add(entry.getKey().toUpperCase(), entry.getValue());
if (value != null)
{
bucket.add(entry.getKey().toUpperCase(), entry.getValue());
}
} }
} }
else repo.persist(metrics);
{
LOG.info(String.format("Forbidden. Cannot add metrics to bucket %s/%s owned by %s in behalf of %s.", bucket.getResource(), bucket.getName(), bucketOwner, owner));
throw new ForbiddenException();
}
repo.persist(bucket);
} }
} }
public List<Bucket> get(String resource, String metric, BucketUnit unit) public List<Collection> get(String resource, String metric, BucketUnit unit)
{ {
return repo.findByResourceAndMetricAndTimeUnit(resource, metric, unit); return repo.findByResourceAndMetricAndTimeUnit(resource, metric, unit);
} }

View File

@ -2,8 +2,7 @@ package dev.dinauer.metrics.service.client;
import java.util.Objects; import java.util.Objects;
public record Client(String id, String password, Permission permission) public record Client(String id, String password, Permission permission) {
{
@Override @Override
public boolean equals(Object object) public boolean equals(Object object)
{ {

View File

@ -2,14 +2,11 @@ package dev.dinauer.metrics.service.client;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.ConfigProvider; import org.eclipse.microprofile.config.ConfigProvider;
import org.jboss.logging.Logger;
import io.quarkus.elytron.security.common.BcryptUtil; import io.quarkus.elytron.security.common.BcryptUtil;
import io.quarkus.runtime.Startup; import io.quarkus.runtime.Startup;
@ -18,12 +15,11 @@ import io.quarkus.runtime.Startup;
@ApplicationScoped @ApplicationScoped
public class ClientRepo public class ClientRepo
{ {
private final static String CLIENT_PROPERTY_PREFIX = "big.bucket.client"; private final static String CLIENT_PROPERTY_PREFIX = "dev.dinauer.metrics-service.client";
private final List<Client> clients; List<Client> clients;
@Inject public ClientRepo()
public ClientRepo(Logger LOG)
{ {
List<Client> result = new ArrayList<>(); List<Client> result = new ArrayList<>();
Config config = ConfigProvider.getConfig(); Config config = ConfigProvider.getConfig();
@ -32,16 +28,16 @@ public class ClientRepo
if (key.startsWith(CLIENT_PROPERTY_PREFIX)) if (key.startsWith(CLIENT_PROPERTY_PREFIX))
{ {
List<String> sections = List.of(key.split("\\.")); List<String> sections = List.of(key.split("\\."));
if (sections.size() == 5) if (sections.size() == 6)
{ {
String clientId = sections.get(3); String clientId = sections.get(4);
String permission = sections.get(4).toUpperCase(); String permission = sections.get(5).toUpperCase();
if (!clientId.isBlank() && List.of("RO", "RW", "WO").contains(permission)) if (!clientId.isBlank() && List.of("RO", "RW").contains(permission))
{ {
String password = config.getValue(key, String.class); String password = config.getValue(key, String.class);
if (password != null && !password.isBlank()) if (password != null && !password.isBlank())
{ {
Client client = new Client(clientId.toLowerCase(), BcryptUtil.bcryptHash(password), Permission.valueOf(permission)); Client client = new Client(clientId, BcryptUtil.bcryptHash(password), Permission.valueOf(permission));
if (!result.contains(client)) if (!result.contains(client))
{ {
result.add(client); result.add(client);
@ -52,15 +48,10 @@ public class ClientRepo
} }
} }
} }
else
{
throw new IllegalArgumentException(String.format("Invalid permission %s for user %s", permission, clientId));
}
} }
} }
} }
this.clients = result; this.clients = result;
LOG.infof("Running with clients: %s", clients.stream().map(client -> String.format("%s[%s]", client.id(), client.permission())).collect(Collectors.joining(",")));
} }
public Client findById(String id) public Client findById(String id)

View File

@ -3,4 +3,4 @@ package dev.dinauer.metrics.service.client;
public enum Permission public enum Permission
{ {
RW, RO, WO RW, RO, WO
} }

View File

@ -7,8 +7,6 @@ import jakarta.inject.Inject;
import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.HttpHeaders;
import org.jboss.resteasy.reactive.common.NotImplementedYet;
import io.quarkus.security.UnauthorizedException; import io.quarkus.security.UnauthorizedException;
import dev.dinauer.metrics.service.client.Client; import dev.dinauer.metrics.service.client.Client;
@ -46,17 +44,11 @@ public class AuthenticationService
AuthHeader header = getAuthHeader(); AuthHeader header = getAuthHeader();
switch (header.type()) switch (header.type())
{ {
case BASIC: case BASIC -> {
{
return basicAuthClientProvider.get(header.credentials()); return basicAuthClientProvider.get(header.credentials());
} }
case BEARER: case BEARER -> {
{ return bearerAuthClientProvider.get(header.credentials());
if (false)
{
return bearerAuthClientProvider.get(header.credentials());
}
throw new NotImplementedYet();
} }
} }
throw new UnauthorizedException(); throw new UnauthorizedException();
@ -73,8 +65,7 @@ public class AuthenticationService
try try
{ {
return new AuthHeader(AuthType.valueOf(sections[0].toUpperCase()), sections[1]); return new AuthHeader(AuthType.valueOf(sections[0].toUpperCase()), sections[1]);
} } catch (IllegalArgumentException e)
catch (IllegalArgumentException e)
{ {
throw new UnauthorizedException(); throw new UnauthorizedException();
} }

View File

@ -4,10 +4,6 @@ import java.util.Optional;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.jwt.JsonWebToken; import org.eclipse.microprofile.jwt.JsonWebToken;
@ -25,18 +21,11 @@ public class BearerAuthClientProvider
@Inject @Inject
JWTParser parser; JWTParser parser;
@ConfigProperty(name = "big.bucket.jwt.client-id.field") @ConfigProperty(name = "dev.dinauer.metrics-service.jwt.client.field")
String clientIdField; String clientIdField;
@ConfigProperty(name = "big.bucket.auth.client-only")
Boolean clientOnly;
public Client get(String credentials) public Client get(String credentials)
{ {
if (clientOnly)
{
throw new WebApplicationException(Response.status(403).type(MediaType.TEXT_PLAIN).entity("endusers_disabled").build());
}
try try
{ {
JsonWebToken token = parser.parse(credentials); JsonWebToken token = parser.parse(credentials);
@ -47,11 +36,9 @@ public class BearerAuthClientProvider
{ {
return new Client(user.get(), null, Permission.RO); return new Client(user.get(), null, Permission.RO);
} }
throw new NotFoundException();
} }
throw new UnauthorizedException(); throw new UnauthorizedException();
} } catch (ParseException e)
catch (ParseException e)
{ {
throw new UnauthorizedException(); throw new UnauthorizedException();
} }

View File

@ -1,5 +1,4 @@
package dev.dinauer.metrics.service.client.auth.utils; package dev.dinauer.metrics.service.client.auth.utils;
public record AuthHeader(AuthType type, String credentials) public record AuthHeader(AuthType type, String credentials) {
{
} }

View File

@ -1,5 +1,4 @@
package dev.dinauer.metrics.service.client.auth.utils; package dev.dinauer.metrics.service.client.auth.utils;
public record BasicAuthCredentials(String clientId, String password) public record BasicAuthCredentials(String clientId, String password) {
{
} }

View File

@ -14,8 +14,8 @@ import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@Entity @Entity
@Table(name = "bucket") @Table(name = "collection")
public class Bucket public class Collection
{ {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@ -25,7 +25,7 @@ public class Bucket
@Column(nullable = false) @Column(nullable = false)
private String resource; private String resource;
@Column(name = "bucket_name", nullable = false) @Column(name = "collection_name", nullable = false)
private String name; private String name;
@Column(nullable = false) @Column(nullable = false)
@ -41,8 +41,6 @@ public class Bucket
@Column(columnDefinition = "text", nullable = false) @Column(columnDefinition = "text", nullable = false)
private String metrics; private String metrics;
private String owner;
@CreationTimestamp @CreationTimestamp
@Column(name = "created_at", updatable = false) @Column(name = "created_at", updatable = false)
private ZonedDateTime createdAt; private ZonedDateTime createdAt;
@ -51,19 +49,18 @@ public class Bucket
@Column(name = "updated_at") @Column(name = "updated_at")
private ZonedDateTime updatedAt; private ZonedDateTime updatedAt;
public Bucket() public Collection()
{ {
} }
public Bucket(String resource, String name, String timestamp, long unixTimestamp, String owner, BucketUnit bucketUnit) public Collection(String resource, String name, String timestamp, long unixTimestamp, BucketUnit bucketUnit)
{ {
this.id = UUID.randomUUID().toString(); this.id = UUID.randomUUID().toString();
this.resource = resource; this.resource = resource;
this.name = name;
this.timestamp = timestamp; this.timestamp = timestamp;
this.unixTimestamp = unixTimestamp; this.unixTimestamp = unixTimestamp;
this.owner = owner;
this.bucketUnit = bucketUnit; this.bucketUnit = bucketUnit;
this.name = name;
this.metrics = "{}"; this.metrics = "{}";
} }
@ -89,8 +86,7 @@ public class Bucket
try try
{ {
this.metrics = OBJECT_MAPPER.writeValueAsString(metrics); this.metrics = OBJECT_MAPPER.writeValueAsString(metrics);
} } catch (JsonProcessingException e)
catch (JsonProcessingException e)
{ {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -132,8 +128,7 @@ public class Bucket
return OBJECT_MAPPER.readValue(metrics, new TypeReference<Map<String, Metric>>() return OBJECT_MAPPER.readValue(metrics, new TypeReference<Map<String, Metric>>()
{ {
}); });
} } catch (JsonProcessingException e)
catch (JsonProcessingException e)
{ {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -149,7 +144,7 @@ public class Bucket
return createdAt; return createdAt;
} }
public Bucket setCreatedAt(ZonedDateTime createdAt) public Collection setCreatedAt(ZonedDateTime createdAt)
{ {
this.createdAt = createdAt; this.createdAt = createdAt;
return this; return this;
@ -160,14 +155,9 @@ public class Bucket
return updatedAt; return updatedAt;
} }
public Bucket setUpdatedAt(ZonedDateTime updatedAt) public Collection setUpdatedAt(ZonedDateTime updatedAt)
{ {
this.updatedAt = updatedAt; this.updatedAt = updatedAt;
return this; return this;
} }
public String getOwner()
{
return owner;
}
} }

View File

@ -18,7 +18,7 @@ import dev.dinauer.metrics.service.model.BucketUnit;
@ApplicationScoped @ApplicationScoped
public class BucketConfigProvider public class BucketConfigProvider
{ {
private final Set<BucketUnit> units; private Set<BucketUnit> units;
@Inject @Inject
public BucketConfigProvider(Logger LOG, @ConfigProperty(name = "dev.dinauer.metrics-service.buckets") String config) public BucketConfigProvider(Logger LOG, @ConfigProperty(name = "dev.dinauer.metrics-service.buckets") String config)

View File

@ -9,9 +9,6 @@ dev.dinauer.metrics-service.jwt.client.field=upn
# JWT # JWT
mp.jwt.verify.publickey.location=dev/publicKey.pem mp.jwt.verify.publickey.location=dev/publicKey.pem
%dev.big.bucket.jwt.client-id.field=upn
%dev.big.bucket.auth.client-only=false
# Postgres # Postgres
quarkus.datasource.db-kind = postgresql quarkus.datasource.db-kind = postgresql
%dev.quarkus.datasource.username = postgres %dev.quarkus.datasource.username = postgres

View File

@ -1,6 +0,0 @@
________ _ ____ __ __
___/ __ )(_)___ _/ __ )__ _______/ /_____ / /_
__/ __ / / __ `/ __ / / / / ___/ //_/ _ \/ __/
_/ /_/ / / /_/ / /_/ / /_/ / /__/ ,< / __/ /_
/_____/_/\__, /_____/\__,_/\___/_/|_|\___/\__/
/____/