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

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

namespace Drupal\k8s\Service;

use Drupal\Core\Entity\EntityInterface;
use Drupal\Component\Serialization\Yaml;

use Drupal\k8s\Entity\K8sNode;
use Drupal\k8s\Entity\K8sNamespace;
use Drupal\k8s\Entity\K8sPod;
use Drupal\k8s\Entity\K8sDeployment;
use Drupal\k8s\Entity\K8sReplicaSet;
use Drupal\k8s\Entity\K8sServiceEntity;
use Drupal\k8s\Entity\K8sCronJob;
use Drupal\k8s\Entity\K8sJob;
use Drupal\k8s\Entity\K8sResourceQuota;
use Drupal\k8s\Entity\K8sLimitRange;
use Drupal\k8s\Entity\K8sSecret;
use Drupal\k8s\Entity\K8sConfigMap;
use Drupal\k8s\Entity\K8sEntityBase;
use Drupal\k8s\Entity\K8sNetworkPolicy;

/**
 * Entity update methods for Batch API processing.
 */
class K8sBatchOperations {

  /**
   * The finish callback function.
   *
   * Deletes stale entities from the database.
   *
   * @param string $entity_type
   *   The entity type.
   * @param array $stale
   *   The stale entities to delete.
   * @param bool $clear
   *   TRUE to clear entities, FALSE keep them.
   */
  public static function finished($entity_type, array $stale, $clear = TRUE) {
    $entity_type_manager = \Drupal::entityTypeManager();
    if (count($stale) && $clear == TRUE) {
      $entity_type_manager->getStorage($entity_type)->delete($stale);
    }
  }

  /**
   * Update or create a k8s node entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $node
   *   The node array.
   */
  public static function updateNode($cloud_context, array $node) {
    $k8s_service = \Drupal::service('k8s');
    $k8s_service->setCloudContext($cloud_context);

    $timestamp = time();
    $name = $node['metadata']['name'];
    $entity_id = $k8s_service->getEntityId('k8s_node', 'name', $name);

    $status = '';
    $last_condition = end($node['status']['conditions']);
    if (!empty($last_condition)) {
      $status = $last_condition['type'];
    }

    if (!empty($entity_id)) {
      $entity = K8sNode::load($entity_id);
    }
    else {
      $entity = K8sNode::create([
        'cloud_context' => $cloud_context,
        'name' => $name,
        'created' => strtotime($node['metadata']['creationTimestamp']),
        'changed' => strtotime($node['metadata']['creationTimestamp']),
        'refreshed' => $timestamp,
      ]);
    }

    $entity->setStatus($status);

    // Labels.
    self::setKeyValueTypeFieldValue($entity, 'labels', $node['metadata']['labels']);

    // Annotations.
    self::setKeyValueTypeFieldValue($entity, 'annotations', $node['metadata']['annotations']);

    // Addresses.
    $map = [];
    foreach ($node['status']['addresses'] as $address) {
      $map[$address['type']] = $address['address'];
    }
    self::setKeyValueTypeFieldValue($entity, 'addresses', $map);

    // Metrics.
    // Capacity.
    $entity->setCpuCapacity($node['status']['capacity']['cpu']);
    $entity->setMemoryCapacity(k8s_convert_memory_to_integer($node['status']['capacity']['memory']));
    $entity->setPodsCapacity($node['status']['capacity']['pods']);

    // Request and limit.
    $pods = $k8s_service->getPods(['spec.nodeName' => $name]);
    $cpu_limit = 0;
    $cpu_request = 0;
    $memory_limit = 0;
    $memory_request = 0;
    $pods_allocation = 0;
    foreach ($pods as $pod) {
      if (!isset($pod['spec']['containers'])) {
        continue;
      }

      // Skip if the status is Succeeded or Failed.
      if ($pod['status']['phase'] == 'Succeeded' || $pod['status']['phase'] == 'Failed') {
        continue;
      }

      $pods_allocation++;

      foreach ($pod['spec']['containers'] as $container) {
        if (isset($container['resources']['requests'])) {
          $requests = $container['resources']['requests'];
          if (isset($requests['cpu'])) {
            $cpu_request += k8s_convert_cpu_to_float($requests['cpu']);
          }

          if (isset($requests['memory'])) {
            $memory_request += k8s_convert_memory_to_integer($requests['memory']);
          }
        }

        if (isset($container['resources']['limits'])) {
          $limits = $container['resources']['limits'];
          if (isset($limits['cpu'])) {
            $cpu_limit += k8s_convert_cpu_to_float($limits['cpu']);
          }

          if (isset($limits['memory'])) {
            $memory_limit += k8s_convert_memory_to_integer($limits['memory']);
          }
        }
      }
    }

    $entity->setCpuRequest($cpu_request);
    $entity->setCpuLimit($cpu_limit);
    $entity->setMemoryRequest($memory_request);
    $entity->setMemoryLimit($memory_limit);

    $metrics_nodes = [];
    try {
      $metrics_nodes = $k8s_service->getMetricsNodes(['metadata.name' => $name]);
    }
    catch (K8sServiceException $e) {
      \Drupal::messenger()->addWarning(t('Unable to retrieve CPU and Memory usage of nodes. Please install <a href="https://github.com/kubernetes-incubator/metrics-server">Kubernetes Metrics Server</a> to K8s.'));
    }

    if (!empty($metrics_nodes)) {
      k8s_export_node_metrics($cloud_context, $metrics_nodes);
      if (isset($metrics_nodes[0]['usage']['cpu'])) {
        $entity->setCpuUsage(k8s_convert_cpu_to_float($metrics_nodes[0]['usage']['cpu']));
      }

      if (isset($metrics_nodes[0]['usage']['memory'])) {
        $entity->setMemoryUsage(k8s_convert_memory_to_integer($metrics_nodes[0]['usage']['memory']));
      }
    }

    // Pods allocated.
    $entity->setPodsAllocation($pods_allocation);

    $entity->setPodCidr(isset($node['spec']['podCIDR']) ? $node['spec']['podCIDR'] : '');
    $entity->setProviderId($node['spec']['providerID']);
    $entity->setUnschedulable(isset($node['spec']['unschedulable']) ?: FALSE);
    $entity->setMachineId($node['status']['nodeInfo']['machineID']);
    $entity->setSystemUuid($node['status']['nodeInfo']['systemUUID']);
    $entity->setBootId($node['status']['nodeInfo']['bootID']);
    $entity->setKernelVersion($node['status']['nodeInfo']['kernelVersion']);
    $entity->setOsImage($node['status']['nodeInfo']['osImage']);
    $entity->setContainerRuntimeVersion($node['status']['nodeInfo']['containerRuntimeVersion']);
    $entity->setKubeletVersion($node['status']['nodeInfo']['kubeletVersion']);
    $entity->setKubeProxyVersion($node['status']['nodeInfo']['kubeProxyVersion']);
    $entity->setOperatingSystem($node['status']['nodeInfo']['operatingSystem']);
    $entity->setArchitecture($node['status']['nodeInfo']['architecture']);
    $entity->setDetail(Yaml::encode($node));

    $entity->setRefreshed($timestamp);
    $entity->save();
  }

  /**
   * Update or create a k8s namespace entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $namespace
   *   The namespace array.
   */
  public static function updateNamespace($cloud_context, array $namespace) {
    $k8s_service = \Drupal::service('k8s');
    $k8s_service->setCloudContext($cloud_context);

    $timestamp = time();
    $name = $namespace['metadata']['name'];
    $entity_id = $k8s_service->getEntityId('k8s_namespace', 'name', $name);

    $status = $namespace['status']['phase'];

    if (!empty($entity_id)) {
      $entity = K8sNamespace::load($entity_id);
    }
    else {
      $entity = K8sNamespace::create([
        'cloud_context' => $cloud_context,
        'name' => $name,
        'created' => strtotime($namespace['metadata']['creationTimestamp']),
        'changed' => strtotime($namespace['metadata']['creationTimestamp']),
        'refreshed' => $timestamp,
      ]);
    }

    $entity->setStatus($status);

    // Labels.
    $labels = [];
    if (!empty($namespace['metadata']['labels'])) {
      $labels = $namespace['metadata']['labels'];
    }
    self::setKeyValueTypeFieldValue($entity, 'labels', $labels);

    $entity->setDetail(Yaml::encode($namespace));
    $entity->setRefreshed($timestamp);
    $entity->save();
  }

  /**
   * Update or create a k8s pod entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $pod
   *   The pod array.
   */
  public static function updatePod($cloud_context, array $pod) {
    $k8s_service = \Drupal::service('k8s');
    $k8s_service->setCloudContext($cloud_context);

    $timestamp = time();
    $name = $pod['metadata']['name'];
    $namespace = $pod['metadata']['namespace'];
    $entity_id = $k8s_service->getEntityId(
      'k8s_pod',
      'name',
      $name,
      ['namespace' => $namespace]
    );

    if (!empty($entity_id)) {
      $entity = K8sPod::load($entity_id);
    }
    else {
      $entity = K8sPod::create([
        'cloud_context' => $cloud_context,
        'name' => $name,
        'created' => strtotime($pod['metadata']['creationTimestamp']),
        'changed' => strtotime($pod['metadata']['creationTimestamp']),
        'refreshed' => $timestamp,
      ]);
    }

    // Owner ID.
    $uid = NULL;
    if (isset($pod['metadata']['annotations'])
      && isset($pod['metadata']['annotations'][K8sEntityBase::ANNOTATION_CREATED_BY_UID])) {
      $uid = $pod['metadata']['annotations'][K8sEntityBase::ANNOTATION_CREATED_BY_UID];
    }
    $entity->setOwnerById($uid);

    // Labels.
    self::setKeyValueTypeFieldValue(
      $entity,
      'labels',
      isset($pod['metadata']['labels']) ? $pod['metadata']['labels'] : []
    );

    // Annotations.
    self::setKeyValueTypeFieldValue(
      $entity,
      'annotations',
      isset($pod['metadata']['annotations']) ? $pod['metadata']['annotations'] : []
    );

    // Containers.
    $containers = [];
    foreach ($pod['spec']['containers'] as $container_data) {
      $containers[] = Yaml::encode($container_data);
    }
    $entity->setContainers($containers);

    // Restarts.
    if (!empty($pod['status']['containerStatuses'])) {
      $entity->setRestarts($pod['status']['containerStatuses'][0]['restartCount']);
    }

    // Metrics.
    $cpu_request = 0;
    $cpu_limit = 0;
    $memory_limit = 0;
    $memory_request = 0;
    foreach ($pod['spec']['containers'] as $container) {
      if (isset($container['resources']['requests'])) {
        $requests = $container['resources']['requests'];
        if (isset($requests['cpu'])) {
          $cpu_request += k8s_convert_cpu_to_float($requests['cpu']);
        }

        if (isset($requests['memory'])) {
          $memory_request += k8s_convert_memory_to_integer($requests['memory']);
        }
      }

      if (isset($container['resources']['limits'])) {
        $limits = $container['resources']['limits'];
        if (isset($limits['cpu'])) {
          $cpu_limit += k8s_convert_cpu_to_float($limits['cpu']);
        }

        if (isset($limits['memory'])) {
          $memory_limit += k8s_convert_memory_to_integer($limits['memory']);
        }
      }
    }

    $entity->setCpuRequest($cpu_request);
    $entity->setCpuLimit($cpu_limit);
    $entity->setMemoryRequest($memory_request);
    $entity->setMemoryLimit($memory_limit);

    if ($pod['status']['phase'] != 'Succeeded' && $pod['status']['phase'] != 'Failed') {
      $metrics_pods = [];
      try {
        $metrics_pods = $k8s_service->getMetricsPods(['metadata.name' => $name]);
      }
      catch (K8sServiceException $e) {
        \Drupal::messenger()->addWarning(t('Unable to retrieve CPU and Memory usage of pods. Please install <a href="https://github.com/kubernetes-incubator/metrics-server">Kubernetes Metrics Server</a> to K8s.'));
      }
      $cpu_usage = 0;
      $memory_usage = 0;
      if (!empty($metrics_pods)) {
        k8s_export_pod_metrics($cloud_context, $metrics_pods);

        foreach ($metrics_pods[0]['containers'] as $container) {
          if (isset($container['usage']['cpu'])) {
            $cpu_usage += k8s_convert_cpu_to_float($container['usage']['cpu']);
          }

          if (isset($container['usage']['memory'])) {
            $memory_usage += k8s_convert_memory_to_integer($container['usage']['memory']);
          }
        }

        $entity->setCpuUsage($cpu_usage);
        $entity->setMemoryUsage($memory_usage);
      }
    }

    // Detail.
    $entity->setDetail(Yaml::encode($pod));

    $entity->setNamespace($pod['metadata']['namespace']);
    $entity->setStatus($pod['status']['phase']);
    $entity->setQosClass($pod['status']['qosClass']);
    $entity->setNodeName($pod['spec']['nodeName']);
    $entity->setPodIp(isset($pod['status']['podIP']) ? $pod['status']['podIP'] : '');
    $entity->setRefreshed($timestamp);
    $entity->save();
  }

  /**
   * Update or create a k8s deployment entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $deployment
   *   The deployment array.
   */
  public static function updateDeployment($cloud_context, array $deployment) {
    $k8s_service = \Drupal::service('k8s');
    $k8s_service->setCloudContext($cloud_context);

    $timestamp = time();
    $name = $deployment['metadata']['name'];
    $namespace = $deployment['metadata']['namespace'];
    $entity_id = $k8s_service->getEntityId(
      'k8s_deployment',
      'name',
      $name,
      ['namespace' => $namespace]
    );

    if (!empty($entity_id)) {
      $entity = K8sDeployment::load($entity_id);
    }
    else {
      $entity = K8sDeployment::create([
        'cloud_context' => $cloud_context,
        'name' => $name,
        'created' => strtotime($deployment['metadata']['creationTimestamp']),
        'changed' => strtotime($deployment['metadata']['creationTimestamp']),
        'refreshed' => $timestamp,
      ]);
    }

    // Labels.
    self::setKeyValueTypeFieldValue(
      $entity,
      'labels',
      isset($deployment['metadata']['labels']) ? $deployment['metadata']['labels'] : []
    );

    // Annotations.
    self::setKeyValueTypeFieldValue(
      $entity,
      'annotations',
      isset($deployment['metadata']['annotations']) ? $deployment['metadata']['annotations'] : []
    );

    // Detail.
    $entity->setDetail(Yaml::encode($deployment));

    $entity->setNamespace($deployment['metadata']['namespace']);
    $entity->setStrategy($deployment['spec']['strategy']['type']);
    $entity->setMinReadySeconds(isset($deployment['spec']['minReadySeconds']) ? $deployment['spec']['minReadySeconds'] : 0);
    $entity->setRevisionHistoryLimit($deployment['spec']['revisionHistoryLimit']);
    $entity->setAvailableReplicas(isset($deployment['status']['availableReplicas']) ? $deployment['status']['availableReplicas'] : 0);
    $entity->setCollisionCount(isset($deployment['status']['collisionCount']) ? $deployment['status']['collisionCount'] : 0);
    $entity->setObservedGeneration(isset($deployment['status']['observedGeneration']) ? $deployment['status']['observedGeneration'] : 0);
    $entity->setReadyReplicas(isset($deployment['status']['readyReplicas']) ? $deployment['status']['readyReplicas'] : 0);
    $entity->setReplicas(isset($deployment['status']['replicas']) ? $deployment['status']['replicas'] : 0);
    $entity->setUnavailableReplicas(isset($deployment['status']['unavailableReplicas']) ? $deployment['status']['unavailableReplicas'] : 0);
    $entity->setUpdatedReplicas(isset($deployment['status']['updatedReplicas']) ? $deployment['status']['updatedReplicas'] : 0);

    $entity->setRefreshed($timestamp);
    $entity->save();
  }

  /**
   * Update or create a k8s replica set entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $replica_set
   *   The replica set array.
   */
  public static function updateReplicaSet($cloud_context, array $replica_set) {
    $k8s_service = \Drupal::service('k8s');
    $k8s_service->setCloudContext($cloud_context);

    $timestamp = time();
    $name = $replica_set['metadata']['name'];
    $namespace = $replica_set['metadata']['namespace'];
    $entity_id = $k8s_service->getEntityId(
      'k8s_replica_set',
      'name',
      $name,
      ['namespace' => $namespace]
    );

    if (!empty($entity_id)) {
      $entity = K8sReplicaSet::load($entity_id);
    }
    else {
      $entity = K8sReplicaSet::create([
        'cloud_context' => $cloud_context,
        'name' => $name,
        'created' => strtotime($replica_set['metadata']['creationTimestamp']),
        'changed' => strtotime($replica_set['metadata']['creationTimestamp']),
        'refreshed' => $timestamp,
      ]);
    }

    // Labels.
    self::setKeyValueTypeFieldValue(
      $entity,
      'labels',
      isset($replica_set['metadata']['labels']) ? $replica_set['metadata']['labels'] : []
    );

    // Annotations.
    self::setKeyValueTypeFieldValue(
      $entity,
      'annotations',
      isset($replica_set['metadata']['annotations']) ? $replica_set['metadata']['annotations'] : []
    );

    // Detail.
    $entity->setDetail(Yaml::encode($replica_set));
    $entity->setNamespace($replica_set['metadata']['namespace']);
    $entity->setReplicas(isset($replica_set['spec']['replicas']) ? $replica_set['spec']['replicas'] : 0);
    $entity->setAvailableReplicas(isset($replica_set['status']['availableReplicas']) ? $replica_set['status']['availableReplicas'] : 0);
    $entity->setFullyLabeledReplicas(isset($replica_set['status']['fullyLabeledReplicas']) ? $replica_set['status']['fullyLabeledReplicas'] : 0);
    $entity->setReadyReplicas(isset($replica_set['status']['readyReplicas']) ? $replica_set['status']['readyReplicas'] : 0);
    $entity->setObservedGeneration(isset($replica_set['status']['observedGeneration']) ? $replica_set['status']['observedGeneration'] : 0);
    $entity->setRefreshed($timestamp);
    $entity->save();
  }

  /**
   * Update or create a k8s service entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $service
   *   The service array.
   */
  public static function updateService($cloud_context, array $service) {
    $k8s_service = \Drupal::service('k8s');
    $k8s_service->setCloudContext($cloud_context);

    $timestamp = time();
    $name = $service['metadata']['name'];
    $namespace = $service['metadata']['namespace'];
    $entity_id = $k8s_service->getEntityId(
      'k8s_service',
      'name',
      $name,
      ['namespace' => $namespace]
    );

    if (!empty($entity_id)) {
      $entity = K8sServiceEntity::load($entity_id);
    }
    else {
      $entity = K8sServiceEntity::create([
        'cloud_context' => $cloud_context,
        'name' => $name,
        'created' => strtotime($service['metadata']['creationTimestamp']),
        'changed' => strtotime($service['metadata']['creationTimestamp']),
        'refreshed' => $timestamp,
      ]);
    }

    // Labels.
    self::setKeyValueTypeFieldValue(
      $entity,
      'labels',
      isset($service['metadata']['labels']) ? $service['metadata']['labels'] : []
    );

    // Annotations.
    self::setKeyValueTypeFieldValue(
      $entity,
      'annotations',
      isset($service['metadata']['annotations']) ? $service['metadata']['annotations'] : []
    );

    // Selector.
    self::setKeyValueTypeFieldValue(
      $entity,
      'selector',
      isset($service['spec']['selector']) ? $service['spec']['selector'] : []
    );

    $namespace = $service['metadata']['namespace'];

    // Internal endpoints.
    $internal_endpoints = [];
    foreach ($service['spec']['ports'] as $port) {
      $internal_endpoints[] = sprintf(
        '%s.%s:%s %s',
        $name,
        $namespace,
        $port['port'],
        $port['protocol']
      );

      if (isset($port['nodePort'])) {
        $internal_endpoints[] = sprintf(
          '%s.%s:%s %s',
          $name,
          $namespace,
          $port['nodePort'],
          $port['protocol']
        );
      }
    }
    $entity->setInternalEndpoints($internal_endpoints);

    // External endpoints.
    if ($service['spec']['type'] == 'LoadBalancer') {
      $external_endpoints = [];

      if (isset($service['status']['loadBalancer']['ingress'])) {
        foreach ($service['status']['loadBalancer']['ingress'] as $lb) {
          foreach ($service['spec']['ports'] as $port) {
            $external_endpoints[] = sprintf(
              '%s:%s',
              $lb['hostname'],
              $port['port']
            );
          }
        }
      }

      $entity->setExternalEndpoints($external_endpoints);
    }

    // Detail.
    $entity->setDetail(Yaml::encode($service));

    $entity->setNamespace($namespace);
    $entity->setType($service['spec']['type']);
    $entity->setSessionAffinity($service['spec']['sessionAffinity']);
    $entity->setClusterIp($service['spec']['clusterIP']);

    $entity->setRefreshed($timestamp);
    $entity->save();
  }

  /**
   * Update or create a k8s cron job entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $cron_job
   *   The cron job array.
   */
  public static function updateCronJob($cloud_context, array $cron_job) {
    $k8s_service = \Drupal::service('k8s');
    $k8s_service->setCloudContext($cloud_context);

    $timestamp = time();
    $name = $cron_job['metadata']['name'];
    $namespace = $cron_job['metadata']['namespace'];
    $entity_id = $k8s_service->getEntityId(
      'k8s_cron_job',
      'name',
      $name,
      ['namespace' => $namespace]
    );

    if (!empty($entity_id)) {
      $entity = K8sCronJob::load($entity_id);
    }
    else {
      $entity = K8sCronJob::create([
        'cloud_context' => $cloud_context,
        'name' => $name,
        'created' => strtotime($cron_job['metadata']['creationTimestamp']),
        'changed' => strtotime($cron_job['metadata']['creationTimestamp']),
        'refreshed' => $timestamp,
      ]);
    }

    // Labels.
    self::setKeyValueTypeFieldValue(
      $entity,
      'labels',
      isset($cron_job['metadata']['labels']) ? $cron_job['metadata']['labels'] : []
    );

    // Annotations.
    self::setKeyValueTypeFieldValue(
      $entity,
      'annotations',
      isset($cron_job['metadata']['annotations']) ? $cron_job['metadata']['annotations'] : []
    );

    $namespace = $cron_job['metadata']['namespace'];

    // Active.
    if (isset($cron_job['status']['active'])) {
      $entity->setActive(count($cron_job['status']['active']));
    }
    else {
      $entity->setActive(0);
    }

    // Detail.
    $entity->setDetail(Yaml::encode($cron_job));

    $entity->setNamespace($namespace);
    $entity->setSchedule($cron_job['spec']['schedule']);
    $entity->setSuspend($cron_job['spec']['suspend']);

    if (!empty($cron_job['status']['lastScheduleTime'])) {
      $entity->setLastScheduleTime(strtotime($cron_job['status']['lastScheduleTime']));
    }
    $entity->setConcurrencyPolicy($cron_job['spec']['concurrencyPolicy']);
    if (isset($cron_job['spec']['startingDeadlineSeconds'])) {
      $entity->setStartingDeadlineSeconds($cron_job['spec']['startingDeadlineSeconds']);
    }

    $entity->setRefreshed($timestamp);
    $entity->save();
  }

  /**
   * Update or create a k8s job entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $job
   *   The job array.
   */
  public static function updateJob($cloud_context, array $job) {
    $k8s_service = \Drupal::service('k8s');
    $k8s_service->setCloudContext($cloud_context);

    $timestamp = time();
    $name = $job['metadata']['name'];
    $namespace = $job['metadata']['namespace'];
    $entity_id = $k8s_service->getEntityId(
      'k8s_job',
      'name',
      $name,
      ['namespace' => $namespace]
    );

    if (!empty($entity_id)) {
      $entity = K8sJob::load($entity_id);
    }
    else {
      $entity = K8sJob::create([
        'cloud_context' => $cloud_context,
        'name' => $name,
        'created' => strtotime($job['metadata']['creationTimestamp']),
        'changed' => strtotime($job['metadata']['creationTimestamp']),
        'refreshed' => $timestamp,
      ]);
    }

    // Labels.
    self::setKeyValueTypeFieldValue(
      $entity,
      'labels',
      isset($job['metadata']['labels']) ? $job['metadata']['labels'] : []
    );

    // Annotations.
    self::setKeyValueTypeFieldValue(
      $entity,
      'annotations',
      isset($job['metadata']['annotations']) ? $job['metadata']['annotations'] : []
    );

    $namespace = $job['metadata']['namespace'];

    // Image.
    if (!empty($job['spec']['template']['spec']['containers'])) {
      $entity->setImage($job['spec']['template']['spec']['containers'][0]['image']);
    }

    // Detail.
    $entity->setDetail(Yaml::encode($job));

    $entity->setNamespace($namespace);
    $entity->setCompletions($job['spec']['completions']);
    $entity->setParallelism($job['spec']['parallelism']);

    // Active.
    if (isset($job['status']['active'])) {
      $entity->setActive($job['status']['active']);
    }
    else {
      $entity->setActive(0);
    }

    // Succeeded.
    if (isset($job['status']['succeeded'])) {
      $entity->setSucceeded($job['status']['succeeded']);
    }
    else {
      $entity->setSucceeded(0);
    }

    // Failed.
    if (isset($job['status']['failed'])) {
      $entity->setFailed($job['status']['failed']);
    }
    else {
      $entity->setFailed(0);
    }

    $entity->setRefreshed($timestamp);
    $entity->save();
  }

  /**
   * Update or create a k8s resource quota entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $resource_quota
   *   The resource quota array.
   */
  public static function updateResourceQuota($cloud_context, array $resource_quota) {
    $k8s_service = \Drupal::service('k8s');
    $k8s_service->setCloudContext($cloud_context);

    $timestamp = time();
    $name = $resource_quota['metadata']['name'];
    $namespace = $resource_quota['metadata']['namespace'];
    $entity_id = $k8s_service->getEntityId(
      'k8s_resource_quota',
      'name',
      $name,
      ['namespace' => $namespace]
    );

    if (!empty($entity_id)) {
      $entity = K8sResourceQuota::load($entity_id);
    }
    else {
      $entity = K8sResourceQuota::create([
        'cloud_context' => $cloud_context,
        'name' => $name,
        'created' => strtotime($resource_quota['metadata']['creationTimestamp']),
        'changed' => strtotime($resource_quota['metadata']['creationTimestamp']),
        'refreshed' => $timestamp,
      ]);
    }

    // Labels.
    self::setKeyValueTypeFieldValue(
      $entity,
      'labels',
      isset($resource_quota['metadata']['labels']) ? $resource_quota['metadata']['labels'] : []
    );

    // Annotations.
    self::setKeyValueTypeFieldValue(
      $entity,
      'annotations',
      isset($resource_quota['metadata']['annotations']) ? $resource_quota['metadata']['annotations'] : []
    );

    // Status hard.
    self::setKeyValueTypeFieldValue(
      $entity,
      'status_hard',
      isset($resource_quota['status']['hard']) ? $resource_quota['status']['hard'] : []
    );

    // Status used.
    self::setKeyValueTypeFieldValue(
      $entity,
      'status_used',
      isset($resource_quota['status']['used']) ? $resource_quota['status']['used'] : []
    );

    // Detail.
    $entity->setDetail(Yaml::encode($resource_quota));

    $namespace = $resource_quota['metadata']['namespace'];
    $entity->setNamespace($namespace);
    $entity->setRefreshed($timestamp);
    $entity->save();
  }

  /**
   * Update or create a k8s limit range entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $limit_range
   *   The limit range array.
   */
  public static function updateLimitRange($cloud_context, array $limit_range) {
    $k8s_service = \Drupal::service('k8s');
    $k8s_service->setCloudContext($cloud_context);

    $timestamp = time();
    $name = $limit_range['metadata']['name'];
    $namespace = $limit_range['metadata']['namespace'];
    $entity_id = $k8s_service->getEntityId(
      'k8s_limit_range',
      'name',
      $name,
      ['namespace' => $namespace]
    );

    if (!empty($entity_id)) {
      $entity = K8sLimitRange::load($entity_id);
    }
    else {
      $entity = K8sLimitRange::create([
        'cloud_context' => $cloud_context,
        'name' => $name,
        'created' => strtotime($limit_range['metadata']['creationTimestamp']),
        'changed' => strtotime($limit_range['metadata']['creationTimestamp']),
        'refreshed' => $timestamp,
      ]);
    }

    // Labels.
    self::setKeyValueTypeFieldValue(
      $entity,
      'labels',
      isset($limit_range['metadata']['labels']) ? $limit_range['metadata']['labels'] : []
    );

    // Annotations.
    self::setKeyValueTypeFieldValue(
      $entity,
      'annotations',
      isset($limit_range['metadata']['annotations']) ? $limit_range['metadata']['annotations'] : []
    );

    // Limits.
    $resources = [
      'cpu',
      'memory',
      'storage',
    ];
    $fields = [
      'max',
      'min',
      'default',
      'default_request',
      'max_limit_request_ratio',
    ];
    $limits = [];
    foreach ($limit_range['spec']['limits'] as $limit_data) {
      $limit = [];
      $limit['limit_type'] = $limit_data['type'];
      foreach ($resources as $resource) {
        $limit['resource'] = $resource;
        $has_limit_data = FALSE;
        foreach ($fields as $field) {
          $field_camel = lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $field))));

          if (empty($limit_data[$field_camel]) || empty($limit_data[$field_camel][$resource])) {
            continue;
          }

          $has_limit_data = TRUE;
          $limit[$field] = $limit_data[$field_camel][$resource];
        }

        if ($has_limit_data) {
          $limits[] = $limit;
        }
      }
    }

    $entity->set('limits', $limits);

    // Detail.
    $entity->setDetail(Yaml::encode($limit_range));

    $namespace = $limit_range['metadata']['namespace'];
    $entity->setNamespace($namespace);
    $entity->setRefreshed($timestamp);
    $entity->save();
  }

  /**
   * Update or create a k8s secret entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $secret
   *   The secret array.
   */
  public static function updateSecret($cloud_context, array $secret) {
    $k8s_service = \Drupal::service('k8s');
    $k8s_service->setCloudContext($cloud_context);

    $timestamp = time();
    $name = $secret['metadata']['name'];
    $namespace = $secret['metadata']['namespace'];
    $entity_id = $k8s_service->getEntityId(
      'k8s_secret',
      'name',
      $name,
      ['namespace' => $namespace]
    );

    if (!empty($entity_id)) {
      $entity = K8sSecret::load($entity_id);
    }
    else {
      $entity = K8sSecret::create([
        'cloud_context' => $cloud_context,
        'name' => $name,
        'created' => strtotime($secret['metadata']['creationTimestamp']),
        'changed' => strtotime($secret['metadata']['creationTimestamp']),
        'refreshed' => $timestamp,
      ]);
    }

    // Labels.
    self::setKeyValueTypeFieldValue(
      $entity,
      'labels',
      isset($secret['metadata']['labels']) ? $secret['metadata']['labels'] : []
    );

    // Annotations.
    self::setKeyValueTypeFieldValue(
      $entity,
      'annotations',
      isset($secret['metadata']['annotations']) ? $secret['metadata']['annotations'] : []
    );

    // Data.
    self::setKeyValueTypeFieldValue(
      $entity,
      'data',
      isset($secret['data']) ? $secret['data'] : []
    );

    // Detail.
    $entity->setDetail(Yaml::encode($secret));

    $namespace = $secret['metadata']['namespace'];
    $entity->setNamespace($namespace);
    $entity->setSecretType($secret['type']);
    $entity->setRefreshed($timestamp);
    $entity->save();
  }

  /**
   * Update or create a k8s config map entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $config_map
   *   The config map array.
   */
  public static function updateConfigMap($cloud_context, array $config_map) {
    $k8s_service = \Drupal::service('k8s');
    $k8s_service->setCloudContext($cloud_context);

    $timestamp = time();
    $name = $config_map['metadata']['name'];
    $namespace = $config_map['metadata']['namespace'];
    $entity_id = $k8s_service->getEntityId(
      'k8s_config_map',
      'name',
      $name,
      ['namespace' => $namespace]
    );

    if (!empty($entity_id)) {
      $entity = K8sConfigMap::load($entity_id);
    }
    else {
      $entity = K8sConfigMap::create([
        'cloud_context' => $cloud_context,
        'name' => $name,
        'created' => strtotime($config_map['metadata']['creationTimestamp']),
        'changed' => strtotime($config_map['metadata']['creationTimestamp']),
        'refreshed' => $timestamp,
      ]);
    }

    // Labels.
    self::setKeyValueTypeFieldValue(
      $entity,
      'labels',
      isset($config_map['metadata']['labels']) ? $config_map['metadata']['labels'] : []
    );

    // Annotations.
    self::setKeyValueTypeFieldValue(
      $entity,
      'annotations',
      isset($config_map['metadata']['annotations']) ? $config_map['metadata']['annotations'] : []
    );

    // Data.
    self::setKeyValueTypeFieldValue(
      $entity,
      'data',
      isset($config_map['data']) ? $config_map['data'] : []
    );

    // Detail.
    $entity->setDetail(Yaml::encode($config_map));

    $namespace = $config_map['metadata']['namespace'];
    $entity->setNamespace($namespace);
    $entity->setRefreshed($timestamp);
    $entity->save();
  }

  /**
   * Update or create a k8s network policy entity.
   *
   * @param string $cloud_context
   *   The cloud context.
   * @param array $network_policy
   *   The network policy array.
   */
  public static function updateNetworkPolicy($cloud_context, array $network_policy) {
    $k8s_service = \Drupal::service('k8s');
    $k8s_service->setCloudContext($cloud_context);

    $timestamp = time();
    $name = $network_policy['metadata']['name'];
    $namespace = $network_policy['metadata']['namespace'];
    $entity_id = $k8s_service->getEntityId(
      'k8s_network_policy',
      'name',
      $name,
      ['namespace' => $namespace]
    );

    if (!empty($entity_id)) {
      $entity = K8sNetworkPolicy::load($entity_id);
    }
    else {
      $entity = K8sNetworkPolicy::create([
        'cloud_context' => $cloud_context,
        'name' => $name,
        'created' => strtotime($network_policy['metadata']['creationTimestamp']),
        'changed' => strtotime($network_policy['metadata']['creationTimestamp']),
        'refreshed' => $timestamp,
      ]);
    }

    // Labels.
    self::setKeyValueTypeFieldValue(
      $entity,
      'labels',
      isset($network_policy['metadata']['labels']) ? $network_policy['metadata']['labels'] : []
    );

    // Annotations.
    self::setKeyValueTypeFieldValue(
      $entity,
      'annotations',
      isset($network_policy['metadata']['annotations']) ? $network_policy['metadata']['annotations'] : []
    );

    // Network Polices.
    self::setKeyValueTypeFieldValue(
      $entity,
      'egress',
      isset($network_policy['spec']['egress']) ? $network_policy['spec']['egress'] : []
    );

    self::setKeyValueTypeFieldValue(
      $entity,
      'ingress',
      isset($network_policy['spec']['pod_selector']) ? $network_policy['spec']['pod_selector'] : []
    );

    self::setKeyValueTypeFieldValue(
      $entity,
      'egress',
      isset($network_policy['spec']['policy_types']) ? $network_policy['spec']['policy_types'] : []
    );

    // Detail.
    $entity->setDetail(Yaml::encode($network_policy));

    $namespace = $network_policy['metadata']['namespace'];
    $entity->setNamespace($namespace);
    $entity->setRefreshed($timestamp);
    $entity->save();
  }

  /**
   * Set key_value type field value.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity object.
   * @param string $field_name
   *   The field name.
   * @param array $value_map
   *   The value of map type.
   */
  private static function setKeyValueTypeFieldValue(EntityInterface $entity, $field_name, array $value_map) {
    $key_values = [];
    if (!isset($value_map)) {
      $value_map = [];
    }
    foreach ($value_map as $key => $value) {
      $key_values[] = ['item_key' => $key, 'item_value' => $value ?: ''];
    }

    usort($key_values, function ($a, $b) {
      return strcmp($a['item_key'], $b['item_key']);
    });

    $entity->set($field_name, $key_values);
  }

}

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

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