cloud-8.x-2.0-beta1/modules/cloud_service_providers/k8s/src/Service/K8sService.php

modules/cloud_service_providers/k8s/src/Service/K8sService.php
<?php

namespace Drupal\k8s\Service;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\core\Field\FieldTypePluginManagerInterface;
use Drupal\Core\Lock\LockBackendInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Messenger\Messenger;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\Batch\BatchBuilder;

use Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface;
use Drupal\cloud\Traits\EntityTrait;

use Drupal\k8s\Service\K8sClientExtension\K8sClient;
use Drupal\k8s\Service\K8sClientExtension\Models\K8sLimitRange;

use Maclof\Kubernetes\Models\NamespaceModel;
use Maclof\Kubernetes\Models\Pod;
use Maclof\Kubernetes\Models\Deployment;
use Maclof\Kubernetes\Models\Service;
use Maclof\Kubernetes\Models\CronJob;
use Maclof\Kubernetes\Models\Job;
use Maclof\Kubernetes\Models\QuotaModel;
use Maclof\Kubernetes\Models\ReplicaSet;
use Maclof\Kubernetes\Models\Secret;
use Maclof\Kubernetes\Models\ConfigMap;
use Maclof\Kubernetes\Models\NetworkPolicy;

/**
 * K8sService service interacts with the K8s API.
 */
class K8sService implements K8sServiceInterface {

  use StringTranslationTrait;
  use EntityTrait;

  /**
   * The Messenger service.
   *
   * @var \Drupal\Core\Messenger\Messenger
   */
  protected $messenger;

  /**
   * Drupal\Core\Entity\EntityTypeManagerInterface definition.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * Cloud context string.
   *
   * @var string
   */
  protected $cloudContext;

  /**
   * A logger instance.
   *
   * @var \Psr\Log\LoggerInterface
   */
  protected $logger;

  /**
   * The config factory.
   *
   * Subclasses should use the self::config() method, which may be overridden to
   * address specific needs when loading config, rather than this property
   * directly. See \Drupal\Core\Form\ConfigFormBase::config() for an example of
   * this.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * The cloud service provider plugin manager (CloudConfigPluginManager).
   *
   * @var \Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface
   */
  protected $cloudConfigPluginManager;

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $currentUser;

  /**
   * Field type plugin manager.
   *
   * @var \Drupal\core\Field\FieldTypePluginManagerInterface
   */
  protected $fieldTypePluginManager;

  /**
   * Entity field manager interface.
   *
   * @var \Drupal\Core\Entity\EntityFieldManagerInterface
   */
  protected $entityFieldManager;

  /**
   * The lock interface.
   *
   * @var \Drupal\Core\Lock\LockBackendInterface
   */
  protected $lock;

  /**
   * Constructs a new K8sService object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   An entity type manager instance.
   * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger_factory
   *   A logger instance.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   A configuration factory.
   * @param \Drupal\Core\Messenger\Messenger $messenger
   *   The messenger service.
   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
   *   The string translation service.
   * @param \Drupal\Core\Session\AccountInterface $current_user
   *   The current user.
   * @param \Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface $cloud_config_plugin_manager
   *   The cloud service provider plugin manager.
   * @param \Drupal\core\Field\FieldTypePluginManagerInterface $field_type_plugin_manager
   *   The field type plugin manager.
   * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
   *   The entity field manager.
   * @param \Drupal\Core\Lock\LockBackendInterface $lock
   *   The lock interface.
   */
  public function __construct(
    EntityTypeManagerInterface $entity_type_manager,
    LoggerChannelFactoryInterface $logger_factory,
    ConfigFactoryInterface $config_factory,
    Messenger $messenger,
    TranslationInterface $string_translation,
    AccountInterface $current_user,
    CloudConfigPluginManagerInterface $cloud_config_plugin_manager,
    FieldTypePluginManagerInterface $field_type_plugin_manager,
    EntityFieldManagerInterface $entity_field_manager,
    LockBackendInterface $lock
  ) {
    // Setup the entity type manager for querying entities.
    $this->entityTypeManager = $entity_type_manager;

    // Setup the logger.
    $this->logger = $logger_factory->get('k8s_service');

    // Setup the configuration factory.
    $this->configFactory = $config_factory;

    // Setup the messenger.
    $this->messenger = $messenger;

    // Setup the $this->t()
    $this->stringTranslation = $string_translation;

    $this->currentUser = $current_user;
    $this->cloudConfigPluginManager = $cloud_config_plugin_manager;
    $this->fieldTypePluginManager = $field_type_plugin_manager;
    $this->entityFieldManager = $entity_field_manager;
    $this->lock = $lock;
  }

  /**
   * {@inheritdoc}
   */
  public function setCloudContext($cloud_context) {
    $this->cloudContext = $cloud_context;
    $this->cloudConfigPluginManager->setCloudContext($cloud_context);
  }

  /**
   * Load and return an Client.
   *
   * @param string $namespace
   *   The namespace.
   */
  protected function getClient($namespace = '') {
    $client = NULL;
    $credentials = $this->cloudConfigPluginManager->loadCredentials();
    try {
      $client = new K8sClient(
        [
          'master'   => $credentials['master'],
          'token' => $credentials['token'],
          'verify' => FALSE,
          'namespace' => $namespace,
        ],
        NULL,
        $this->messenger,
        $this->stringTranslation
      );
    }
    catch (\Exception $e) {
      $this->logger->error($e->getMessage());
    }

    return $client;
  }

  /**
   * {@inheritdoc}
   */
  public function getPods(array $params = []) {
    return $this->getClient()
      ->pods()
      ->setFieldSelector($params)
      ->find()
      ->toArray();
  }

  /**
   * {@inheritdoc}
   */
  public function createPod($namespace, array $params = []) {
    return $this->getClient($namespace)
      ->pods()
      ->create(new Pod($params));
  }

  /**
   * {@inheritdoc}
   */
  public function updatePod($namespace, array $params = []) {
    // Remove empty properties.
    $params['spec'] = array_filter($params['spec']);

    // Remove status, which should not be modified.
    unset($params['status']);

    return $this->getClient($namespace)
      ->pods()
      ->update(new Pod($params));
  }

  /**
   * {@inheritdoc}
   */
  public function deletePod($namespace, array $params = []) {
    return $this->getClient($namespace)
      ->pods()
      ->delete(new Pod($params));
  }

  /**
   * {@inheritdoc}
   */
  public function getPodLogs($namespace, array $params = []) {
    return $this->getClient($namespace)
      ->pods()
      ->logs(new Pod($params), [
        'pretty' => TRUE,
      ]);
  }

  /**
   * {@inheritdoc}
   */
  public function getNodes(array $params = []) {
    return $this->getClient()
      ->nodes()
      ->setFieldSelector($params)
      ->find()
      ->toArray();
  }

  /**
   * {@inheritdoc}
   */
  public function getNamespaces(array $params = []) {
    return $this->getClient()
      ->namespaces()
      ->setFieldSelector($params)
      ->find()
      ->toArray();
  }

  /**
   * {@inheritdoc}
   */
  public function createNamespace(array $params = []) {
    return $this->getClient()
      ->namespaces()
      ->create(new NamespaceModel($params));
  }

  /**
   * {@inheritdoc}
   */
  public function updateNamespace(array $params = []) {
    return $this->getClient()
      ->namespaces()
      ->update(new NamespaceModel($params));
  }

  /**
   * {@inheritdoc}
   */
  public function deleteNamespace(array $params = []) {
    return $this->getClient()
      ->namespaces()
      ->delete(new NamespaceModel($params));
  }

  /**
   * {@inheritdoc}
   */
  public function getMetricsPods(array $params = []) {
    return $this->getClient()
      ->metricsPods()
      ->setFieldSelector($params)
      ->find()
      ->toArray();
  }

  /**
   * {@inheritdoc}
   */
  public function getMetricsNodes(array $params = []) {
    return $this->getClient()
      ->metricsNodes()
      ->setFieldSelector($params)
      ->find()
      ->toArray();
  }

  /**
   * {@inheritdoc}
   */
  public function updatePods(array $params = [], $clear = TRUE) {
    return $this->updateEntities(
      'k8s_pod',
      'Pod',
      'getPods',
      'updatePod',
      $params,
      $clear,
      'namespace'
    );
  }

  /**
   * {@inheritdoc}
   */
  public function updatePodsWithoutBatch(array $params = [], $clear = TRUE) {
    return $this->updateEntities(
      'k8s_pod',
      'Pod',
      'getPods',
      'updatePod',
      $params,
      $clear,
      'namespace',
      FALSE
    );
  }

  /**
   * {@inheritdoc}
   */
  public function updateNodes(array $params = [], $clear = TRUE) {
    return $this->updateEntities(
      'k8s_node',
      'Node',
      'getNodes',
      'updateNode',
      $params,
      $clear
    );
  }

  /**
   * {@inheritdoc}
   */
  public function updateNodesWithoutBatch(array $params = [], $clear = TRUE) {
    return $this->updateEntities(
      'k8s_node',
      'Node',
      'getNodes',
      'updateNode',
      $params,
      $clear,
      NULL,
      FALSE
    );
  }

  /**
   * {@inheritdoc}
   */
  public function updateNamespaces(array $params = [], $clear = TRUE) {
    return $this->updateEntities(
      'k8s_namespace',
      'Namespace',
      'getNamespaces',
      'updateNamespace',
      $params,
      $clear
    );
  }

  /**
   * {@inheritdoc}
   */
  public function updateNamespacesWithoutBatch(array $params = [], $clear = TRUE) {
    return $this->updateEntities(
      'k8s_namespace',
      'Namespace',
      'getNamespaces',
      'updateNamespace',
      $params,
      $clear,
      NULL,
      FALSE
    );
  }

  /**
   * {@inheritdoc}
   */
  public function updateDeployments(array $params = [], $clear = TRUE) {
    return $this->updateEntities(
      'k8s_deployment',
      'Deployment',
      'getDeployments',
      'updateDeployment',
      $params,
      $clear,
      'namespace'
    );
  }

  /**
   * {@inheritdoc}
   */
  public function updateReplicaSets(array $params = [], $clear = TRUE) {
    return $this->updateEntities(
      'k8s_replica_set',
      'ReplicaSet',
      'getReplicaSets',
      'updateReplicaSet',
      $params,
      $clear,
      'namespace'
    );
  }

  /**
   * {@inheritdoc}
   */
  public function updateServices(array $params = [], $clear = TRUE) {
    return $this->updateEntities(
      'k8s_service',
      'Service',
      'getServices',
      'updateService',
      $params,
      $clear,
      'namespace'
    );
  }

  /**
   * {@inheritdoc}
   */
  public function updateCronJobs(array $params = [], $clear = TRUE) {
    return $this->updateEntities(
      'k8s_cron_job',
      'CronJob',
      'getCronJobs',
      'updateCronJob',
      $params,
      $clear,
      'namespace'
    );
  }

  /**
   * {@inheritdoc}
   */
  public function updateJobs(array $params = [], $clear = TRUE) {
    return $this->updateEntities(
      'k8s_job',
      'Job',
      'getJobs',
      'updateJob',
      $params,
      $clear,
      'namespace'
    );
  }

  /**
   * {@inheritdoc}
   */
  public function updateResourceQuotas(array $params = [], $clear = TRUE) {
    return $this->updateEntities(
      'k8s_resource_quota',
      'Resource Quota',
      'getResourceQuotas',
      'updateResourceQuota',
      $params,
      $clear,
      'namespace'
    );
  }

  /**
   * {@inheritdoc}
   */
  public function updateLimitRanges(array $params = [], $clear = TRUE) {
    return $this->updateEntities(
      'k8s_limit_range',
      'Limit Range',
      'getLimitRanges',
      'updateLimitRange',
      $params,
      $clear,
      'namespace'
    );
  }

  /**
   * {@inheritdoc}
   */
  public function updateSecrets(array $params = [], $clear = TRUE) {
    return $this->updateEntities(
      'k8s_secret',
      'Secret',
      'getSecrets',
      'updateSecret',
      $params,
      $clear,
      'namespace'
    );
  }

