Use less gson internally.
This commit is contained in:
parent
8e692a03fe
commit
c8781c2d8e
33 changed files with 1405 additions and 905 deletions
|
|
@ -157,27 +157,6 @@ public class K8s {
|
|||
return Optional.of(apiRes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an object from its metadata.
|
||||
*
|
||||
* @param <T> the generic type
|
||||
* @param <LT> the generic type
|
||||
* @param api the api
|
||||
* @param meta the meta
|
||||
* @return the object
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("PMD.GenericsNaming")
|
||||
public static <T extends KubernetesObject, LT extends KubernetesListObject>
|
||||
Optional<T>
|
||||
get(GenericKubernetesApi<T, LT> api, V1ObjectMeta meta) {
|
||||
var response = api.get(meta.getNamespace(), meta.getName());
|
||||
if (response.isSuccess()) {
|
||||
return Optional.of(response.getObject());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the given patch data.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import io.kubernetes.client.openapi.ApiException;
|
|||
import io.kubernetes.client.util.Strings;
|
||||
import io.kubernetes.client.util.generic.GenericKubernetesApi;
|
||||
import io.kubernetes.client.util.generic.KubernetesApiResponse;
|
||||
import io.kubernetes.client.util.generic.dynamic.DynamicKubernetesObject;
|
||||
import io.kubernetes.client.util.generic.options.GetOptions;
|
||||
import io.kubernetes.client.util.generic.options.ListOptions;
|
||||
import io.kubernetes.client.util.generic.options.PatchOptions;
|
||||
|
|
@ -47,7 +48,7 @@ import java.util.function.Function;
|
|||
* @param <O> the generic type
|
||||
* @param <L> the generic type
|
||||
*/
|
||||
@SuppressWarnings("PMD.DataflowAnomalyAnalysis")
|
||||
@SuppressWarnings({ "PMD.DataflowAnomalyAnalysis", "PMD.TooManyMethods" })
|
||||
public class K8sGenericStub<O extends KubernetesObject,
|
||||
L extends KubernetesListObject> {
|
||||
protected final K8sClient client;
|
||||
|
|
@ -224,7 +225,7 @@ public class K8sGenericStub<O extends KubernetesObject,
|
|||
* @param patchType the patch type
|
||||
* @param patch the patch
|
||||
* @param options the options
|
||||
* @return the kubernetes api response
|
||||
* @return the kubernetes api response if successful
|
||||
* @throws ApiException the api exception
|
||||
*/
|
||||
public Optional<O> patch(String patchType, V1Patch patch,
|
||||
|
|
@ -239,7 +240,7 @@ public class K8sGenericStub<O extends KubernetesObject,
|
|||
*
|
||||
* @param patchType the patch type
|
||||
* @param patch the patch
|
||||
* @return the kubernetes api response
|
||||
* @return the kubernetes api response if successful
|
||||
* @throws ApiException the api exception
|
||||
*/
|
||||
public Optional<O>
|
||||
|
|
@ -248,6 +249,21 @@ public class K8sGenericStub<O extends KubernetesObject,
|
|||
return patch(patchType, patch, opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the given definition.
|
||||
*
|
||||
* @param def the def
|
||||
* @return the kubernetes api response if successful
|
||||
* @throws ApiException the api exception
|
||||
*/
|
||||
public Optional<O> apply(DynamicKubernetesObject def) throws ApiException {
|
||||
PatchOptions opts = new PatchOptions();
|
||||
opts.setForce(true);
|
||||
opts.setFieldManager("kubernetes-java-kubectl-apply");
|
||||
return patch(V1Patch.PATCH_FORMAT_APPLY_YAML,
|
||||
new V1Patch(client.getJSON().serialize(def)), opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the object.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,332 @@
|
|||
/*
|
||||
* VM-Operator
|
||||
* Copyright (C) 2024 Michael N. Lipp
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.jdrupes.vmoperator.common;
|
||||
|
||||
import io.kubernetes.client.openapi.models.V1ObjectMeta;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import org.jdrupes.vmoperator.util.DataPath;
|
||||
|
||||
/**
|
||||
* Represents a VM definition.
|
||||
*/
|
||||
@SuppressWarnings({ "PMD.DataClass" })
|
||||
public class VmDefinition {
|
||||
|
||||
private String kind;
|
||||
private String apiVersion;
|
||||
private V1ObjectMeta metadata;
|
||||
private Map<String, Object> spec;
|
||||
private Map<String, Object> status;
|
||||
private final Map<String, Object> extra = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* The VM state from the VM definition.
|
||||
*/
|
||||
public enum RequestedVmState {
|
||||
STOPPED, RUNNING
|
||||
}
|
||||
|
||||
/**
|
||||
* Permissions for accessing and manipulating the VM.
|
||||
*/
|
||||
public enum Permission {
|
||||
START("start"), STOP("stop"), RESET("reset"),
|
||||
ACCESS_CONSOLE("accessConsole");
|
||||
|
||||
@SuppressWarnings("PMD.UseConcurrentHashMap")
|
||||
private static Map<String, Permission> reprs = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (var value : EnumSet.allOf(Permission.class)) {
|
||||
reprs.put(value.repr, value);
|
||||
}
|
||||
}
|
||||
|
||||
private final String repr;
|
||||
|
||||
Permission(String repr) {
|
||||
this.repr = repr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create permission from representation in CRD.
|
||||
*
|
||||
* @param value the value
|
||||
* @return the permission
|
||||
*/
|
||||
@SuppressWarnings("PMD.AvoidLiteralsInIfCondition")
|
||||
public static Set<Permission> parse(String value) {
|
||||
if ("*".equals(value)) {
|
||||
return EnumSet.allOf(Permission.class);
|
||||
}
|
||||
return Set.of(reprs.get(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return repr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the kind.
|
||||
*
|
||||
* @return the kind
|
||||
*/
|
||||
public String getKind() {
|
||||
return kind;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the kind.
|
||||
*
|
||||
* @param kind the kind to set
|
||||
*/
|
||||
public void setKind(String kind) {
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the api version.
|
||||
*
|
||||
* @return the apiVersion
|
||||
*/
|
||||
public String getApiVersion() {
|
||||
return apiVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the api version.
|
||||
*
|
||||
* @param apiVersion the apiVersion to set
|
||||
*/
|
||||
public void setApiVersion(String apiVersion) {
|
||||
this.apiVersion = apiVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the metadata.
|
||||
*
|
||||
* @return the metadata
|
||||
*/
|
||||
public V1ObjectMeta getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the metadata.
|
||||
*
|
||||
* @return the metadata
|
||||
*/
|
||||
public V1ObjectMeta metadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the metadata.
|
||||
*
|
||||
* @param metadata the metadata to set
|
||||
*/
|
||||
public void setMetadata(V1ObjectMeta metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the spec.
|
||||
*
|
||||
* @return the spec
|
||||
*/
|
||||
public Map<String, Object> getSpec() {
|
||||
return spec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the spec.
|
||||
*
|
||||
* @return the spec
|
||||
*/
|
||||
public Map<String, Object> spec() {
|
||||
return spec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value from the spec using {@link DataPath#get}.
|
||||
*
|
||||
* @param <T> the generic type
|
||||
* @param selectors the selectors
|
||||
* @return the value, if found
|
||||
*/
|
||||
public <T> Optional<T> fromSpec(Object... selectors) {
|
||||
return DataPath.get(spec, selectors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value from the `spec().get("vm")` using {@link DataPath#get}.
|
||||
*
|
||||
* @param <T> the generic type
|
||||
* @param selectors the selectors
|
||||
* @return the value, if found
|
||||
*/
|
||||
public <T> Optional<T> fromVm(Object... selectors) {
|
||||
return DataPath.get(spec, "vm")
|
||||
.flatMap(vm -> DataPath.get(vm, selectors));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the spec.
|
||||
*
|
||||
* @param spec the spec to set
|
||||
*/
|
||||
public void setSpec(Map<String, Object> spec) {
|
||||
this.spec = spec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status.
|
||||
*
|
||||
* @return the status
|
||||
*/
|
||||
public Map<String, Object> getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status.
|
||||
*
|
||||
* @return the status
|
||||
*/
|
||||
public Map<String, Object> status() {
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value from the status using {@link DataPath#get}.
|
||||
*
|
||||
* @param <T> the generic type
|
||||
* @param selectors the selectors
|
||||
* @return the value, if found
|
||||
*/
|
||||
public <T> Optional<T> fromStatus(Object... selectors) {
|
||||
return DataPath.get(status, selectors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the status.
|
||||
*
|
||||
* @param status the status to set
|
||||
*/
|
||||
public void setStatus(Map<String, Object> status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set extra data (locally used, unknown to kubernetes).
|
||||
*
|
||||
* @param property the property
|
||||
* @param value the value
|
||||
* @return the VM definition
|
||||
*/
|
||||
public VmDefinition extra(String property, Object value) {
|
||||
extra.put(property, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return extra data.
|
||||
*
|
||||
* @param property the property
|
||||
* @return the object
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T extra(String property) {
|
||||
return (T) extra.get(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the definition's name.
|
||||
*
|
||||
* @return the string
|
||||
*/
|
||||
public String name() {
|
||||
return metadata.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the definition's namespace.
|
||||
*
|
||||
* @return the string
|
||||
*/
|
||||
public String namespace() {
|
||||
return metadata.getNamespace();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the requested VM state
|
||||
*
|
||||
* @return the string
|
||||
*/
|
||||
public RequestedVmState vmState() {
|
||||
// TODO
|
||||
return fromVm("state")
|
||||
.map(s -> "Running".equals(s) ? RequestedVmState.RUNNING
|
||||
: RequestedVmState.STOPPED)
|
||||
.orElse(RequestedVmState.STOPPED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect all permissions for the given user with the given roles.
|
||||
*
|
||||
* @param user the user
|
||||
* @param roles the roles
|
||||
* @return the sets the
|
||||
*/
|
||||
public Set<Permission> permissionsFor(String user,
|
||||
Collection<String> roles) {
|
||||
return this.<List<Map<String, Object>>> fromSpec("permissions")
|
||||
.orElse(Collections.emptyList()).stream()
|
||||
.filter(p -> DataPath.get(p, "user").map(u -> u.equals(user))
|
||||
.orElse(false)
|
||||
|| DataPath.get(p, "role").map(roles::contains).orElse(false))
|
||||
.map(p -> DataPath.<List<String>> get(p, "may")
|
||||
.orElse(Collections.emptyList()).stream())
|
||||
.flatMap(Function.identity())
|
||||
.map(Permission::parse).map(Set::stream)
|
||||
.flatMap(Function.identity()).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the display password serial.
|
||||
*
|
||||
* @return the optional
|
||||
*/
|
||||
public Optional<Long> displayPasswordSerial() {
|
||||
return this.<Number> fromStatus("displayPasswordSerial")
|
||||
.map(Number::longValue);
|
||||
}
|
||||
}
|
||||
|
|
@ -20,16 +20,6 @@ package org.jdrupes.vmoperator.common;
|
|||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import org.jdrupes.vmoperator.util.GsonPtr;
|
||||
|
||||
/**
|
||||
* Represents a VM definition.
|
||||
|
|
@ -37,55 +27,6 @@ import org.jdrupes.vmoperator.util.GsonPtr;
|
|||
@SuppressWarnings("PMD.DataClass")
|
||||
public class VmDefinitionModel extends K8sDynamicModel {
|
||||
|
||||
/**
|
||||
* The VM state from the VM definition.
|
||||
*/
|
||||
public enum RequestedVmState {
|
||||
STOPPED, RUNNING
|
||||
}
|
||||
|
||||
/**
|
||||
* Permissions for accessing and manipulating the VM.
|
||||
*/
|
||||
public enum Permission {
|
||||
START("start"), STOP("stop"), RESET("reset"),
|
||||
ACCESS_CONSOLE("accessConsole");
|
||||
|
||||
@SuppressWarnings("PMD.UseConcurrentHashMap")
|
||||
private static Map<String, Permission> reprs = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (var value : EnumSet.allOf(Permission.class)) {
|
||||
reprs.put(value.repr, value);
|
||||
}
|
||||
}
|
||||
|
||||
private final String repr;
|
||||
|
||||
Permission(String repr) {
|
||||
this.repr = repr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create permission from representation in CRD.
|
||||
*
|
||||
* @param value the value
|
||||
* @return the permission
|
||||
*/
|
||||
@SuppressWarnings("PMD.AvoidLiteralsInIfCondition")
|
||||
public static Set<Permission> parse(String value) {
|
||||
if ("*".equals(value)) {
|
||||
return EnumSet.allOf(Permission.class);
|
||||
}
|
||||
return Set.of(reprs.get(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return repr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new model from the JSON representation.
|
||||
*
|
||||
|
|
@ -95,49 +36,4 @@ public class VmDefinitionModel extends K8sDynamicModel {
|
|||
public VmDefinitionModel(Gson delegate, JsonObject json) {
|
||||
super(delegate, json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect all permissions for the given user with the given roles.
|
||||
*
|
||||
* @param user the user
|
||||
* @param roles the roles
|
||||
* @return the sets the
|
||||
*/
|
||||
public Set<Permission> permissionsFor(String user,
|
||||
Collection<String> roles) {
|
||||
return GsonPtr.to(data())
|
||||
.getAsListOf(JsonObject.class, "spec", "permissions")
|
||||
.stream().filter(p -> GsonPtr.to(p).getAsString("user")
|
||||
.map(u -> u.equals(user)).orElse(false)
|
||||
|| GsonPtr.to(p).getAsString("role").map(roles::contains)
|
||||
.orElse(false))
|
||||
.map(p -> GsonPtr.to(p).getAsListOf(JsonPrimitive.class, "may")
|
||||
.stream())
|
||||
.flatMap(Function.identity()).map(p -> p.getAsString())
|
||||
.map(Permission::parse).map(Set::stream)
|
||||
.flatMap(Function.identity()).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the requested VM state
|
||||
*
|
||||
* @return the string
|
||||
*/
|
||||
public RequestedVmState vmState() {
|
||||
return GsonPtr.to(data()).getAsString("spec", "vm", "state")
|
||||
.map(s -> "Running".equals(s) ? RequestedVmState.RUNNING
|
||||
: RequestedVmState.STOPPED)
|
||||
.orElse(RequestedVmState.STOPPED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the display password serial.
|
||||
*
|
||||
* @return the optional
|
||||
*/
|
||||
public Optional<Long> displayPasswordSerial() {
|
||||
return GsonPtr.to(status())
|
||||
.get(JsonPrimitive.class, "displayPasswordSerial")
|
||||
.map(JsonPrimitive::getAsLong);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue