All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hotels.road.loadingbay.lander.kubernetes.PodWatcher Maven / Gradle / Ivy

/**
 * Copyright (C) 2016-2019 Expedia Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hotels.road.loadingbay.lander.kubernetes;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;

import io.fabric8.kubernetes.api.model.ContainerState;
import io.fabric8.kubernetes.api.model.ContainerStateTerminated;
import io.fabric8.kubernetes.api.model.ContainerStatus;
import io.fabric8.kubernetes.api.model.DoneablePod;
import io.fabric8.kubernetes.api.model.Pod;
import io.fabric8.kubernetes.api.model.PodStatus;
import io.fabric8.kubernetes.client.KubernetesClientException;
import io.fabric8.kubernetes.client.Watch;
import io.fabric8.kubernetes.client.Watcher;
import io.fabric8.kubernetes.client.dsl.PodResource;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class PodWatcher implements Supplier>, Watcher {
  private final PodResource resource;
  private final String podName;
  private final Watch watch;
  private final CompletableFuture exitCodeFuture;

  public PodWatcher(PodResource resource, String podName) {
    this.resource = resource;
    this.podName = podName;
    if (resource.get() == null) {
      throw new RuntimeException(String.format("pod %s does not exist.", podName));
    }
    watch = resource.watch(this);
    exitCodeFuture = new CompletableFuture() {
      @Override
      public boolean cancel(boolean mayInterruptIfRunning) {
        resource.delete();
        return super.cancel(mayInterruptIfRunning);
      }
    };
  }

  @Override
  public void onClose(KubernetesClientException cause) {
    if (!exitCodeFuture.isDone()) {
      if (cause == null) {
        exitCodeFuture
            .completeExceptionally(new IllegalStateException("Watcher closed normally without completing the future."));
      } else {
        exitCodeFuture.completeExceptionally(cause);
      }
    }
  }

  @Override
  public CompletableFuture get() {
    return exitCodeFuture;
  }

  @Override
  public void eventReceived(io.fabric8.kubernetes.client.Watcher.Action action, Pod pod) {
    log.info("Event received for pod: {}, action: {}", podName, action);
    PodStatus status = pod.getStatus();
    List containerStatuses = status.getContainerStatuses();
    if (!containerStatuses.isEmpty()) {
      ContainerStatus containerStatus = containerStatuses.get(0);
      ContainerState state = containerStatus.getState();
      ContainerStateTerminated terminated = state.getTerminated();
      if (terminated != null) {
        Integer exitCode = terminated.getExitCode();
        log.info("Container exit code for pod {}: {}", podName, exitCode);
        if (exitCode == 0) {
          exitCodeFuture.complete(0);
        } else {
          exitCodeFuture.completeExceptionally(new RuntimeException("Completed with non zero exit code: " + exitCode));
        }
        resource.delete();
        watch.close();
      } else {
        log.warn("ContainerStateTerminated was null for pod: {}, action {}", podName, action);
      }
    } else {
      log.warn("ContainerStatus list was empty for pod: {}, action {}", podName, action);
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy