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

io.kubernetes.client.informer.SharedInformerFactory Maven / Gradle / Ivy

There is a newer version: 22.0.0
Show newest version
/*
Copyright 2020 The Kubernetes Authors.
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 io.kubernetes.client.informer;

import com.google.gson.reflect.TypeToken;
import io.kubernetes.client.common.KubernetesListObject;
import io.kubernetes.client.common.KubernetesObject;
import io.kubernetes.client.informer.cache.Cache;
import io.kubernetes.client.informer.impl.DefaultSharedIndexInformer;
import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.Configuration;
import io.kubernetes.client.util.CallGenerator;
import io.kubernetes.client.util.CallGeneratorParams;
import io.kubernetes.client.util.Namespaces;
import io.kubernetes.client.util.Watch;
import io.kubernetes.client.util.Watchable;
import io.kubernetes.client.util.generic.GenericKubernetesApi;
import io.kubernetes.client.util.generic.options.ListOptions;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.function.BiConsumer;
import okhttp3.Call;
import org.apache.commons.collections4.MapUtils;

/** SharedInformerFactory class constructs and caches informers for api types. */
public class SharedInformerFactory {

  protected Map informers;

  private Map startedInformers;

  private ExecutorService informerExecutor;

  private ApiClient apiClient;

  /** Constructor w/ default thread pool. */
  /** DEPRECATE: In favor of explicit apiClient constructor to avoid misguiding */
  @Deprecated
  public SharedInformerFactory() {
    this(Configuration.getDefaultApiClient().setReadTimeout(0), Executors.newCachedThreadPool());
  }

  /** Constructor w/ api client specified and default thread pool. */
  public SharedInformerFactory(ApiClient apiClient) {
    this(apiClient, Executors.newCachedThreadPool());
  }

  /**
   * Constructor w/ thread pool specified.
   *
   * @param threadPool specified thread pool
   */
  public SharedInformerFactory(ExecutorService threadPool) {
    this(Configuration.getDefaultApiClient().setReadTimeout(0), threadPool);
  }

  /**
   * Constructor w/ api client and thread pool specified.
   *
   * @param client specific api client
   * @param threadPool specified thread pool
   */
  public SharedInformerFactory(ApiClient client, ExecutorService threadPool) {
    if (client.getReadTimeout() != 0) {
      throw new IllegalArgumentException("read timeout of ApiClient must be zero");
    }

    apiClient = client;
    informerExecutor = threadPool;
    informers = new HashMap<>();
    startedInformers = new HashMap<>();
  }

  /**
   * Shared index informer for shared index informer.
   *
   * @param  the type parameter
   * @param  the type parameter
   * @param callGenerator the call generator
   * @param apiTypeClass the api type class
   * @param apiListTypeClass the api list type class
   * @return the shared index informer
   */
  public synchronized 
      SharedIndexInformer sharedIndexInformerFor(
          CallGenerator callGenerator,
          Class apiTypeClass,
          Class apiListTypeClass) {
    return sharedIndexInformerFor(callGenerator, apiTypeClass, apiListTypeClass, 0);
  }

  /**
   * Constructs and returns a shared index informer w/ resync period specified. But the informer
   * cache will not be overwritten i.e. only the first registered informer will be kept.
   *
   * @param  the type parameter
   * @param  the type parameter
   * @param callGenerator the call generator
   * @param apiTypeClass the api type class
   * @param apiListTypeClass the api list type class
   * @param resyncPeriodInMillis the resync period in millis
   * @return the shared index informer
   */
  public synchronized 
      SharedIndexInformer sharedIndexInformerFor(
          CallGenerator callGenerator,
          Class apiTypeClass,
          Class apiListTypeClass,
          long resyncPeriodInMillis) {
    return sharedIndexInformerFor(
        callGenerator, apiTypeClass, apiListTypeClass, resyncPeriodInMillis, null);
  }

  /**
   * Shared index informer for shared index informer.
   *
   * @param  the type parameter
   * @param  the type parameter
   * @param callGenerator the call generator
   * @param apiTypeClass the api type class
   * @param apiListTypeClass the api list type class
   * @param exceptionHandler the exception Handler
   * @return the shared index informer
   */
  public synchronized 
      SharedIndexInformer sharedIndexInformerFor(
          CallGenerator callGenerator,
          Class apiTypeClass,
          Class apiListTypeClass,
          long resyncPeriodInMillis,
          BiConsumer, Throwable> exceptionHandler) {
    ListerWatcher listerWatcher =
        listerWatcherFor(callGenerator, apiTypeClass, apiListTypeClass);
    return sharedIndexInformerFor(
        listerWatcher, apiTypeClass, resyncPeriodInMillis, exceptionHandler);
  }

  /**
   * Constructs and returns a shared index informer by specifying lister-watcher. But the informer
   * cache will not be overwritten on multiple call w/ the the same apiTypeClass i.e. only the first
   * registered informer will be kept.
   *
   * @param  the type parameter
   * @param  the type parameter
   * @param listerWatcher the lister watcher
   * @param apiTypeClass the api type class
   * @param resyncPeriodInMillis the resync period in millis
   * @return the shared index informer
   */
  public synchronized 
      SharedIndexInformer sharedIndexInformerFor(
          ListerWatcher listerWatcher,
          Class apiTypeClass,
          long resyncPeriodInMillis) {
    return sharedIndexInformerFor(listerWatcher, apiTypeClass, resyncPeriodInMillis, null);
  }

  public synchronized 
      SharedIndexInformer sharedIndexInformerFor(
          ListerWatcher listerWatcher,
          Class apiTypeClass,
          long resyncPeriodInMillis,
          BiConsumer, Throwable> exceptionHandler) {

    SharedIndexInformer informer =
        new DefaultSharedIndexInformer<>(
            apiTypeClass, listerWatcher, resyncPeriodInMillis, new Cache<>(), exceptionHandler);
    this.informers.putIfAbsent(TypeToken.get(apiTypeClass).getType(), informer);
    return informer;
  }

  /**
   * Constructs and returns a shared index informer by specifying a generic api instance. But the
   * informer cache will not be overwritten on multiple call w/ the the same apiTypeClass i.e. only
   * the first registered informer will be kept.
   *
   * @param  the type parameter
   * @param  the type parameter
   * @param genericKubernetesApi the generic kubernetes api
   * @param apiTypeClass the api type class
   * @param resyncPeriodInMillis the resync period in millis
   * @return the shared index informer
   */
  public synchronized 
      SharedIndexInformer sharedIndexInformerFor(
          GenericKubernetesApi genericKubernetesApi,
          Class apiTypeClass,
          long resyncPeriodInMillis) {
    return sharedIndexInformerFor(
        genericKubernetesApi, apiTypeClass, resyncPeriodInMillis, Namespaces.NAMESPACE_ALL);
  }

  /**
   * Working the same as {@link SharedInformerFactory#sharedIndexInformerFor} above.
   *
   * 

Constructs and returns a shared index informer for a specific namespace. * * @param the type parameter * @param the type parameter * @param genericKubernetesApi the generic kubernetes api * @param apiTypeClass the api type class * @param resyncPeriodInMillis the resync period in millis * @param namespace the target namespace * @return the shared index informer */ public synchronized SharedIndexInformer sharedIndexInformerFor( GenericKubernetesApi genericKubernetesApi, Class apiTypeClass, long resyncPeriodInMillis, String namespace) { return sharedIndexInformerFor( genericKubernetesApi, apiTypeClass, resyncPeriodInMillis, namespace, null); } /** * Working the same as {@link SharedInformerFactory#sharedIndexInformerFor} above. * *

Constructs and returns a shared index informer for a specific namespace. * * @param the type parameter * @param the type parameter * @param genericKubernetesApi the generic kubernetes api * @param apiTypeClass the api type class * @param resyncPeriodInMillis the resync period in millis * @param namespace the target namespace * @param exceptionHandler the exception Handler * @return the shared index informer */ public synchronized SharedIndexInformer sharedIndexInformerFor( GenericKubernetesApi genericKubernetesApi, Class apiTypeClass, long resyncPeriodInMillis, String namespace, BiConsumer, Throwable> exceptionHandler) { ListerWatcher listerWatcher = listerWatcherFor(genericKubernetesApi, namespace); return sharedIndexInformerFor( listerWatcher, apiTypeClass, resyncPeriodInMillis, exceptionHandler); } private ListerWatcher listerWatcherFor( CallGenerator callGenerator, Class apiTypeClass, Class apiListTypeClass) { if (apiClient.getReadTimeout() > 0) { // set read timeout zero to ensure client doesn't time out apiClient.setReadTimeout(0); } return new ListerWatcher() { @Override public ApiListType list(CallGeneratorParams params) throws ApiException { Call call = callGenerator.generate(params); return (ApiListType) apiClient.execute(call, apiListTypeClass).getData(); } @Override public Watch watch(CallGeneratorParams params) throws ApiException { Call call = callGenerator.generate(params); // bind call with private http client to make sure read timeout is zero. call = apiClient.getHttpClient().newCall(call.request()); return Watch.createWatch( apiClient, call, TypeToken.getParameterized(Watch.Response.class, apiTypeClass).getType()); } }; } private ListerWatcher listerWatcherFor( GenericKubernetesApi genericKubernetesApi, String namespace) { if (apiClient.getReadTimeout() > 0) { // set read timeout zero to ensure client doesn't time out apiClient.setReadTimeout(0); } // TODO: it seems read timeout is determined by genericKubernetesApi instead of above apiClient. return new ListerWatcher() { public ApiListType list(CallGeneratorParams params) throws ApiException { if (Namespaces.NAMESPACE_ALL.equals(namespace)) { return genericKubernetesApi .list( new ListOptions() { { setResourceVersion(params.resourceVersion); setTimeoutSeconds(params.timeoutSeconds); } }) .throwsApiException() .getObject(); } else { return genericKubernetesApi .list( namespace, new ListOptions() { { setResourceVersion(params.resourceVersion); setTimeoutSeconds(params.timeoutSeconds); } }) .throwsApiException() .getObject(); } } public Watchable watch(CallGeneratorParams params) throws ApiException { if (Namespaces.NAMESPACE_ALL.equals(namespace)) { return genericKubernetesApi.watch( new ListOptions() { { setResourceVersion(params.resourceVersion); setTimeoutSeconds(params.timeoutSeconds); } }); } else { return genericKubernetesApi.watch( namespace, new ListOptions() { { setResourceVersion(params.resourceVersion); setTimeoutSeconds(params.timeoutSeconds); } }); } } }; } /** * Gets existing shared index informer, return null if the requesting informer is never * constructed. * * @param the type parameter * @param apiTypeClass the api type class * @return the existing shared index informer */ public synchronized SharedIndexInformer getExistingSharedIndexInformer(Class apiTypeClass) { return this.informers.get(TypeToken.get(apiTypeClass).getType()); } /** Start all registered informers. */ public synchronized void startAllRegisteredInformers() { if (MapUtils.isEmpty(informers)) { return; } informers.forEach( (informerType, informer) -> startedInformers.computeIfAbsent( informerType, key -> informerExecutor.submit((Runnable) informer::run))); } /** Stop all registered informers and shut down the thread pool. */ public synchronized void stopAllRegisteredInformers() { stopAllRegisteredInformers(true); } /** * Stop all registered informers. * * @param shutdownThreadPool whether or not to shut down the thread pool. */ public synchronized void stopAllRegisteredInformers(boolean shutdownThreadPool) { if (MapUtils.isEmpty(informers)) { return; } informers.forEach( (informerType, informer) -> { if (startedInformers.remove(informerType) != null) { informer.stop(); } }); if (shutdownThreadPool) { informerExecutor.shutdown(); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy