Take different approach to finding CR.
Requires less privileges.
This commit is contained in:
parent
2210dbcae2
commit
ea6751282c
2 changed files with 61 additions and 59 deletions
|
|
@ -22,8 +22,10 @@ import com.google.gson.JsonObject;
|
||||||
import io.kubernetes.client.custom.Quantity;
|
import io.kubernetes.client.custom.Quantity;
|
||||||
import io.kubernetes.client.custom.Quantity.Format;
|
import io.kubernetes.client.custom.Quantity.Format;
|
||||||
import io.kubernetes.client.openapi.ApiException;
|
import io.kubernetes.client.openapi.ApiException;
|
||||||
import io.kubernetes.client.openapi.apis.ApiextensionsV1Api;
|
import io.kubernetes.client.openapi.apis.ApisApi;
|
||||||
import io.kubernetes.client.openapi.models.V1CustomResourceDefinitionVersion;
|
import io.kubernetes.client.openapi.apis.CustomObjectsApi;
|
||||||
|
import io.kubernetes.client.openapi.models.V1APIGroup;
|
||||||
|
import io.kubernetes.client.openapi.models.V1GroupVersionForDiscovery;
|
||||||
import io.kubernetes.client.util.Config;
|
import io.kubernetes.client.util.Config;
|
||||||
import io.kubernetes.client.util.generic.dynamic.DynamicKubernetesApi;
|
import io.kubernetes.client.util.generic.dynamic.DynamicKubernetesApi;
|
||||||
import io.kubernetes.client.util.generic.dynamic.DynamicKubernetesObject;
|
import io.kubernetes.client.util.generic.dynamic.DynamicKubernetesObject;
|
||||||
|
|
@ -41,12 +43,13 @@ import org.jdrupes.vmoperator.runner.qemu.events.HotpluggableCpuStatus;
|
||||||
import org.jdrupes.vmoperator.runner.qemu.events.RunnerConfigurationUpdate;
|
import org.jdrupes.vmoperator.runner.qemu.events.RunnerConfigurationUpdate;
|
||||||
import org.jdrupes.vmoperator.runner.qemu.events.RunnerStateChange;
|
import org.jdrupes.vmoperator.runner.qemu.events.RunnerStateChange;
|
||||||
import org.jdrupes.vmoperator.runner.qemu.events.RunnerStateChange.State;
|
import org.jdrupes.vmoperator.runner.qemu.events.RunnerStateChange.State;
|
||||||
import static org.jdrupes.vmoperator.util.Constants.VM_OP_CRD_NAME;
|
|
||||||
import static org.jdrupes.vmoperator.util.Constants.VM_OP_GROUP;
|
import static org.jdrupes.vmoperator.util.Constants.VM_OP_GROUP;
|
||||||
|
import static org.jdrupes.vmoperator.util.Constants.VM_OP_KIND_VM;
|
||||||
import org.jdrupes.vmoperator.util.GsonPtr;
|
import org.jdrupes.vmoperator.util.GsonPtr;
|
||||||
import org.jgrapes.core.Channel;
|
import org.jgrapes.core.Channel;
|
||||||
import org.jgrapes.core.Component;
|
import org.jgrapes.core.Component;
|
||||||
import org.jgrapes.core.annotation.Handler;
|
import org.jgrapes.core.annotation.Handler;
|
||||||
|
import org.jgrapes.core.events.HandlingError;
|
||||||
import org.jgrapes.core.events.Start;
|
import org.jgrapes.core.events.Start;
|
||||||
import org.jgrapes.util.events.ConfigurationUpdate;
|
import org.jgrapes.util.events.ConfigurationUpdate;
|
||||||
import org.jgrapes.util.events.InitialConfiguration;
|
import org.jgrapes.util.events.InitialConfiguration;
|
||||||
|
|
@ -73,6 +76,20 @@ public class StatusUpdater extends Component {
|
||||||
super(componentChannel);
|
super(componentChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On handling error.
|
||||||
|
*
|
||||||
|
* @param event the event
|
||||||
|
*/
|
||||||
|
@Handler(channels = Channel.class)
|
||||||
|
public void onHandlingError(HandlingError event) {
|
||||||
|
if (event.throwable() instanceof ApiException exc) {
|
||||||
|
logger.log(Level.WARNING, exc,
|
||||||
|
() -> "Problem accessing kubernetes: " + exc.getResponseBody());
|
||||||
|
event.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* On configuration update.
|
* On configuration update.
|
||||||
*
|
*
|
||||||
|
|
@ -114,52 +131,41 @@ public class StatusUpdater extends Component {
|
||||||
* Handle the start event.
|
* Handle the start event.
|
||||||
*
|
*
|
||||||
* @param event the event
|
* @param event the event
|
||||||
|
* @throws IOException
|
||||||
|
* @throws ApiException
|
||||||
*/
|
*/
|
||||||
@Handler
|
@Handler
|
||||||
@SuppressWarnings({ "PMD.DataflowAnomalyAnalysis",
|
@SuppressWarnings({ "PMD.DataflowAnomalyAnalysis",
|
||||||
"PMD.AvoidInstantiatingObjectsInLoops" })
|
"PMD.AvoidInstantiatingObjectsInLoops", "PMD.AvoidDuplicateLiterals" })
|
||||||
public void onStart(Start event) {
|
public void onStart(Start event) throws IOException, ApiException {
|
||||||
try {
|
|
||||||
var client = Config.defaultClient();
|
var client = Config.defaultClient();
|
||||||
var extsApi = new ApiextensionsV1Api(client);
|
var apis = new ApisApi(client).getAPIVersions();
|
||||||
var crds = extsApi.listCustomResourceDefinition(null, null, null,
|
var crdVersions = apis.getGroups().stream()
|
||||||
"metadata.name=" + VM_OP_CRD_NAME, null, null, null,
|
.filter(g -> g.getName().equals(VM_OP_GROUP)).findFirst()
|
||||||
null, null, null);
|
.map(V1APIGroup::getVersions).stream().flatMap(l -> l.stream())
|
||||||
if (crds.getItems().isEmpty()) {
|
.map(V1GroupVersionForDiscovery::getVersion).toList();
|
||||||
logger.warning(() -> "CRD is unknown, status will not"
|
var coa = new CustomObjectsApi(client);
|
||||||
+ " be updated.");
|
for (var crdVersion : crdVersions) {
|
||||||
return;
|
var crdApiRes = coa.getAPIResources(VM_OP_GROUP,
|
||||||
|
crdVersion).getResources().stream()
|
||||||
|
.filter(r -> VM_OP_KIND_VM.equals(r.getKind())).findFirst();
|
||||||
|
if (crdApiRes.isEmpty()) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
var crd = crds.getItems().get(0);
|
var crApi = new DynamicKubernetesApi(VM_OP_GROUP,
|
||||||
if (crd.getSpec().getVersions().stream()
|
crdVersion, crdApiRes.get().getName(), client);
|
||||||
.filter(v -> v.getSubresources() == null).findAny()
|
var vmCr = crApi.get(namespace, vmName).throwsApiException();
|
||||||
.isPresent()) {
|
if (vmCr.isSuccess()) {
|
||||||
logger.warning(() -> "You are using an old version of the CRD,"
|
vmCrApi = crApi;
|
||||||
+ " status will not be updated.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var crdPlural = crd.getSpec().getNames().getPlural();
|
|
||||||
var vmOpApiVersions = crd.getSpec().getVersions().stream()
|
|
||||||
.map(V1CustomResourceDefinitionVersion::getName).toList();
|
|
||||||
for (var apiVer : vmOpApiVersions) {
|
|
||||||
var api = new DynamicKubernetesApi(VM_OP_GROUP, apiVer,
|
|
||||||
crdPlural, client);
|
|
||||||
var res = api.get(namespace, vmName);
|
|
||||||
if (res.isSuccess()) {
|
|
||||||
vmCrApi = api;
|
|
||||||
observedGeneration
|
observedGeneration
|
||||||
= res.getObject().getMetadata().getGeneration();
|
= vmCr.getObject().getMetadata().getGeneration();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (vmCrApi == null) {
|
if (vmCrApi == null) {
|
||||||
logger.warning(() -> "VM's CR is unknown, status will not"
|
logger.warning(() -> "Cannot find VM's CR, status will not"
|
||||||
+ " be updated.");
|
+ " be updated.");
|
||||||
}
|
}
|
||||||
} catch (IOException | ApiException e) {
|
|
||||||
logger.log(Level.WARNING, e, () -> "Cannot access kubernetes: "
|
|
||||||
+ e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("PMD.AvoidDuplicateLiterals")
|
@SuppressWarnings("PMD.AvoidDuplicateLiterals")
|
||||||
|
|
@ -189,9 +195,8 @@ public class StatusUpdater extends Component {
|
||||||
vmCrApi.updateStatus(vmCr, from -> {
|
vmCrApi.updateStatus(vmCr, from -> {
|
||||||
JsonObject status = currentStatus(from);
|
JsonObject status = currentStatus(from);
|
||||||
status.getAsJsonArray("conditions").asList().stream()
|
status.getAsJsonArray("conditions").asList().stream()
|
||||||
.map(cond -> (JsonObject) cond)
|
.map(cond -> (JsonObject) cond).filter(cond -> "Running"
|
||||||
.filter(
|
.equals(cond.get("type").getAsString()))
|
||||||
cond -> "Running".equals(cond.get("type").getAsString()))
|
|
||||||
.forEach(cond -> cond.addProperty("observedGeneration",
|
.forEach(cond -> cond.addProperty("observedGeneration",
|
||||||
from.getMetadata().getGeneration()));
|
from.getMetadata().getGeneration()));
|
||||||
return status;
|
return status;
|
||||||
|
|
@ -202,7 +207,7 @@ public class StatusUpdater extends Component {
|
||||||
* On runner state changed.
|
* On runner state changed.
|
||||||
*
|
*
|
||||||
* @param event the event
|
* @param event the event
|
||||||
* @throws ApiException the api exception
|
* @throws ApiException
|
||||||
*/
|
*/
|
||||||
@Handler
|
@Handler
|
||||||
public void onRunnerStateChanged(RunnerStateChange event)
|
public void onRunnerStateChanged(RunnerStateChange event)
|
||||||
|
|
@ -210,8 +215,8 @@ public class StatusUpdater extends Component {
|
||||||
if (vmCrApi == null) {
|
if (vmCrApi == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var vmCr = vmCrApi.get(namespace, vmName)
|
var vmCr = vmCrApi.get(namespace, vmName).throwsApiException()
|
||||||
.throwsApiException().getObject();
|
.getObject();
|
||||||
vmCrApi.updateStatus(vmCr, from -> {
|
vmCrApi.updateStatus(vmCr, from -> {
|
||||||
JsonObject status = currentStatus(from);
|
JsonObject status = currentStatus(from);
|
||||||
status.getAsJsonArray("conditions").asList().stream()
|
status.getAsJsonArray("conditions").asList().stream()
|
||||||
|
|
@ -230,7 +235,7 @@ public class StatusUpdater extends Component {
|
||||||
status.addProperty("cpus", 0);
|
status.addProperty("cpus", 0);
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
});
|
}).throwsApiException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateRunningCondition(RunnerStateChange event,
|
private void updateRunningCondition(RunnerStateChange event,
|
||||||
|
|
@ -266,15 +271,15 @@ public class StatusUpdater extends Component {
|
||||||
if (vmCrApi == null) {
|
if (vmCrApi == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var vmCr
|
var vmCr = vmCrApi.get(namespace, vmName).throwsApiException()
|
||||||
= vmCrApi.get(namespace, vmName).throwsApiException().getObject();
|
.getObject();
|
||||||
vmCrApi.updateStatus(vmCr, from -> {
|
vmCrApi.updateStatus(vmCr, from -> {
|
||||||
JsonObject status = currentStatus(from);
|
JsonObject status = currentStatus(from);
|
||||||
status.addProperty("ram",
|
status.addProperty("ram",
|
||||||
new Quantity(new BigDecimal(event.size()), Format.BINARY_SI)
|
new Quantity(new BigDecimal(event.size()), Format.BINARY_SI)
|
||||||
.toSuffixedString());
|
.toSuffixedString());
|
||||||
return status;
|
return status;
|
||||||
});
|
}).throwsApiException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -288,12 +293,12 @@ public class StatusUpdater extends Component {
|
||||||
if (vmCrApi == null) {
|
if (vmCrApi == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var vmCr
|
var vmCr = vmCrApi.get(namespace, vmName).throwsApiException()
|
||||||
= vmCrApi.get(namespace, vmName).throwsApiException().getObject();
|
.getObject();
|
||||||
vmCrApi.updateStatus(vmCr, from -> {
|
vmCrApi.updateStatus(vmCr, from -> {
|
||||||
JsonObject status = currentStatus(from);
|
JsonObject status = currentStatus(from);
|
||||||
status.addProperty("cpus", event.usedCpus().size());
|
status.addProperty("cpus", event.usedCpus().size());
|
||||||
return status;
|
return status;
|
||||||
});
|
}).throwsApiException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,6 @@ public class Constants {
|
||||||
/** The Constant VM_OP_GROUP. */
|
/** The Constant VM_OP_GROUP. */
|
||||||
public static final String VM_OP_GROUP = "vmoperator.jdrupes.org";
|
public static final String VM_OP_GROUP = "vmoperator.jdrupes.org";
|
||||||
|
|
||||||
/** The Constant VM_OP_CRD_NAME. */
|
|
||||||
public static final String VM_OP_CRD_NAME = "vms." + VM_OP_GROUP;
|
|
||||||
|
|
||||||
/** The Constant VM_OP_KIND_VM. */
|
/** The Constant VM_OP_KIND_VM. */
|
||||||
public static final String VM_OP_KIND_VM = "VirtualMachine";
|
public static final String VM_OP_KIND_VM = "VirtualMachine";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue