Reorganize imports.

This commit is contained in:
Michael Lipp 2025-03-01 21:51:33 +01:00
parent e822d472f9
commit 41ae658e0c
16 changed files with 139 additions and 100 deletions

View file

@ -18,6 +18,7 @@
package org.jdrupes.vmoperator.common; package org.jdrupes.vmoperator.common;
// TODO: Auto-generated Javadoc
/** /**
* Some constants. * Some constants.
*/ */
@ -30,21 +31,48 @@ public class Constants {
/** The Constant VM_OP_NAME. */ /** The Constant VM_OP_NAME. */
public static final String VM_OP_NAME = "vm-operator"; public static final String VM_OP_NAME = "vm-operator";
/** The Constant VM_OP_GROUP. */ /**
public static final String VM_OP_GROUP = "vmoperator.jdrupes.org"; * Constants related to the CRD.
*/
@SuppressWarnings("PMD.ShortClassName")
public static class Crd {
/** The Constant GROUP. */
public static final String GROUP = "vmoperator.jdrupes.org";
/** The Constant VM_OP_KIND_VM. */ /** The Constant KIND_VM. */
public static final String VM_OP_KIND_VM = "VirtualMachine"; public static final String KIND_VM = "VirtualMachine";
/** The Constant VM_OP_KIND_VM_POOL. */ /** The Constant KIND_VM_POOL. */
public static final String VM_OP_KIND_VM_POOL = "VmPool"; public static final String KIND_VM_POOL = "VmPool";
}
/** The Constant COMP_DISPLAY_SECRETS. */
public static final String COMP_DISPLAY_SECRET = "display-secret"; /**
* Status related constants.
/** The Constant DATA_DISPLAY_PASSWORD. */ */
public static final String DATA_DISPLAY_PASSWORD = "display-password"; public static class Status {
/** The Constant LOGGED_IN_USER. */
/** The Constant DATA_PASSWORD_EXPIRY. */ public static final String LOGGED_IN_USER = "loggedInUser";
public static final String DATA_PASSWORD_EXPIRY = "password-expiry";
/** The Constant CONSOLE_CLIENT. */
public static final String CONSOLE_CLIENT = "consoleClient";
/** The Constant CONSOLE_USER. */
public static final String CONSOLE_USER = "consoleUser";
}
/**
* DisplaySecret related constants.
*/
public static class DisplaySecret {
/** The Constant NAME. */
public static final String NAME = "display-secret";
/** The Constant PASSWORD. */
public static final String PASSWORD = "display-password";
/** The Constant EXPIRY. */
public static final String EXPIRY = "password-expiry";
}
} }

View file

@ -38,6 +38,7 @@ import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.jdrupes.vmoperator.common.Constants.Status;
import org.jdrupes.vmoperator.util.DataPath; import org.jdrupes.vmoperator.util.DataPath;
/** /**
@ -286,7 +287,7 @@ public class VmDefinition extends K8sDynamicModel {
* @return the optional * @return the optional
*/ */
public Optional<String> consoleUser() { public Optional<String> consoleUser() {
return this.<String> fromStatus("consoleUser"); return this.<String> fromStatus(Status.CONSOLE_USER);
} }
/** /**

View file

@ -11,7 +11,7 @@ metadata:
vmoperator.jdrupes.org/version: ${ managerVersion } vmoperator.jdrupes.org/version: ${ managerVersion }
ownerReferences: ownerReferences:
- apiVersion: ${ cr.apiVersion() } - apiVersion: ${ cr.apiVersion() }
kind: ${ constants.VM_OP_KIND_VM } kind: ${ constants.Crd.KIND_VM }
name: ${ cr.name() } name: ${ cr.name() }
uid: ${ cr.metadata().getUid() } uid: ${ cr.metadata().getUid() }
controller: false controller: false

View file

@ -11,7 +11,7 @@ metadata:
vmoperator.jdrupes.org/version: ${ managerVersion } vmoperator.jdrupes.org/version: ${ managerVersion }
ownerReferences: ownerReferences:
- apiVersion: ${ cr.apiVersion() } - apiVersion: ${ cr.apiVersion() }
kind: ${ constants.VM_OP_KIND_VM } kind: ${ constants.Crd.KIND_VM }
name: ${ cr.name() } name: ${ cr.name() }
uid: ${ cr.metadata().getUid() } uid: ${ cr.metadata().getUid() }
controller: false controller: false

View file

@ -15,7 +15,7 @@ metadata:
vmoperator.jdrupes.org/version: ${ managerVersion } vmoperator.jdrupes.org/version: ${ managerVersion }
ownerReferences: ownerReferences:
- apiVersion: ${ cr.apiVersion() } - apiVersion: ${ cr.apiVersion() }
kind: ${ constants.VM_OP_KIND_VM } kind: ${ constants.Crd.KIND_VM }
name: ${ cr.name() } name: ${ cr.name() }
uid: ${ cr.metadata().getUid() } uid: ${ cr.metadata().getUid() }
blockOwnerDeletion: true blockOwnerDeletion: true

View file

@ -29,8 +29,7 @@ import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.time.Instant; import java.time.Instant;
import java.util.logging.Level; import java.util.logging.Level;
import static org.jdrupes.vmoperator.common.Constants.VM_OP_GROUP; import org.jdrupes.vmoperator.common.Constants.Crd;
import static org.jdrupes.vmoperator.common.Constants.VM_OP_KIND_VM;
import org.jdrupes.vmoperator.common.K8sClient; import org.jdrupes.vmoperator.common.K8sClient;
import org.jdrupes.vmoperator.common.K8sDynamicStub; import org.jdrupes.vmoperator.common.K8sDynamicStub;
import org.jdrupes.vmoperator.common.VmDefinitionStub; import org.jdrupes.vmoperator.common.VmDefinitionStub;
@ -194,7 +193,7 @@ public class Controller extends Component {
private void patchVmDef(K8sClient client, String name, String path, private void patchVmDef(K8sClient client, String name, String path,
Object value) throws ApiException, IOException { Object value) throws ApiException, IOException {
var vmStub = K8sDynamicStub.get(client, var vmStub = K8sDynamicStub.get(client,
new GroupVersionKind(VM_OP_GROUP, "", VM_OP_KIND_VM), namespace, new GroupVersionKind(Crd.GROUP, "", Crd.KIND_VM), namespace,
name); name);
// Patch running // Patch running
@ -227,7 +226,7 @@ public class Controller extends Component {
try { try {
var vmDef = channel.vmDefinition(); var vmDef = channel.vmDefinition();
var vmStub = VmDefinitionStub.get(channel.client(), var vmStub = VmDefinitionStub.get(channel.client(),
new GroupVersionKind(VM_OP_GROUP, "", VM_OP_KIND_VM), new GroupVersionKind(Crd.GROUP, "", Crd.KIND_VM),
vmDef.namespace(), vmDef.name()); vmDef.namespace(), vmDef.name());
if (vmStub.updateStatus(vmDef, from -> { if (vmStub.updateStatus(vmDef, from -> {
JsonObject status = from.statusJson(); JsonObject status = from.statusJson();

View file

@ -28,11 +28,11 @@ import io.kubernetes.client.util.generic.options.PatchOptions;
import java.io.IOException; import java.io.IOException;
import java.util.logging.Level; import java.util.logging.Level;
import static org.jdrupes.vmoperator.common.Constants.APP_NAME; import static org.jdrupes.vmoperator.common.Constants.APP_NAME;
import org.jdrupes.vmoperator.common.Constants.DisplaySecret;
import static org.jdrupes.vmoperator.common.Constants.VM_OP_NAME; import static org.jdrupes.vmoperator.common.Constants.VM_OP_NAME;
import org.jdrupes.vmoperator.common.K8sClient; import org.jdrupes.vmoperator.common.K8sClient;
import org.jdrupes.vmoperator.common.K8sV1PodStub; import org.jdrupes.vmoperator.common.K8sV1PodStub;
import org.jdrupes.vmoperator.common.K8sV1SecretStub; import org.jdrupes.vmoperator.common.K8sV1SecretStub;
import static org.jdrupes.vmoperator.manager.Constants.COMP_DISPLAY_SECRET;
import org.jdrupes.vmoperator.manager.events.ChannelDictionary; import org.jdrupes.vmoperator.manager.events.ChannelDictionary;
import org.jdrupes.vmoperator.manager.events.VmChannel; import org.jdrupes.vmoperator.manager.events.VmChannel;
import org.jgrapes.core.Channel; import org.jgrapes.core.Channel;
@ -61,7 +61,7 @@ public class DisplaySecretMonitor
context(K8sV1SecretStub.CONTEXT); context(K8sV1SecretStub.CONTEXT);
ListOptions options = new ListOptions(); ListOptions options = new ListOptions();
options.setLabelSelector("app.kubernetes.io/name=" + APP_NAME + "," options.setLabelSelector("app.kubernetes.io/name=" + APP_NAME + ","
+ "app.kubernetes.io/component=" + COMP_DISPLAY_SECRET); + "app.kubernetes.io/component=" + DisplaySecret.NAME);
options(options); options(options);
} }

View file

@ -37,14 +37,12 @@ import java.util.Optional;
import java.util.Scanner; import java.util.Scanner;
import java.util.logging.Logger; import java.util.logging.Logger;
import static org.jdrupes.vmoperator.common.Constants.APP_NAME; import static org.jdrupes.vmoperator.common.Constants.APP_NAME;
import static org.jdrupes.vmoperator.common.Constants.COMP_DISPLAY_SECRET; import org.jdrupes.vmoperator.common.Constants.Crd;
import static org.jdrupes.vmoperator.common.Constants.VM_OP_GROUP; import org.jdrupes.vmoperator.common.Constants.DisplaySecret;
import static org.jdrupes.vmoperator.common.Constants.VM_OP_KIND_VM; import org.jdrupes.vmoperator.common.Constants.Status;
import org.jdrupes.vmoperator.common.K8sV1SecretStub; import org.jdrupes.vmoperator.common.K8sV1SecretStub;
import org.jdrupes.vmoperator.common.VmDefinition; import org.jdrupes.vmoperator.common.VmDefinition;
import org.jdrupes.vmoperator.common.VmDefinitionStub; import org.jdrupes.vmoperator.common.VmDefinitionStub;
import static org.jdrupes.vmoperator.manager.Constants.DATA_DISPLAY_PASSWORD;
import static org.jdrupes.vmoperator.manager.Constants.DATA_PASSWORD_EXPIRY;
import org.jdrupes.vmoperator.manager.events.PrepareConsole; import org.jdrupes.vmoperator.manager.events.PrepareConsole;
import org.jdrupes.vmoperator.manager.events.VmChannel; import org.jdrupes.vmoperator.manager.events.VmChannel;
import org.jdrupes.vmoperator.manager.events.VmDefChanged; import org.jdrupes.vmoperator.manager.events.VmDefChanged;
@ -143,7 +141,7 @@ public class DisplaySecretReconciler extends Component {
var vmDef = event.vmDefinition(); var vmDef = event.vmDefinition();
ListOptions options = new ListOptions(); ListOptions options = new ListOptions();
options.setLabelSelector("app.kubernetes.io/name=" + APP_NAME + "," options.setLabelSelector("app.kubernetes.io/name=" + APP_NAME + ","
+ "app.kubernetes.io/component=" + COMP_DISPLAY_SECRET + "," + "app.kubernetes.io/component=" + DisplaySecret.NAME + ","
+ "app.kubernetes.io/instance=" + vmDef.name()); + "app.kubernetes.io/instance=" + vmDef.name());
var stubs = K8sV1SecretStub.list(channel.client(), vmDef.namespace(), var stubs = K8sV1SecretStub.list(channel.client(), vmDef.namespace(),
options); options);
@ -154,9 +152,9 @@ public class DisplaySecretReconciler extends Component {
// Create secret // Create secret
var secret = new V1Secret(); var secret = new V1Secret();
secret.setMetadata(new V1ObjectMeta().namespace(vmDef.namespace()) secret.setMetadata(new V1ObjectMeta().namespace(vmDef.namespace())
.name(vmDef.name() + "-" + COMP_DISPLAY_SECRET) .name(vmDef.name() + "-" + DisplaySecret.NAME)
.putLabelsItem("app.kubernetes.io/name", APP_NAME) .putLabelsItem("app.kubernetes.io/name", APP_NAME)
.putLabelsItem("app.kubernetes.io/component", COMP_DISPLAY_SECRET) .putLabelsItem("app.kubernetes.io/component", DisplaySecret.NAME)
.putLabelsItem("app.kubernetes.io/instance", vmDef.name())); .putLabelsItem("app.kubernetes.io/instance", vmDef.name()));
secret.setType("Opaque"); secret.setType("Opaque");
SecureRandom random = null; SecureRandom random = null;
@ -169,8 +167,8 @@ public class DisplaySecretReconciler extends Component {
byte[] bytes = new byte[16]; byte[] bytes = new byte[16];
random.nextBytes(bytes); random.nextBytes(bytes);
var password = Base64.encode(bytes); var password = Base64.encode(bytes);
secret.setStringData(Map.of(DATA_DISPLAY_PASSWORD, password, secret.setStringData(Map.of(DisplaySecret.PASSWORD, password,
DATA_PASSWORD_EXPIRY, "now")); DisplaySecret.EXPIRY, "now"));
K8sV1SecretStub.create(channel.client(), secret); K8sV1SecretStub.create(channel.client(), secret);
} }
@ -196,7 +194,7 @@ public class DisplaySecretReconciler extends Component {
// Check if access is possible // Check if access is possible
if (event.loginUser() if (event.loginUser()
? !vmDef.<String> fromStatus("loggedInUser") ? !vmDef.<String> fromStatus(Status.LOGGED_IN_USER)
.map(u -> u.equals(event.user())).orElse(false) .map(u -> u.equals(event.user())).orElse(false)
: !vmDef.conditionStatus("Running").orElse(false)) { : !vmDef.conditionStatus("Running").orElse(false)) {
return; return;
@ -229,11 +227,11 @@ public class DisplaySecretReconciler extends Component {
private VmDefinition updateConsoleUser(PrepareConsole event, private VmDefinition updateConsoleUser(PrepareConsole event,
VmChannel channel) throws ApiException { VmChannel channel) throws ApiException {
var vmStub = VmDefinitionStub.get(channel.client(), var vmStub = VmDefinitionStub.get(channel.client(),
new GroupVersionKind(VM_OP_GROUP, "", VM_OP_KIND_VM), new GroupVersionKind(Crd.GROUP, "", Crd.KIND_VM),
event.vmDefinition().namespace(), event.vmDefinition().name()); event.vmDefinition().namespace(), event.vmDefinition().name());
return vmStub.updateStatus(from -> { return vmStub.updateStatus(from -> {
JsonObject status = from.statusJson(); JsonObject status = from.statusJson();
status.addProperty("consoleUser", event.user()); status.addProperty(Status.CONSOLE_USER, event.user());
return status; return status;
}).orElse(null); }).orElse(null);
} }
@ -243,7 +241,7 @@ public class DisplaySecretReconciler extends Component {
// Look for secret // Look for secret
ListOptions options = new ListOptions(); ListOptions options = new ListOptions();
options.setLabelSelector("app.kubernetes.io/name=" + APP_NAME + "," options.setLabelSelector("app.kubernetes.io/name=" + APP_NAME + ","
+ "app.kubernetes.io/component=" + COMP_DISPLAY_SECRET + "," + "app.kubernetes.io/component=" + DisplaySecret.NAME + ","
+ "app.kubernetes.io/instance=" + vmDef.name()); + "app.kubernetes.io/instance=" + vmDef.name());
var stubs = K8sV1SecretStub.list(channel.client(), vmDef.namespace(), var stubs = K8sV1SecretStub.list(channel.client(), vmDef.namespace(),
options); options);
@ -257,12 +255,12 @@ public class DisplaySecretReconciler extends Component {
private boolean updatePassword(V1Secret secret, PrepareConsole event) { private boolean updatePassword(V1Secret secret, PrepareConsole event) {
var expiry = Optional.ofNullable(secret.getData() var expiry = Optional.ofNullable(secret.getData()
.get(DATA_PASSWORD_EXPIRY)).map(b -> new String(b)).orElse(null); .get(DisplaySecret.EXPIRY)).map(b -> new String(b)).orElse(null);
if (secret.getData().get(DATA_DISPLAY_PASSWORD) != null if (secret.getData().get(DisplaySecret.PASSWORD) != null
&& stillValid(expiry)) { && stillValid(expiry)) {
// Fixed secret, don't touch // Fixed secret, don't touch
event.setResult( event.setResult(
new String(secret.getData().get(DATA_DISPLAY_PASSWORD))); new String(secret.getData().get(DisplaySecret.PASSWORD)));
return false; return false;
} }
@ -277,8 +275,8 @@ public class DisplaySecretReconciler extends Component {
byte[] bytes = new byte[16]; byte[] bytes = new byte[16];
random.nextBytes(bytes); random.nextBytes(bytes);
var password = Base64.encode(bytes); var password = Base64.encode(bytes);
secret.setStringData(Map.of(DATA_DISPLAY_PASSWORD, password, secret.setStringData(Map.of(DisplaySecret.PASSWORD, password,
DATA_PASSWORD_EXPIRY, DisplaySecret.EXPIRY,
Long.toString(Instant.now().getEpochSecond() + passwordValidity))); Long.toString(Instant.now().getEpochSecond() + passwordValidity)));
event.setResult(password); event.setResult(password);
return true; return true;

View file

@ -28,8 +28,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import static org.jdrupes.vmoperator.common.Constants.VM_OP_GROUP; import org.jdrupes.vmoperator.common.Constants.Crd;
import static org.jdrupes.vmoperator.common.Constants.VM_OP_KIND_VM;
import org.jdrupes.vmoperator.common.K8s; import org.jdrupes.vmoperator.common.K8s;
import org.jdrupes.vmoperator.common.K8sClient; import org.jdrupes.vmoperator.common.K8sClient;
import org.jdrupes.vmoperator.common.K8sDynamicModel; import org.jdrupes.vmoperator.common.K8sDynamicModel;
@ -38,7 +37,6 @@ import org.jdrupes.vmoperator.common.K8sDynamicStub;
import org.jdrupes.vmoperator.common.K8sObserver.ResponseType; import org.jdrupes.vmoperator.common.K8sObserver.ResponseType;
import org.jdrupes.vmoperator.common.VmDefinitionStub; import org.jdrupes.vmoperator.common.VmDefinitionStub;
import org.jdrupes.vmoperator.common.VmPool; import org.jdrupes.vmoperator.common.VmPool;
import static org.jdrupes.vmoperator.manager.Constants.VM_OP_KIND_VM_POOL;
import org.jdrupes.vmoperator.manager.events.GetPools; import org.jdrupes.vmoperator.manager.events.GetPools;
import org.jdrupes.vmoperator.manager.events.VmDefChanged; import org.jdrupes.vmoperator.manager.events.VmDefChanged;
import org.jdrupes.vmoperator.manager.events.VmPoolChanged; import org.jdrupes.vmoperator.manager.events.VmPoolChanged;
@ -88,7 +86,7 @@ public class PoolMonitor extends
client(new K8sClient()); client(new K8sClient());
// Get all our API versions // Get all our API versions
var ctx = K8s.context(client(), VM_OP_GROUP, "", VM_OP_KIND_VM_POOL); var ctx = K8s.context(client(), Crd.GROUP, "", Crd.KIND_VM_POOL);
if (ctx.isEmpty()) { if (ctx.isEmpty()) {
logger.severe(() -> "Cannot get CRD context."); logger.severe(() -> "Cannot get CRD context.");
return; return;
@ -184,7 +182,7 @@ public class PoolMonitor extends
return; return;
} }
var vmStub = VmDefinitionStub.get(client(), var vmStub = VmDefinitionStub.get(client(),
new GroupVersionKind(VM_OP_GROUP, "", VM_OP_KIND_VM), new GroupVersionKind(Crd.GROUP, "", Crd.KIND_VM),
vmDef.namespace(), vmDef.name()); vmDef.namespace(), vmDef.name());
vmStub.updateStatus(from -> { vmStub.updateStatus(from -> {
// TODO // TODO

View file

@ -22,12 +22,10 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import freemarker.template.AdapterTemplateModel; import freemarker.template.AdapterTemplateModel;
import freemarker.template.Configuration; import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapperBuilder;
import freemarker.template.SimpleNumber; import freemarker.template.SimpleNumber;
import freemarker.template.SimpleScalar; import freemarker.template.SimpleScalar;
import freemarker.template.TemplateException; import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler; import freemarker.template.TemplateExceptionHandler;
import freemarker.template.TemplateHashModel;
import freemarker.template.TemplateMethodModelEx; import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModel; import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException; import freemarker.template.TemplateModelException;
@ -37,21 +35,23 @@ import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.models.V1ObjectMeta; import io.kubernetes.client.openapi.models.V1ObjectMeta;
import io.kubernetes.client.util.generic.options.ListOptions; import io.kubernetes.client.util.generic.options.ListOptions;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Modifier;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import static org.jdrupes.vmoperator.common.Constants.APP_NAME; import static org.jdrupes.vmoperator.common.Constants.APP_NAME;
import org.jdrupes.vmoperator.common.Constants.DisplaySecret;
import org.jdrupes.vmoperator.common.Convertions; import org.jdrupes.vmoperator.common.Convertions;
import org.jdrupes.vmoperator.common.K8sClient; import org.jdrupes.vmoperator.common.K8sClient;
import org.jdrupes.vmoperator.common.K8sObserver; import org.jdrupes.vmoperator.common.K8sObserver;
import org.jdrupes.vmoperator.common.K8sV1SecretStub; import org.jdrupes.vmoperator.common.K8sV1SecretStub;
import org.jdrupes.vmoperator.common.VmDefinition; import org.jdrupes.vmoperator.common.VmDefinition;
import static org.jdrupes.vmoperator.manager.Constants.COMP_DISPLAY_SECRET;
import org.jdrupes.vmoperator.manager.events.ResetVm; import org.jdrupes.vmoperator.manager.events.ResetVm;
import org.jdrupes.vmoperator.manager.events.VmChannel; import org.jdrupes.vmoperator.manager.events.VmChannel;
import org.jdrupes.vmoperator.manager.events.VmDefChanged; import org.jdrupes.vmoperator.manager.events.VmDefChanged;
@ -266,17 +266,14 @@ public class Reconciler extends Component {
Optional.ofNullable(Reconciler.class.getPackage() Optional.ofNullable(Reconciler.class.getPackage()
.getImplementationVersion()).orElse("(Unknown)")); .getImplementationVersion()).orElse("(Unknown)"));
model.put("cr", vmDef); model.put("cr", vmDef);
model.put("constants", // Freemarker's static models don't handle nested classes.
(TemplateHashModel) new DefaultObjectWrapperBuilder( model.put("constants", constantsMap(Constants.class));
Configuration.VERSION_2_3_32)
.build().getStaticModels()
.get(Constants.class.getName()));
model.put("reconciler", config); model.put("reconciler", config);
// Check if we have a display secret // Check if we have a display secret
ListOptions options = new ListOptions(); ListOptions options = new ListOptions();
options.setLabelSelector("app.kubernetes.io/name=" + APP_NAME + "," options.setLabelSelector("app.kubernetes.io/name=" + APP_NAME + ","
+ "app.kubernetes.io/component=" + COMP_DISPLAY_SECRET + "," + "app.kubernetes.io/component=" + DisplaySecret.NAME + ","
+ "app.kubernetes.io/instance=" + vmDef.name()); + "app.kubernetes.io/instance=" + vmDef.name());
var dsStub = K8sV1SecretStub var dsStub = K8sV1SecretStub
.list(client, vmDef.namespace(), options) .list(client, vmDef.namespace(), options)
@ -297,6 +294,30 @@ public class Reconciler extends Component {
return model; return model;
} }
@SuppressWarnings("PMD.EmptyCatchBlock")
private Map<String, Object> constantsMap(Class<?> clazz) {
@SuppressWarnings("PMD.UseConcurrentHashMap")
Map<String, Object> result = new HashMap<>();
Arrays.stream(clazz.getFields()).filter(f -> {
var modifiers = f.getModifiers();
return Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers)
&& f.getType() == String.class;
}).forEach(f -> {
try {
result.put(f.getName(), f.get(null));
} catch (IllegalArgumentException | IllegalAccessException e) {
// Should not happen, ignore
}
});
Arrays.stream(clazz.getClasses()).filter(c -> {
var modifiers = c.getModifiers();
return Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers);
}).forEach(c -> {
result.put(c.getSimpleName(), constantsMap(c));
});
return result;
}
private final TemplateMethodModelEx parseQuantityModel private final TemplateMethodModelEx parseQuantityModel
= new TemplateMethodModelEx() { = new TemplateMethodModelEx() {
@Override @Override

View file

@ -31,8 +31,7 @@ import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.jdrupes.vmoperator.common.Constants.VM_OP_GROUP; import org.jdrupes.vmoperator.common.Constants.Crd;
import static org.jdrupes.vmoperator.common.Constants.VM_OP_KIND_VM;
import org.jdrupes.vmoperator.common.K8s; import org.jdrupes.vmoperator.common.K8s;
import org.jdrupes.vmoperator.common.K8sClient; import org.jdrupes.vmoperator.common.K8sClient;
import org.jdrupes.vmoperator.common.K8sDynamicStub; import org.jdrupes.vmoperator.common.K8sDynamicStub;
@ -87,7 +86,7 @@ public class VmMonitor extends
client(new K8sClient()); client(new K8sClient());
// Get all our API versions // Get all our API versions
var ctx = K8s.context(client(), VM_OP_GROUP, "", VM_OP_KIND_VM); var ctx = K8s.context(client(), Crd.GROUP, "", Crd.KIND_VM);
if (ctx.isEmpty()) { if (ctx.isEmpty()) {
logger.severe(() -> "Cannot get CRD context."); logger.severe(() -> "Cannot get CRD context.");
return; return;

View file

@ -12,10 +12,10 @@ import java.util.Collection;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.jdrupes.vmoperator.common.Constants;
import static org.jdrupes.vmoperator.common.Constants.APP_NAME; import static org.jdrupes.vmoperator.common.Constants.APP_NAME;
import static org.jdrupes.vmoperator.common.Constants.COMP_DISPLAY_SECRET; import org.jdrupes.vmoperator.common.Constants.Crd;
import static org.jdrupes.vmoperator.common.Constants.VM_OP_GROUP; import org.jdrupes.vmoperator.common.Constants.DisplaySecret;
import static org.jdrupes.vmoperator.common.Constants.VM_OP_KIND_VM;
import static org.jdrupes.vmoperator.common.Constants.VM_OP_NAME; import static org.jdrupes.vmoperator.common.Constants.VM_OP_NAME;
import org.jdrupes.vmoperator.common.K8s; import org.jdrupes.vmoperator.common.K8s;
import org.jdrupes.vmoperator.common.K8sClient; import org.jdrupes.vmoperator.common.K8sClient;
@ -60,7 +60,7 @@ class BasicTests {
waitForManager(); waitForManager();
// Context for working with our CR // Context for working with our CR
var apiRes = K8s.context(client, VM_OP_GROUP, null, VM_OP_KIND_VM); var apiRes = K8s.context(client, Crd.GROUP, null, Crd.KIND_VM);
assertTrue(apiRes.isPresent()); assertTrue(apiRes.isPresent());
vmsContext = apiRes.get(); vmsContext = apiRes.get();
@ -70,7 +70,7 @@ class BasicTests {
ListOptions listOpts = new ListOptions(); ListOptions listOpts = new ListOptions();
listOpts.setLabelSelector("app.kubernetes.io/name=" + APP_NAME + "," listOpts.setLabelSelector("app.kubernetes.io/name=" + APP_NAME + ","
+ "app.kubernetes.io/instance=" + VM_NAME + "," + "app.kubernetes.io/instance=" + VM_NAME + ","
+ "app.kubernetes.io/component=" + COMP_DISPLAY_SECRET); + "app.kubernetes.io/component=" + DisplaySecret.NAME);
var secrets = K8sV1SecretStub.list(client, "vmop-dev", listOpts); var secrets = K8sV1SecretStub.list(client, "vmop-dev", listOpts);
for (var secret : secrets) { for (var secret : secrets) {
secret.delete(); secret.delete();
@ -138,12 +138,11 @@ class BasicTests {
List.of("name"), VM_NAME, List.of("name"), VM_NAME,
List.of("labels", "app.kubernetes.io/name"), Constants.APP_NAME, List.of("labels", "app.kubernetes.io/name"), Constants.APP_NAME,
List.of("labels", "app.kubernetes.io/instance"), VM_NAME, List.of("labels", "app.kubernetes.io/instance"), VM_NAME,
List.of("labels", "app.kubernetes.io/managed-by"), List.of("labels", "app.kubernetes.io/managed-by"), VM_OP_NAME,
Constants.VM_OP_NAME,
List.of("annotations", "vmoperator.jdrupes.org/version"), EXISTS, List.of("annotations", "vmoperator.jdrupes.org/version"), EXISTS,
List.of("ownerReferences", 0, "apiVersion"), List.of("ownerReferences", 0, "apiVersion"),
vmsContext.getGroup() + "/" + vmsContext.getVersions().get(0), vmsContext.getGroup() + "/" + vmsContext.getVersions().get(0),
List.of("ownerReferences", 0, "kind"), Constants.VM_OP_KIND_VM, List.of("ownerReferences", 0, "kind"), Crd.KIND_VM,
List.of("ownerReferences", 0, "name"), VM_NAME, List.of("ownerReferences", 0, "name"), VM_NAME,
List.of("ownerReferences", 0, "uid"), EXISTS); List.of("ownerReferences", 0, "uid"), EXISTS);
checkProps(config.getMetadata(), toCheck); checkProps(config.getMetadata(), toCheck);
@ -189,7 +188,7 @@ class BasicTests {
ListOptions listOpts = new ListOptions(); ListOptions listOpts = new ListOptions();
listOpts.setLabelSelector("app.kubernetes.io/name=" + APP_NAME + "," listOpts.setLabelSelector("app.kubernetes.io/name=" + APP_NAME + ","
+ "app.kubernetes.io/instance=" + VM_NAME + "," + "app.kubernetes.io/instance=" + VM_NAME + ","
+ "app.kubernetes.io/component=" + COMP_DISPLAY_SECRET); + "app.kubernetes.io/component=" + DisplaySecret.NAME);
Collection<K8sV1SecretStub> secrets = null; Collection<K8sV1SecretStub> secrets = null;
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
secrets = K8sV1SecretStub.list(client, "vmop-dev", listOpts); secrets = K8sV1SecretStub.list(client, "vmop-dev", listOpts);
@ -219,8 +218,7 @@ class BasicTests {
checkProps(pvc.getMetadata(), Map.of( checkProps(pvc.getMetadata(), Map.of(
List.of("labels", "app.kubernetes.io/name"), Constants.APP_NAME, List.of("labels", "app.kubernetes.io/name"), Constants.APP_NAME,
List.of("labels", "app.kubernetes.io/instance"), VM_NAME, List.of("labels", "app.kubernetes.io/instance"), VM_NAME,
List.of("labels", "app.kubernetes.io/managed-by"), List.of("labels", "app.kubernetes.io/managed-by"), VM_OP_NAME));
Constants.VM_OP_NAME));
checkProps(pvc.getSpec(), Map.of( checkProps(pvc.getSpec(), Map.of(
List.of("resources", "requests", "storage"), List.of("resources", "requests", "storage"),
Quantity.fromString("1Mi"))); Quantity.fromString("1Mi")));
@ -240,8 +238,7 @@ class BasicTests {
checkProps(pvc.getMetadata(), Map.of( checkProps(pvc.getMetadata(), Map.of(
List.of("labels", "app.kubernetes.io/name"), Constants.APP_NAME, List.of("labels", "app.kubernetes.io/name"), Constants.APP_NAME,
List.of("labels", "app.kubernetes.io/instance"), VM_NAME, List.of("labels", "app.kubernetes.io/instance"), VM_NAME,
List.of("labels", "app.kubernetes.io/managed-by"), List.of("labels", "app.kubernetes.io/managed-by"), VM_OP_NAME,
Constants.VM_OP_NAME,
List.of("annotations", "use_as"), "system-disk")); List.of("annotations", "use_as"), "system-disk"));
checkProps(pvc.getSpec(), Map.of( checkProps(pvc.getSpec(), Map.of(
List.of("resources", "requests", "storage"), List.of("resources", "requests", "storage"),
@ -262,8 +259,7 @@ class BasicTests {
checkProps(pvc.getMetadata(), Map.of( checkProps(pvc.getMetadata(), Map.of(
List.of("labels", "app.kubernetes.io/name"), Constants.APP_NAME, List.of("labels", "app.kubernetes.io/name"), Constants.APP_NAME,
List.of("labels", "app.kubernetes.io/instance"), VM_NAME, List.of("labels", "app.kubernetes.io/instance"), VM_NAME,
List.of("labels", "app.kubernetes.io/managed-by"), List.of("labels", "app.kubernetes.io/managed-by"), VM_OP_NAME));
Constants.VM_OP_NAME));
checkProps(pvc.getSpec(), Map.of( checkProps(pvc.getSpec(), Map.of(
List.of("resources", "requests", "storage"), List.of("resources", "requests", "storage"),
Quantity.fromString("1Gi"))); Quantity.fromString("1Gi")));
@ -290,13 +286,12 @@ class BasicTests {
List.of("labels", "app.kubernetes.io/name"), APP_NAME, List.of("labels", "app.kubernetes.io/name"), APP_NAME,
List.of("labels", "app.kubernetes.io/instance"), VM_NAME, List.of("labels", "app.kubernetes.io/instance"), VM_NAME,
List.of("labels", "app.kubernetes.io/component"), APP_NAME, List.of("labels", "app.kubernetes.io/component"), APP_NAME,
List.of("labels", "app.kubernetes.io/managed-by"), List.of("labels", "app.kubernetes.io/managed-by"), VM_OP_NAME,
Constants.VM_OP_NAME,
List.of("annotations", "vmrunner.jdrupes.org/cmVersion"), EXISTS, List.of("annotations", "vmrunner.jdrupes.org/cmVersion"), EXISTS,
List.of("annotations", "vmoperator.jdrupes.org/version"), EXISTS, List.of("annotations", "vmoperator.jdrupes.org/version"), EXISTS,
List.of("ownerReferences", 0, "apiVersion"), List.of("ownerReferences", 0, "apiVersion"),
vmsContext.getGroup() + "/" + vmsContext.getVersions().get(0), vmsContext.getGroup() + "/" + vmsContext.getVersions().get(0),
List.of("ownerReferences", 0, "kind"), Constants.VM_OP_KIND_VM, List.of("ownerReferences", 0, "kind"), Crd.KIND_VM,
List.of("ownerReferences", 0, "name"), VM_NAME, List.of("ownerReferences", 0, "name"), VM_NAME,
List.of("ownerReferences", 0, "uid"), EXISTS)); List.of("ownerReferences", 0, "uid"), EXISTS));
checkProps(pod.getSpec(), Map.of( checkProps(pod.getSpec(), Map.of(

View file

@ -25,8 +25,8 @@ import io.kubernetes.client.openapi.models.EventsV1Event;
import java.io.IOException; import java.io.IOException;
import java.util.logging.Level; import java.util.logging.Level;
import static org.jdrupes.vmoperator.common.Constants.APP_NAME; import static org.jdrupes.vmoperator.common.Constants.APP_NAME;
import static org.jdrupes.vmoperator.common.Constants.VM_OP_GROUP; import org.jdrupes.vmoperator.common.Constants.Crd;
import static org.jdrupes.vmoperator.common.Constants.VM_OP_KIND_VM; import org.jdrupes.vmoperator.common.Constants.Status;
import org.jdrupes.vmoperator.common.K8s; import org.jdrupes.vmoperator.common.K8s;
import org.jdrupes.vmoperator.common.K8sClient; import org.jdrupes.vmoperator.common.K8sClient;
import org.jdrupes.vmoperator.common.VmDefinitionStub; import org.jdrupes.vmoperator.common.VmDefinitionStub;
@ -74,7 +74,7 @@ public class ConsoleTracker extends VmDefUpdater {
} }
try { try {
vmStub = VmDefinitionStub.get(apiClient, vmStub = VmDefinitionStub.get(apiClient,
new GroupVersionKind(VM_OP_GROUP, "", VM_OP_KIND_VM), new GroupVersionKind(Crd.GROUP, "", Crd.KIND_VM),
namespace, vmName); namespace, vmName);
} catch (ApiException e) { } catch (ApiException e) {
logger.log(Level.SEVERE, e, logger.log(Level.SEVERE, e,
@ -108,13 +108,13 @@ public class ConsoleTracker extends VmDefUpdater {
vmStub.updateStatus(from -> { vmStub.updateStatus(from -> {
JsonObject status = updateCondition(from, "ConsoleConnected", true, JsonObject status = updateCondition(from, "ConsoleConnected", true,
"Connected", "Connection from " + event.clientHost()); "Connected", "Connection from " + event.clientHost());
status.addProperty("consoleClient", event.clientHost()); status.addProperty(Status.CONSOLE_CLIENT, event.clientHost());
return status; return status;
}); });
// Log event // Log event
var evt = new EventsV1Event() var evt = new EventsV1Event()
.reportingController(VM_OP_GROUP + "/" + APP_NAME) .reportingController(Crd.GROUP + "/" + APP_NAME)
.action("ConsoleConnectionUpdate") .action("ConsoleConnectionUpdate")
.reason("Connection from " + event.clientHost()); .reason("Connection from " + event.clientHost());
K8s.createEvent(apiClient, vmStub.model().get(), evt); K8s.createEvent(apiClient, vmStub.model().get(), evt);
@ -142,13 +142,13 @@ public class ConsoleTracker extends VmDefUpdater {
vmStub.updateStatus(from -> { vmStub.updateStatus(from -> {
JsonObject status = updateCondition(from, "ConsoleConnected", false, JsonObject status = updateCondition(from, "ConsoleConnected", false,
"Disconnected", event.clientHost() + " has disconnected"); "Disconnected", event.clientHost() + " has disconnected");
status.addProperty("consoleClient", ""); status.addProperty(Status.CONSOLE_CLIENT, "");
return status; return status;
}); });
// Log event // Log event
var evt = new EventsV1Event() var evt = new EventsV1Event()
.reportingController(VM_OP_GROUP + "/" + APP_NAME) .reportingController(Crd.GROUP + "/" + APP_NAME)
.action("ConsoleConnectionUpdate") .action("ConsoleConnectionUpdate")
.reason("Disconnected from " + event.clientHost()); .reason("Disconnected from " + event.clientHost());
K8s.createEvent(apiClient, vmStub.model().get(), evt); K8s.createEvent(apiClient, vmStub.model().get(), evt);

View file

@ -24,8 +24,7 @@ import java.nio.file.Path;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.logging.Level; import java.util.logging.Level;
import static org.jdrupes.vmoperator.common.Constants.DATA_DISPLAY_PASSWORD; import org.jdrupes.vmoperator.common.Constants.DisplaySecret;
import static org.jdrupes.vmoperator.common.Constants.DATA_PASSWORD_EXPIRY;
import org.jdrupes.vmoperator.runner.qemu.commands.QmpSetDisplayPassword; import org.jdrupes.vmoperator.runner.qemu.commands.QmpSetDisplayPassword;
import org.jdrupes.vmoperator.runner.qemu.commands.QmpSetPasswordExpiry; import org.jdrupes.vmoperator.runner.qemu.commands.QmpSetPasswordExpiry;
import org.jdrupes.vmoperator.runner.qemu.events.ConfigureQemu; import org.jdrupes.vmoperator.runner.qemu.events.ConfigureQemu;
@ -64,7 +63,7 @@ public class DisplayController extends Component {
public DisplayController(Channel componentChannel, Path configDir) { public DisplayController(Channel componentChannel, Path configDir) {
super(componentChannel); super(componentChannel);
this.configDir = configDir; this.configDir = configDir;
fire(new WatchFile(configDir.resolve(DATA_DISPLAY_PASSWORD))); fire(new WatchFile(configDir.resolve(DisplaySecret.PASSWORD)));
} }
/** /**
@ -115,7 +114,7 @@ public class DisplayController extends Component {
@Handler @Handler
@SuppressWarnings("PMD.EmptyCatchBlock") @SuppressWarnings("PMD.EmptyCatchBlock")
public void onFileChanged(FileChanged event) { public void onFileChanged(FileChanged event) {
if (event.path().equals(configDir.resolve(DATA_DISPLAY_PASSWORD))) { if (event.path().equals(configDir.resolve(DisplaySecret.PASSWORD))) {
configurePassword(); configurePassword();
} }
} }
@ -130,7 +129,7 @@ public class DisplayController extends Component {
} }
private boolean setDisplayPassword() { private boolean setDisplayPassword() {
return readFromFile(DATA_DISPLAY_PASSWORD).map(password -> { return readFromFile(DisplaySecret.PASSWORD).map(password -> {
if (Objects.equals(this.currentPassword, password)) { if (Objects.equals(this.currentPassword, password)) {
return true; return true;
} }
@ -143,7 +142,7 @@ public class DisplayController extends Component {
} }
private void setPasswordExpiry() { private void setPasswordExpiry() {
readFromFile(DATA_PASSWORD_EXPIRY).ifPresent(expiry -> { readFromFile(DisplaySecret.EXPIRY).ifPresent(expiry -> {
logger.fine(() -> "Updating expiry time to " + expiry); logger.fine(() -> "Updating expiry time to " + expiry);
fire( fire(
new MonitorCommand(new QmpSetPasswordExpiry(protocol, expiry))); new MonitorCommand(new QmpSetPasswordExpiry(protocol, expiry)));

View file

@ -56,7 +56,7 @@ import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Option; import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options; import org.apache.commons.cli.Options;
import static org.jdrupes.vmoperator.common.Constants.APP_NAME; import static org.jdrupes.vmoperator.common.Constants.APP_NAME;
import static org.jdrupes.vmoperator.common.Constants.DATA_DISPLAY_PASSWORD; import org.jdrupes.vmoperator.common.Constants.DisplaySecret;
import org.jdrupes.vmoperator.runner.qemu.commands.QmpCont; import org.jdrupes.vmoperator.runner.qemu.commands.QmpCont;
import org.jdrupes.vmoperator.runner.qemu.commands.QmpReset; import org.jdrupes.vmoperator.runner.qemu.commands.QmpReset;
import org.jdrupes.vmoperator.runner.qemu.events.ConfigureQemu; import org.jdrupes.vmoperator.runner.qemu.events.ConfigureQemu;
@ -312,7 +312,7 @@ public class Runner extends Component {
// Add some values from other sources to configuration // Add some values from other sources to configuration
newConf.asOf = Instant.ofEpochSecond(configFile.lastModified()); newConf.asOf = Instant.ofEpochSecond(configFile.lastModified());
Path dsPath = configDir.resolve(DATA_DISPLAY_PASSWORD); Path dsPath = configDir.resolve(DisplaySecret.PASSWORD);
newConf.hasDisplayPassword = dsPath.toFile().canRead(); newConf.hasDisplayPassword = dsPath.toFile().canRead();
// Special actions for initial configuration (startup) // Special actions for initial configuration (startup)

View file

@ -33,8 +33,8 @@ import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.logging.Level; import java.util.logging.Level;
import static org.jdrupes.vmoperator.common.Constants.APP_NAME; import static org.jdrupes.vmoperator.common.Constants.APP_NAME;
import static org.jdrupes.vmoperator.common.Constants.VM_OP_GROUP; import org.jdrupes.vmoperator.common.Constants.Crd;
import static org.jdrupes.vmoperator.common.Constants.VM_OP_KIND_VM; import org.jdrupes.vmoperator.common.Constants.Status;
import org.jdrupes.vmoperator.common.K8s; import org.jdrupes.vmoperator.common.K8s;
import org.jdrupes.vmoperator.common.VmDefinition; import org.jdrupes.vmoperator.common.VmDefinition;
import org.jdrupes.vmoperator.common.VmDefinitionStub; import org.jdrupes.vmoperator.common.VmDefinitionStub;
@ -112,7 +112,7 @@ public class StatusUpdater extends VmDefUpdater {
} }
try { try {
vmStub = VmDefinitionStub.get(apiClient, vmStub = VmDefinitionStub.get(apiClient,
new GroupVersionKind(VM_OP_GROUP, "", VM_OP_KIND_VM), new GroupVersionKind(Crd.GROUP, "", Crd.KIND_VM),
namespace, vmName); namespace, vmName);
var vmDef = vmStub.model().orElse(null); var vmDef = vmStub.model().orElse(null);
if (vmDef == null) { if (vmDef == null) {
@ -121,7 +121,7 @@ public class StatusUpdater extends VmDefUpdater {
observedGeneration = vmDef.getMetadata().getGeneration(); observedGeneration = vmDef.getMetadata().getGeneration();
vmStub.updateStatus(from -> { vmStub.updateStatus(from -> {
JsonObject status = from.statusJson(); JsonObject status = from.statusJson();
status.remove("loggedInUser"); status.remove(Status.LOGGED_IN_USER);
return status; return status;
}); });
} catch (ApiException e) { } catch (ApiException e) {
@ -206,12 +206,12 @@ public class StatusUpdater extends VmDefUpdater {
} else if (event.runState() == RunState.STOPPED) { } else if (event.runState() == RunState.STOPPED) {
status.addProperty("ram", "0"); status.addProperty("ram", "0");
status.addProperty("cpus", 0); status.addProperty("cpus", 0);
status.remove("loggedInUser"); status.remove(Status.LOGGED_IN_USER);
} }
if (!running) { if (!running) {
// In case console connection was still present // In case console connection was still present
status.addProperty("consoleClient", ""); status.addProperty(Status.CONSOLE_CLIENT, "");
updateCondition(from, "ConsoleConnected", false, "VmStopped", updateCondition(from, "ConsoleConnected", false, "VmStopped",
"The VM is not running"); "The VM is not running");
@ -239,7 +239,7 @@ public class StatusUpdater extends VmDefUpdater {
// Log event // Log event
var evt = new EventsV1Event() var evt = new EventsV1Event()
.reportingController(VM_OP_GROUP + "/" + APP_NAME) .reportingController(Crd.GROUP + "/" + APP_NAME)
.action("StatusUpdate").reason(event.reason()) .action("StatusUpdate").reason(event.reason())
.note(event.message()); .note(event.message());
K8s.createEvent(apiClient, vmDef, evt); K8s.createEvent(apiClient, vmDef, evt);
@ -363,7 +363,8 @@ public class StatusUpdater extends VmDefUpdater {
throws ApiException { throws ApiException {
vmStub.updateStatus(from -> { vmStub.updateStatus(from -> {
JsonObject status = from.statusJson(); JsonObject status = from.statusJson();
status.addProperty("loggedInUser", event.triggering().user()); status.addProperty(Status.LOGGED_IN_USER,
event.triggering().user());
return status; return status;
}); });
} }
@ -378,7 +379,7 @@ public class StatusUpdater extends VmDefUpdater {
throws ApiException { throws ApiException {
vmStub.updateStatus(from -> { vmStub.updateStatus(from -> {
JsonObject status = from.statusJson(); JsonObject status = from.statusJson();
status.remove("loggedInUser"); status.remove(Status.LOGGED_IN_USER);
return status; return status;
}); });
} }