  /**
   * {@inheritdoc}
   */
  public function updateConfigMaps(array $params = [], $clear = TRUE) {
    return $this->updateEntities(
      'k8s_config_map',
      'ConfigMap',
      'getConfigMaps',
      'updateConfigMap',
      $params,
      $clear,
      'namespace'
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getDeployments(array $params = []) {
    return $this->getClient()
      ->deployments()
      ->setFieldSelector($params)
      ->find()
      ->toArray();
  }

  /**
   * {@inheritdoc}
   */
  public function createDeployment($namespace, array $params = []) {
    return $this->getClient($namespace)
      ->deployments()
      ->create(new Deployment($params));
  }

  /**
   * {@inheritdoc}
   */
  public function updateDeployment($namespace, array $params = []) {
    // Remove empty properties.
    $params['spec'] = array_filter($params['spec']);

    // Remove status, which should not be modified.
    unset($params['status']);

    return $this->getClient($namespace)
      ->deployments()
      ->update(new Deployment($params));
  }

  /**
   * {@inheritdoc}
   */
  public function deleteDeployment($namespace, array $params = []) {
    return $this->getClient($namespace)
      ->deployments()
      ->delete(new Deployment($params));
  }

  /**
   * {@inheritdoc}
   */
  public function getReplicaSets(array $params = []) {
    return $this->getClient()
      ->replicaSets()
      ->setFieldSelector($params)
      ->find()
      ->toArray();
  }

  /**
   * {@inheritdoc}
   */
  public function createReplicaSet($namespace, array $params = []) {
    return $this->getClient($namespace)
      ->replicaSets()
      ->create(new ReplicaSet($params));
  }

  /**
   * {@inheritdoc}
   */
  public function updateReplicaSet($namespace, array $params = []) {
    // Remove empty properties.
    $params['spec'] = array_filter($params['spec']);

    // Remove status, which should not be modified.
    unset($params['status']);

    return $this->getClient($namespace)
      ->replicaSets()
      ->update(new ReplicaSet($params));
  }

  /**
   * {@inheritdoc}
   */
  public function deleteReplicaSet($namespace, array $params = []) {
    return $this->getClient($namespace)
      ->replicaSets()
      ->delete(new ReplicaSet($params));
  }

  /**
   * {@inheritdoc}
   */
  public function getServices(array $params = []) {
    return $this->getClient()
      ->services()
      ->setFieldSelector($params)
      ->find()
      ->toArray();
  }

  /**
   * {@inheritdoc}
   */
  public function createService($namespace, array $params = []) {
    return $this->getClient($namespace)
      ->services()
      ->create(new Service($params));
  }

  /**
   * {@inheritdoc}
   */
  public function updateService($namespace, array $params = []) {
    // Remove empty properties.
    $params['spec'] = array_filter($params['spec']);

    // Remove status, which should not be modified.
    unset($params['status']);

    return $this->getClient($namespace)
      ->services()
      ->update(new Service($params));
  }

  /**
   * {@inheritdoc}
   */
  public function deleteService($namespace, array $params = []) {
    return $this->getClient($namespace)
      ->services()
      ->delete(new Service($params));
  }

  /**
   * {@inheritdoc}
   */
  public function getCronJobs(array $params = []) {
    return $this->getClient()
      ->cronJobs()
      ->setFieldSelector($params)
      ->find()
      ->toArray();
  }

  /**
   * {@inheritdoc}
   */
  public function createCronJob($namespace, array $params = []) {
    return $this->getClient($namespace)
      ->cronJobs()
      ->create(new CronJob($params));
  }

  /**
   * {@inheritdoc}
   */
  public function updateCronJob($namespace, array $params = []) {
    // Remove empty properties.
    $params['spec'] = array_filter($params['spec']);

    // Remove status, which should not be modified.
    unset($params['status']);

    return $this->getClient($namespace)
      ->cronJobs()
      ->update(new CronJob($params));
  }

  /**
   * {@inheritdoc}
   */
  public function deleteCronJob($namespace, array $params = []) {
    return $this->getClient($namespace)
      ->cronJobs()
      ->delete(new CronJob($params));
  }

  /**
   * {@inheritdoc}
   */
  public function getJobs(array $params = []) {
    return $this->getClient()
      ->jobs()
      ->setFieldSelector($params)
      ->find()
      ->toArray();
  }

  /**
   * {@inheritdoc}
   */
  public function createJob($namespace, array $params = []) {
    return $this->getClient($namespace)
      ->jobs()
      ->create(new Job($params));
  }

  /**
   * {@inheritdoc}
   */
  public function updateJob($namespace, array $params = []) {
    // Remove empty properties.
    $params['spec'] = array_filter($params['spec']);

    // Remove status, which should not be modified.
    unset($params['status']);

    return $this->getClient($namespace)
      ->jobs()
      ->update(new Job($params));
  }

  /**
   * {@inheritdoc}
   */
  public function deleteJob($namespace, array $params = []) {
    return $this->getClient($namespace)
      ->jobs()
      ->delete(new Job($params));
  }

  /**
   * {@inheritdoc}
   */
  public function getResourceQuotas(array $params = []) {
    return $this->getClient()
      ->quotas()
      ->setFieldSelector($params)
      ->find()
      ->toArray();
  }

  /**
   * {@inheritdoc}
   */
  public function createResourceQuota($namespace, array $params = []) {
    $params['kind'] = 'ResourceQuota';
    return $this->getClient($namespace)
      ->quotas()
      ->create(new QuotaModel($params));
  }

  /**
   * {@inheritdoc}
   */
  public function updateResourceQuota($namespace, array $params = []) {
    // Remove empty properties.
    $params['spec'] = array_filter($params['spec']);

    // Remove status, which should not be modified.
    unset($params['status']);

    $params['kind'] = 'ResourceQuota';

    return $this->getClient($namespace)
      ->quotas()
      ->update(new QuotaModel($params));
  }

  /**
   * {@inheritdoc}
   */
  public function deleteResourceQuota($namespace, array $params = []) {
    $params['kind'] = 'ResourceQuota';

    return $this->getClient($namespace)
      ->quotas()
      ->delete(new QuotaModel($params));
  }

  /**
   * {@inheritdoc}
   */
  public function getLimitRanges(array $params = []) {
    return $this->getClient()
      ->limitRanges()
      ->setFieldSelector($params)
      ->find()
      ->toArray();
  }

  /**
   * {@inheritdoc}
   */
  public function createLimitRange($namespace, array $params = []) {
    $params['kind'] = 'LimitRange';
    return $this->getClient($namespace)
      ->limitRanges()
      ->create(new K8sLimitRange($params));
  }

  /**
   * {@inheritdoc}
   */
  public function updateLimitRange($namespace, array $params = []) {
    // Remove empty properties.
    $params['spec'] = array_filter($params['spec']);

    // Remove status, which should not be modified.
    unset($params['status']);

    $params['kind'] = 'LimitRange';

    return $this->getClient($namespace)
      ->limitRanges()
      ->update(new K8sLimitRange($params));
  }

  /**
   * {@inheritdoc}
   */
  public function deleteLimitRange($namespace, array $params = []) {
    $params['kind'] = 'LimitRange';

    return $this->getClient($namespace)
      ->limitRanges()
      ->delete(new K8sLimitRange($params));
  }

  /**
   * {@inheritdoc}
   */
  public function getSecrets(array $params = []) {
    return $this->getClient()
      ->secrets()
      ->setFieldSelector($params)
      ->find()
      ->toArray();
  }

  /**
   * {@inheritdoc}
   */
  public function createSecret($namespace, array $params = []) {
    $params['kind'] = 'Secret';
    return $this->getClient($namespace)
      ->secrets()
      ->create(new Secret($params));
  }

  /**
   * {@inheritdoc}
   */
  public function updateSecret($namespace, array $params = []) {
    // Remove empty properties.
    $params['spec'] = array_filter($params['spec']);

    // Remove status, which should not be modified.
    unset($params['status']);

    $params['kind'] = 'Secret';

    return $this->getClient($namespace)
      ->secrets()
      ->update(new Secret($params));
  }

  /**
   * {@inheritdoc}
   */
  public function deleteSecret($namespace, array $params = []) {
    $params['kind'] = 'Secret';

    return $this->getClient($namespace)
      ->secrets()
      ->delete(new Secret($params));
  }

  /**
   * {@inheritdoc}
   */
  public function getConfigMaps(array $params = []) {
    return $this->getClient()
      ->configMaps()
      ->setFieldSelector($params)
      ->find()
      ->toArray();
  }

  /**
   * {@inheritdoc}
   */
  public function createConfigMap($namespace, array $params = []) {
    $params['kind'] = 'ConfigMap';
    return $this->getClient($namespace)
      ->configMaps()
      ->create(new ConfigMap($params));
  }

  /**
   * {@inheritdoc}
   */
  public function updateConfigMap($namespace, array $params = []) {
    // Remove empty properties.
    $params['spec'] = array_filter($params['spec']);

    // Remove status, which should not be modified.
    unset($params['status']);

    $params['kind'] = 'ConfigMap';

    return $this->getClient($namespace)
      ->configMaps()
      ->update(new ConfigMap($params));
  }

  /**
   * {@inheritdoc}
   */
  public function deleteConfigMap($namespace, array $params = []) {
    $params['kind'] = 'ConfigMap';

    return $this->getClient($namespace)
      ->configMaps()
      ->delete(new ConfigMap($params));
  }

  /**
   * {@inheritdoc}
   */
  public function updateNetworkPolicies(array $params = [], $clear = TRUE) {
    return $this->updateEntities(
      'k8s_network_policy',
      'Network Policy',
      'getNetworkPolicies',
      'updateNetworkPolicy',
      $params,
      $clear,
      'namespace'
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getNetworkPolicies(array $params = []) {
    return $this->getClient()
      ->networkPolicies()
      ->setFieldSelector($params)
      ->find()
      ->toArray();
  }

  /**
   * {@inheritdoc}
   */
  public function createNetworkPolicy($namespace, array $params = []) {
    $params['kind'] = 'NetworkPolicy';
    return $this->getClient($namespace)
      ->networkPolicies()
      ->create(new NetworkPolicy($params));
  }

  /**
   * {@inheritdoc}
   */
  public function updateNetworkPolicy($namespace, array $params = []) {
    // Remove empty properties.
    $params['spec'] = array_filter($params['spec']);

    // Remove status, which should not be modified.
    unset($params['status']);

    $params['kind'] = 'NetworkPolicy';

    return $this->getClient($namespace)
      ->networkPolicies()
      ->update(new NetworkPolicy($params));
  }

  /**
   * {@inheritdoc}
   */
  public function deleteNetworkPolicy($namespace, array $params = []) {
    $params['kind'] = 'NetworkPolicy';

    return $this->getClient($namespace)
      ->networkPolicies()
      ->delete(new NetworkPolicy($params));
  }

  /**
   * {@inheritdoc}
   */
  public function clearAllEntities() {
    $this->clearEntities('k8s_node', time());
    $this->clearEntities('k8s_namespace', time());
    $this->clearEntities('k8s_pod', time());
    $this->clearEntities('k8s_deployment', time());
    $this->clearEntities('k8s_replica_set', time());
    $this->clearEntities('k8s_service', time());
    $this->clearEntities('k8s_cron_job', time());
    $this->clearEntities('k8s_job', time());
    $this->clearEntities('k8s_resource_quota', time());
    $this->clearEntities('k8s_limit_range', time());
    $this->clearEntities('k8s_secret', time());
    $this->clearEntities('k8s_config_map', time());
  }

  /**
   * Helper method to load an entity using parameters.
   *
   * @param string $entity_type
   *   Entity Type.
   * @param string $id_field
   *   Entity ID field.
   * @param string $id_value
   *   Entity ID value.
   * @param array $extra_conditions
   *   Extra conditions.
   *
   * @return int
   *   Entity ID.
   */
  public function getEntityId($entity_type, $id_field, $id_value, array $extra_conditions = []) {
    $query = $this->entityTypeManager
      ->getStorage($entity_type)
      ->getQuery()
      ->condition($id_field, $id_value)
      ->condition('cloud_context', $this->cloudContext);

    foreach ($extra_conditions as $key => $value) {
      $query->condition($key, $value);
    }

    $entities = $query->execute();
    return array_shift($entities);
  }

  /**
   * Setup the default parameters that all API calls will need.
   *
   * @return array
   *   Array of default parameters.
   */
  protected function getDefaultParameters() {
    return [];
  }

  /**
   * Generate a lock key based on entity name.
   *
   * @param string $name
   *   The entity name.
   *
   * @return string
   *   The lock key.
   */
  protected function getLockKey($name) {
    return $this->cloudContext . '_' . $name;
  }

  /**
   * Initialize a new batch builder.
   *
   * @param string $batch_name
   *   The batch name.
   *
   * @return \Drupal\Core\Batch\BatchBuilder
   *   The initialized batch object.
   */
  protected function initBatch($batch_name) {
    return (new BatchBuilder())
      ->setTitle($batch_name);
  }

  /**
   * Run the batch job to process entities.
   *
   * @param \Drupal\Core\Batch\BatchBuilder $batch_builder
   *   The batch builder object.
   */
  protected function runBatch(BatchBuilder $batch_builder) {
    // Log the start time.
    $start = time();
    $batch_array = $batch_builder->toArray();
    batch_set($batch_array);

    // Reset the progressive so batch works with out a web head.
    $batch = &batch_get();
    $batch['progressive'] = FALSE;
    batch_process();

    // Log the end time.
    $end = time();
    $this->logger->info(
      $this->t('@updater - @cloud_context: Batch operation took @time seconds.',
        [
          '@cloud_context' => $this->cloudContext,
          '@updater' => $batch_array['title'],
          '@time' => $end - $start,
        ]
      )
    );
  }

  /**
   * Update entities.
   *
   * @param string $entity_type
   *   The entity type.
   * @param string $entity_type_label
   *   The entity type label.
   * @param string $get_entities_method
   *   The method name of get entities.
   * @param string $update_entity_method
   *   The method name of update entity.
   * @param array $params
   *   The params for API Call.
   * @param bool $clear
   *   TRUE to clear stale entities.
   * @param string $extra_key_name
   *   The extra key name.
   * @param bool $batch_mode
   *   Whether updating entities in batch.
   */
  private function updateEntities(
    $entity_type,
    $entity_type_label,
    $get_entities_method,
    $update_entity_method,
    array $params = [],
    $clear = TRUE,
    $extra_key_name = NULL,
    $batch_mode = TRUE
  ) {
    $updated = FALSE;
    $lock_name = $this->getLockKey($entity_type);

    if (!$this->lock->acquire($lock_name)) {
      return FALSE;
    }

    $result = NULL;
    try {
      $result = $this->$get_entities_method($params);
    }
    catch (K8sServiceException $e) {
    }
    if ($result !== NULL) {
      $all_entities = $this->loadAllEntities($entity_type);
      $stale = [];
      foreach ($all_entities as $entity) {
        $key = $entity->getName();
        if (!empty($extra_key_name)) {
          $extra_key_get_method = 'get' . ucfirst($extra_key_name);
          $key .= ':' . $entity->$extra_key_get_method();
        }
        $stale[$key] = $entity;
      }

      if ($batch_mode) {
        /* @var \Drupal\Core\Batch\BatchBuilder $batch_builder */
        $batch_builder = $this->initBatch("$entity_type_label Update");
      }

      foreach ($result as $entity) {
        // Keep track of snapshot that do not exist anymore
        // delete them after saving the rest of the snapshots.
        $key = $entity['metadata']['name'];
        if (!empty($extra_key_name)) {
          $key .= ':' . $entity['metadata']['namespace'];
        }
        if (isset($stale[$key])) {
          unset($stale[$key]);
        }

        if ($batch_mode) {
          $batch_builder->addOperation([
            K8sBatchOperations::class,
            $update_entity_method,
          ], [$this->cloudContext, $entity]);
        }
        else {
          K8sBatchOperations::$update_entity_method($this->cloudContext, $entity);
        }
      }

      if ($batch_mode) {
        $batch_builder->addOperation([
          '\Drupal\k8s\Service\K8sBatchOperations',
          'finished',
        ], [$entity_type, $stale, $clear]);
        $this->runBatch($batch_builder);
      }
      else {
        if (count($stale) && $clear == TRUE) {
          $this->entityTypeManager->getStorage($entity_type)->delete($stale);
        }
      }

      $updated = TRUE;
    }

    $this->lock->release($lock_name);
    return $updated;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc