io.fabric8.kubernetes.assertions.support.PodWatcher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kubernetes-assertions
Show all versions of kubernetes-assertions
This library provides a bunch of helpful assertj assertions for working with the kubernetes-api.
The newest version!
package io.fabric8.kubernetes.assertions.support;
import io.fabric8.kubernetes.api.KubernetesHelper;
import io.fabric8.kubernetes.api.model.Container;
import io.fabric8.kubernetes.api.model.Pod;
import io.fabric8.kubernetes.api.model.PodSpec;
import io.fabric8.kubernetes.assertions.PodSelectionAssert;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClientException;
import io.fabric8.kubernetes.client.Watcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static io.fabric8.kubernetes.api.KubernetesHelper.getName;
import static io.fabric8.kubernetes.assertions.support.LogHelpers.getRestartCount;
import static org.assertj.core.api.Assertions.fail;
import static org.fusesource.jansi.Ansi.Color.GREEN;
import static org.fusesource.jansi.Ansi.ansi;
/**
*
*/
public class PodWatcher
implements Watcher, Closeable
{
private static final transient Logger LOG = LoggerFactory.getLogger(PodWatcher.class);
private final PodSelectionAssert podSelectionAssert;
private final long readyTimeoutMS;
private final long readyPeriodMS;
private Map podAsserts = new ConcurrentHashMap<>();
private Map podLogWatchers = new ConcurrentHashMap<>();
private CountDownLatch podReady = new CountDownLatch(1);
private CountDownLatch podReadyForEntireDuration = new CountDownLatch(1);
private File basedir;
public PodWatcher(PodSelectionAssert podSelectionAssert, long readyTimeoutMS, long readyPeriodMS)
{
this.podSelectionAssert = podSelectionAssert;
this.readyTimeoutMS = readyTimeoutMS;
this.readyPeriodMS = readyPeriodMS;
}
public KubernetesClient getClient()
{
return podSelectionAssert.getClient();
}
public String getDescription()
{
return podSelectionAssert.getDescription();
}
public long getReadyTimeoutMS()
{
return readyTimeoutMS;
}
public long getReadyPeriodMS()
{
return readyPeriodMS;
}
/**
* Lets load the current pods as we don't get watch events for current pods
*/
public void loadCurrentPods()
{
List pods = podSelectionAssert.getPods();
for (Pod pod : pods) {
String name = getName(pod);
if (!podAsserts.containsKey(name)) {
onPod(name, pod);
}
}
}
@Override
public void eventReceived(Action action, Pod pod)
{
String name = getName(pod);
if (action.equals(Action.ERROR)) {
LOG.warn("Got error for pod " + name);
}
else if (action.equals(Action.DELETED)) {
closeCloser(name, this.podAsserts);
closeCloser(name, this.podLogWatchers);
}
else {
onPod(name, pod);
}
}
protected void onPod(String name, Pod pod)
{
PodAsserter asserter = podAsserts.get(name);
if (asserter == null) {
asserter = new PodAsserter(this, name, pod);
podAsserts.put(name, asserter);
}
else {
asserter.updated(pod);
}
int restartCount = getRestartCount(pod);
PodSpec spec = pod.getSpec();
if (spec != null) {
if (KubernetesHelper.isPodRunning(pod)) {
List containers = spec.getContainers();
for (Container container : containers) {
File logFileName = LogHelpers.getLogFileName(getBaseDir(), name, container, restartCount);
String key = logFileName.getName();
PodLogWatcher logWatcher = podLogWatchers.get(key);
if (logWatcher == null) {
try {
String containerName = container.getName();
logWatcher = new PodLogWatcher(this, name, pod, containerName, logFileName);
podLogWatchers.put(key, logWatcher);
LOG.info("Watching pod " + name + " container " + containerName + " log at file: " + logFileName.getAbsolutePath());
}
catch (Exception e) {
LOG.warn("Failed to create PodLogWatcher: " + e, e);
}
}
}
}
}
File yamlFile = new File(getBaseDir(), "target/test-pod-status/" + name + ".yml");
yamlFile.getParentFile().mkdirs();
try {
KubernetesHelper.saveYaml(pod, yamlFile);
}
catch (IOException e) {
LOG.warn("Failed to write " + yamlFile + ". " + e, e);
}
}
public File getBaseDir()
{
if (basedir == null) {
basedir = new File(System.getProperty("basedir", "."));
}
return basedir;
}
public void setBasedir(File basedir)
{
this.basedir = basedir;
}
@Override
public void onClose(KubernetesClientException e)
{
LOG.info("onClose: " + e);
}
public void close()
{
closeAllClosers(podAsserts);
closeAllClosers(podLogWatchers);
}
protected void closeAllClosers(Map closers)
{
while (!closers.isEmpty()) {
Set keys = closers.keySet();
for (String key : keys) {
closeCloser(key, closers);
}
}
}
private void closeCloser(String name, Map closers)
{
Closeable closer = closers.remove(name);
if (closer != null) {
try {
closer.close();
}
catch (Exception e) {
LOG.warn("Failed to close " + closer + ". " + e, e);
}
}
}
public void waitForPodReady()
{
boolean ready = false;
try {
ready = podReady.await(readyTimeoutMS, TimeUnit.MILLISECONDS);
}
catch (InterruptedException e) {
LOG.warn("Interupted waiting for podReady: " + e);
ready = podReady.getCount() == 0L;
}
if (!ready) {
fail(podSelectionAssert.getDescription() + " did not have a pod become Ready within " + readyTimeoutMS + " millis");
}
try {
ready = podReadyForEntireDuration.await(readyPeriodMS * 2, TimeUnit.MILLISECONDS);
}
catch (InterruptedException e) {
LOG.warn("Interupted waiting for podReadyForEntireDuration: " + e);
ready = podReadyForEntireDuration.getCount() == 0L;
}
if (!ready) {
fail(podSelectionAssert.getDescription() + " did not have a pod Ready for a duration of " + readyPeriodMS + " millis");
}
}
public void podIsReadyForEntireDuration(String name, Pod pod)
{
String message = "Pod " + name + " has been Ready now for " + getReadyPeriodMS() + " millis!";
LOG.info(ansi().fg(GREEN).a(message).reset().toString());
podReadyForEntireDuration.countDown();
}
public void podIsReady(String name, Pod pod)
{
if (podReady.getCount() > 0) {
String message = "Pod " + name + " is Ready!";
LOG.info(ansi().fg(GREEN).a(message).reset().toString());
podReady.countDown();
}
}
}