use of io.fabric8.kubernetes.client.Watcher.Action in project devspaces-images by redhat-developer.
the class KubernetesDeployments method watchEvents.
/**
* Registers a specified handler for handling events about changes in pods containers. Registering
* several handlers doesn't create multiple websocket connections, so it is efficient to call this
* method several times instead of using composite handler to combine other handlers.
*
* @param handler pod container events handler
* @throws InfrastructureException if any error occurs while watcher starting
*/
public void watchEvents(PodEventHandler handler) throws InfrastructureException {
if (containerWatch == null) {
final Watcher<Event> watcher = new Watcher<>() {
@Override
public void eventReceived(Action action, Event event) {
ObjectReference involvedObject = event.getInvolvedObject();
if (POD_OBJECT_KIND.equals(involvedObject.getKind()) || REPLICASET_OBJECT_KIND.equals(involvedObject.getKind()) || DEPLOYMENT_OBJECT_KIND.equals(involvedObject.getKind())) {
String podName = involvedObject.getName();
String lastTimestamp = event.getLastTimestamp();
if (lastTimestamp == null) {
String firstTimestamp = event.getFirstTimestamp();
if (firstTimestamp != null) {
// Done in the same way like it made in
// https://github.com/kubernetes/kubernetes/pull/86557
lastTimestamp = firstTimestamp;
} else {
LOG.debug("lastTimestamp and firstTimestamp are undefined. Event: {}. Fallback to the current time.", event);
lastTimestamp = PodEvents.convertDateToEventTimestamp(new Date());
}
}
PodEvent podEvent = new PodEvent(podName, getContainerName(involvedObject.getFieldPath()), event.getReason(), event.getMessage(), event.getMetadata().getCreationTimestamp(), lastTimestamp);
try {
if (happenedAfterWatcherInitialization(podEvent)) {
containerEventsHandlers.forEach(h -> h.handle(podEvent));
}
} catch (ParseException e) {
LOG.error("Failed to parse last timestamp of the event. Cause: {}. Event: {}", e.getMessage(), podEvent, e);
}
}
}
@Override
public void onClose(WatcherException ignored) {
}
/**
* Returns the container name if the event is related to container. When the event is
* related to container `fieldPath` field contain information in the following format:
* `spec.container{web}`, where `web` is container name
*/
private String getContainerName(String fieldPath) {
String containerName = null;
if (fieldPath != null) {
Matcher containerFieldMatcher = CONTAINER_FIELD_PATH_PATTERN.matcher(fieldPath);
if (containerFieldMatcher.matches()) {
containerName = containerFieldMatcher.group(CONTAINER_NAME_GROUP);
}
}
return containerName;
}
/**
* Returns true if 'lastTimestamp' of the event is *after* the time of the watcher
* initialization
*/
private boolean happenedAfterWatcherInitialization(PodEvent event) throws ParseException {
String eventLastTimestamp = event.getLastTimestamp();
Date eventLastTimestampDate = PodEvents.convertEventTimestampToDate(eventLastTimestamp);
return eventLastTimestampDate.after(watcherInitializationDate);
}
};
try {
watcherInitializationDate = new Date();
containerWatch = clientFactory.create(workspaceId).v1().events().inNamespace(namespace).watch(watcher);
} catch (KubernetesClientException ex) {
throw new KubernetesInfrastructureException(ex);
}
}
containerEventsHandlers.add(handler);
}
use of io.fabric8.kubernetes.client.Watcher.Action in project devspaces-images by redhat-developer.
the class KubernetesIngresses method wait.
public Ingress wait(String name, long timeout, TimeUnit timeoutUnit, Predicate<Ingress> predicate) throws InfrastructureException {
CompletableFuture<Ingress> future = new CompletableFuture<>();
Watch watch = null;
try {
Resource<Ingress> ingressResource = clientFactory.create(workspaceId).network().v1().ingresses().inNamespace(namespace).withName(name);
watch = ingressResource.watch(new Watcher<>() {
@Override
public void eventReceived(Action action, Ingress ingress) {
if (predicate.test(ingress)) {
future.complete(ingress);
}
}
@Override
public void onClose(WatcherException cause) {
future.completeExceptionally(new InfrastructureException("Waiting for ingress '" + name + "' was interrupted"));
}
});
Ingress actualIngress = ingressResource.get();
if (actualIngress == null) {
throw new InfrastructureException("Specified ingress " + name + " doesn't exist");
}
if (predicate.test(actualIngress)) {
return actualIngress;
}
try {
return future.get(timeout, timeoutUnit);
} catch (ExecutionException e) {
throw new InfrastructureException(e.getCause().getMessage(), e);
} catch (TimeoutException e) {
throw new InfrastructureException("Waiting for ingress '" + name + "' reached timeout");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new InfrastructureException("Waiting for ingress '" + name + "' was interrupted");
}
} catch (KubernetesClientException e) {
throw new KubernetesInfrastructureException(e);
} finally {
if (watch != null) {
watch.close();
}
}
}
use of io.fabric8.kubernetes.client.Watcher.Action in project devspaces-images by redhat-developer.
the class KubernetesNamespace method waitDefaultServiceAccount.
/**
* Waits few seconds until 'default' service account become available otherwise an infrastructure
* exception will be thrown.
*/
protected void waitDefaultServiceAccount(String namespaceName, KubernetesClient client) throws InfrastructureException {
final Predicate<ServiceAccount> predicate = Objects::nonNull;
final CompletableFuture<ServiceAccount> future = new CompletableFuture<>();
Watch watch = null;
try {
final Resource<ServiceAccount> saResource = client.serviceAccounts().inNamespace(namespaceName).withName(DEFAULT_SERVICE_ACCOUNT_NAME);
watch = saResource.watch(new Watcher<>() {
@Override
public void eventReceived(Action action, ServiceAccount serviceAccount) {
if (predicate.test(serviceAccount)) {
future.complete(serviceAccount);
}
}
@Override
public void onClose(WatcherException cause) {
future.completeExceptionally(new InfrastructureException("Waiting for service account '" + DEFAULT_SERVICE_ACCOUNT_NAME + "' was interrupted"));
}
});
if (predicate.test(saResource.get())) {
return;
}
try {
future.get(SERVICE_ACCOUNT_READINESS_TIMEOUT_SEC, TimeUnit.SECONDS);
} catch (ExecutionException ex) {
throw new InfrastructureException(ex.getCause().getMessage(), ex);
} catch (TimeoutException ex) {
throw new InfrastructureException("Waiting for service account '" + DEFAULT_SERVICE_ACCOUNT_NAME + "' reached timeout");
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
throw new InfrastructureException("Waiting for service account '" + DEFAULT_SERVICE_ACCOUNT_NAME + "' was interrupted");
}
} catch (KubernetesClientException ex) {
throw new KubernetesInfrastructureException(ex);
} finally {
if (watch != null) {
watch.close();
}
}
}
use of io.fabric8.kubernetes.client.Watcher.Action in project kubernetes-client by fabric8io.
the class CRDExample method main.
/**
* Example of Cluster and Namespaced scoped K8S Custom Resources.
* To test Cluster scoped resource use "--cluster" as first argument.
* To test Namespaced resource provide namespace as first argument (namespace must exists in K8S).
*
* @param args Either "--cluster" or namespace name.
*/
public static void main(String[] args) {
boolean resourceNamespaced = true;
String namespace = null;
if (args.length > 0) {
if ("--cluster".equals(args[0])) {
resourceNamespaced = false;
} else {
namespace = args[0];
}
}
try (final KubernetesClient client = new KubernetesClientBuilder().build()) {
if (resourceNamespaced) {
if (namespace == null) {
namespace = client.getNamespace();
}
if (namespace == null) {
System.err.println("No namespace specified and no default defined!");
return;
}
System.out.println("Using namespace: " + namespace);
} else {
System.out.println("Creating cluster scoped resource");
}
if (LOG_ROOT_PATHS) {
RootPaths rootPaths = client.rootPaths();
if (rootPaths != null) {
List<String> paths = rootPaths.getPaths();
if (paths != null) {
System.out.println("Supported API Paths:");
for (String path : paths) {
System.out.println(" " + path);
}
System.out.println();
}
}
}
CustomResourceDefinitionList crds = client.apiextensions().v1().customResourceDefinitions().list();
List<CustomResourceDefinition> crdsItems = crds.getItems();
System.out.println("Found " + crdsItems.size() + " CRD(s)");
CustomResourceDefinition dummyCRD = null;
final String dummyCRDName = CustomResource.getCRDName(Dummy.class);
for (CustomResourceDefinition crd : crdsItems) {
ObjectMeta metadata = crd.getMetadata();
if (metadata != null) {
String name = metadata.getName();
System.out.println(" " + name + " => " + metadata.getSelfLink());
if (dummyCRDName.equals(name)) {
dummyCRD = crd;
}
}
}
if (dummyCRD != null) {
System.out.println("Found CRD: " + dummyCRD.getMetadata().getSelfLink());
} else {
dummyCRD = CustomResourceDefinitionContext.v1CRDFromCustomResourceType(Dummy.class).editSpec().editVersion(0).withNewSchema().withNewOpenAPIV3Schema().withTitle("dummy").withType("object").addToRequired("spec").addToProperties("spec", new JSONSchemaPropsBuilder().withType("object").addToProperties("foo", new JSONSchemaPropsBuilder().withType("string").build()).addToProperties("bar", new JSONSchemaPropsBuilder().withType("string").build()).build()).endOpenAPIV3Schema().endSchema().endVersion().endSpec().build();
client.apiextensions().v1().customResourceDefinitions().create(dummyCRD);
System.out.println("Created CRD " + dummyCRD.getMetadata().getName());
}
// wait a beat for the endpoints to be ready
Thread.sleep(5000);
// lets create a client for the CRD
NonNamespaceOperation<Dummy, DummyList, Resource<Dummy>> dummyClient = client.resources(Dummy.class, DummyList.class);
if (resourceNamespaced) {
dummyClient = ((MixedOperation<Dummy, DummyList, Resource<Dummy>>) dummyClient).inNamespace(namespace);
}
CustomResourceList<Dummy> dummyList = dummyClient.list();
List<Dummy> items = dummyList.getItems();
System.out.println(" found " + items.size() + " dummies");
for (Dummy item : items) {
System.out.println(" " + item);
}
Dummy dummy = new Dummy();
ObjectMeta metadata = new ObjectMeta();
metadata.setName("foo");
dummy.setMetadata(metadata);
DummySpec dummySpec = new DummySpec();
Date now = new Date();
dummySpec.setBar("beer: " + now);
dummySpec.setFoo("cheese: " + now);
dummy.setSpec(dummySpec);
Dummy created = dummyClient.createOrReplace(dummy);
System.out.println("Upserted " + dummy);
created.getSpec().setBar("otherBar");
dummyClient.createOrReplace(created);
System.out.println("Watching for changes to Dummies");
dummyClient.withResourceVersion(created.getMetadata().getResourceVersion()).watch(new Watcher<Dummy>() {
@Override
public void eventReceived(Action action, Dummy resource) {
System.out.println("==> " + action + " for " + resource);
if (resource.getSpec() == null) {
logger.error("No Spec for resource {}", resource);
}
}
@Override
public void onClose(WatcherException cause) {
}
});
System.in.read();
} catch (KubernetesClientException e) {
logger.error(e.getMessage(), e);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
use of io.fabric8.kubernetes.client.Watcher.Action in project kubernetes-client by fabric8io.
the class PodWatchEquivalent method main.
public static void main(String[] args) {
String namespace = "default";
// Latch for Watch termination
final CountDownLatch isWatchClosed = new CountDownLatch(1);
try (final KubernetesClient k8s = new KubernetesClientBuilder().build()) {
k8s.pods().inNamespace(namespace).watch(new Watcher<Pod>() {
@Override
public void eventReceived(Action action, Pod pod) {
logger.info("{} {}", action.name(), pod.getMetadata().getName());
switch(action) {
case ADDED:
logger.info("{} got added", pod.getMetadata().getName());
break;
case DELETED:
logger.info("{} got deleted", pod.getMetadata().getName());
break;
case MODIFIED:
logger.info("{} got modified", pod.getMetadata().getName());
break;
default:
logger.error("Unrecognized event: {}", action.name());
}
}
@Override
public void onClose(WatcherException e) {
logger.info("Closed");
isWatchClosed.countDown();
}
});
// Wait till watch gets closed
isWatchClosed.await();
} catch (InterruptedException interruptedException) {
logger.warn("Interrupted while waiting for the watch to close: {}", interruptedException.getMessage());
Thread.currentThread().interrupt();
}
}
Aggregations