🧑‍💻 Cleanup

This commit is contained in:
andreas.dinauer 2025-11-16 13:26:33 +01:00
parent 3799cf822f
commit 9414d5f07f
15 changed files with 108 additions and 42 deletions

4
Jenkinsfile vendored
View File

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

View File

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

View File

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

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">
<modelVersion>4.0.0</modelVersion>
<groupId>dev.dinauer</groupId>
<artifactId>metrics-service</artifactId>
<artifactId>big-bucket</artifactId>
<version>1.0.0-SNAPSHOT</version>
<properties>

View File

@ -0,0 +1,9 @@
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

@ -1,7 +1,6 @@
package dev.dinauer.metrics.service;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import jakarta.inject.Inject;
@ -21,11 +20,11 @@ public class Resource
Service service;
@POST
public void insert(@PathParam("resource") String resource, @PathParam("metric") String metric, Map<String, Double> values)
public void insert(@PathParam("resource") String resource, @PathParam("metric") String metric, Insert insert)
{
if (authenticationService.canWrite())
{
service.index(resource, metric, values);
service.index(resource, metric, insert.owner(), insert.values());
}
else
{

View File

@ -4,10 +4,14 @@ import java.time.Clock;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
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;
@ -23,27 +27,39 @@ public class Service
@Inject
BucketConfigProvider bucketConfigProvider;
public void index(String resource, String metric, Map<String, Double> values)
@Inject
Logger LOG;
public void index(String resource, String metric, String owner, Map<String, Double> values)
{
index(resource, metric, values, ZonedDateTime.now(Clock.systemUTC()));
index(resource, metric, owner, values, ZonedDateTime.now(Clock.systemUTC()));
}
@Transactional
public void index(String resource, String metric, Map<String, Double> values, ZonedDateTime now)
public void index(String resource, String name, String owner, Map<String, Double> values, ZonedDateTime now)
{
for (BucketUnit unit : bucketConfigProvider.get())
{
String timestamp = TimestampGenerator.generateTimestamp(now, unit);
Bucket metrics = repo.findByProperties(resource, metric, timestamp, unit).orElse(new Bucket(resource, metric, timestamp, now.toEpochSecond(), unit));
Bucket bucket = repo.findByProperties(resource, name, timestamp, unit).orElse(new Bucket(resource, name, timestamp, now.toEpochSecond(), owner, unit));
String bucketOwner = bucket.getOwner();
if (Objects.isNull(bucketOwner) || Objects.equals(bucketOwner, owner))
{
for (Map.Entry<String, Double> entry : values.entrySet())
{
Double value = entry.getValue();
if (value != null)
{
metrics.add(entry.getKey().toUpperCase(), entry.getValue());
bucket.add(entry.getKey().toUpperCase(), entry.getValue());
}
}
repo.persist(metrics);
}
else
{
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);
}
}

View File

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

View File

@ -7,6 +7,8 @@ import jakarta.inject.Inject;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.HttpHeaders;
import org.jboss.resteasy.reactive.common.NotImplementedYet;
import io.quarkus.security.UnauthorizedException;
import dev.dinauer.metrics.service.client.Client;
@ -49,9 +51,13 @@ public class AuthenticationService
return basicAuthClientProvider.get(header.credentials());
}
case BEARER:
{
if (false)
{
return bearerAuthClientProvider.get(header.credentials());
}
throw new NotImplementedYet();
}
}
throw new UnauthorizedException();
}

View File

@ -4,8 +4,11 @@ import java.util.Optional;
import jakarta.enterprise.context.ApplicationScoped;
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.jwt.JsonWebToken;
@ -22,11 +25,18 @@ public class BearerAuthClientProvider
@Inject
JWTParser parser;
@ConfigProperty(name = "dev.dinauer.metrics-service.jwt.client.field")
@ConfigProperty(name = "big.bucket.jwt.client-id.field")
String clientIdField;
@ConfigProperty(name = "big.bucket.auth.client-only")
Boolean clientOnly;
public Client get(String credentials)
{
if (clientOnly)
{
throw new WebApplicationException(Response.status(403).type(MediaType.TEXT_PLAIN).entity("endusers_disabled").build());
}
try
{
JsonWebToken token = parser.parse(credentials);

View File

@ -25,7 +25,7 @@ public class Bucket
@Column(nullable = false)
private String resource;
@Column(name = "collection_name", nullable = false)
@Column(name = "bucket_name", nullable = false)
private String name;
@Column(nullable = false)
@ -55,14 +55,15 @@ public class Bucket
{
}
public Bucket(String resource, String name, String timestamp, long unixTimestamp, BucketUnit bucketUnit)
public Bucket(String resource, String name, String timestamp, long unixTimestamp, String owner, BucketUnit bucketUnit)
{
this.id = UUID.randomUUID().toString();
this.resource = resource;
this.name = name;
this.timestamp = timestamp;
this.unixTimestamp = unixTimestamp;
this.owner = owner;
this.bucketUnit = bucketUnit;
this.name = name;
this.metrics = "{}";
}
@ -164,4 +165,9 @@ public class Bucket
this.updatedAt = updatedAt;
return this;
}
public String getOwner()
{
return owner;
}
}

View File

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

View File

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

View File

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