cloud-8.x-2.0-beta1/modules/cloud_service_providers/k8s/src/Plugin/cloud/server_template/K8sCloudServerTemplatePlugin.php
modules/cloud_service_providers/k8s/src/Plugin/cloud/server_template/K8sCloudServerTemplatePlugin.php
<?php
namespace Drupal\k8s\Plugin\cloud\server_template;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\Messenger;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Component\Plugin\PluginBase;
use Drupal\Component\Uuid\UuidInterface;
use Drupal\cloud\Entity\CloudServerTemplateInterface;
use Drupal\cloud\Plugin\cloud\server_template\CloudServerTemplatePluginInterface;
use Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface;
use Drupal\k8s\Service\K8sServiceException;
use Drupal\k8s\Service\K8sServiceInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Component\Serialization\Yaml;
use Drupal\cloud\Service\EntityLinkRendererInterface;
/**
* K8s Cloud server template plugin.
*/
class K8sCloudServerTemplatePlugin extends PluginBase implements CloudServerTemplatePluginInterface, ContainerFactoryPluginInterface {
use StringTranslationTrait;
/**
* The K8s Service.
*
* @var \Drupal\k8s\Service\K8sServiceInterface
*/
protected $k8sService;
/**
* The Messenger service.
*
* @var \Drupal\Core\Messenger\Messenger
*/
protected $messenger;
/**
* The Entity Type Manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The UUID service.
*
* @var \Drupal\Component\Uuid\UuidInterface
*/
protected $uuidService;
/**
* Current login user.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $currentUser;
/**
* The config factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* The cloud service provider plugin manager (CloudConfigPluginManager).
*
* @var \Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface
*/
protected $cloudConfigPluginManager;
/**
* Entity link renderer object.
*
* @var \Drupal\cloud\Service\EntityLinkRendererInterface
*/
protected $entityLinkRenderer;
/**
* K8sCloudServerTemplatePlugin constructor.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\k8s\Service\K8sServiceInterface $k8s_service
* The AWS EC2 Service.
* @param \Drupal\Core\Messenger\Messenger $messenger
* The Messenger service.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Component\Uuid\UuidInterface $uuid_service
* The uuid service.
* @param \Drupal\Core\Session\AccountProxyInterface $current_user
* Current login user.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The factory for configuration objects.
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
* The string translation service.
* @param \Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface $cloud_config_plugin_manager
* The cloud service provider plugin manager (CloudConfigPluginManager).
* @param \Drupal\cloud\Service\EntityLinkRendererInterface $entity_link_renderer
* The entity link render service.
*/
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
K8sServiceInterface $k8s_service,
Messenger $messenger,
EntityTypeManagerInterface $entity_type_manager,
UuidInterface $uuid_service,
AccountProxyInterface $current_user,
ConfigFactoryInterface $config_factory,
TranslationInterface $string_translation,
CloudConfigPluginManagerInterface $cloud_config_plugin_manager,
EntityLinkRendererInterface $entity_link_renderer
) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->k8sService = $k8s_service;
$this->messenger = $messenger;
$this->entityTypeManager = $entity_type_manager;
$this->uuidService = $uuid_service;
$this->currentUser = $current_user;
$this->configFactory = $config_factory;
$this->stringTranslation = $string_translation;
$this->cloudConfigPluginManager = $cloud_config_plugin_manager;
$this->entityLinkRenderer = $entity_link_renderer;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('k8s'),
$container->get('messenger'),
$container->get('entity_type.manager'),
$container->get('uuid'),
$container->get('current_user'),
$container->get('config.factory'),
$container->get('string_translation'),
$container->get('plugin.manager.cloud_config_plugin'),
$container->get('entity.link_renderer')
);
}
/**
* {@inheritdoc}
*/
public function getEntityBundleName() {
return $this->pluginDefinition['entity_bundle'];
}
/**
* {@inheritdoc}
*/
public function launch(CloudServerTemplateInterface $cloud_server_template, FormStateInterface $form_state = NULL) {
$this->k8sService->setCloudContext($cloud_server_template->getCloudContext());
$k8s_obj = $cloud_server_template->get('field_object')->value;
$route = [
'route_name' => 'entity.cloud_server_template.canonical',
'params' => [
'cloud_server_template' => $cloud_server_template->id(),
'cloud_context' => $cloud_server_template->getCloudContext(),
],
];
switch ($k8s_obj) {
case 'pod':
$route = $this->launchPod($cloud_server_template);
break;
case 'deployment':
$route = $this->launchDeployment($cloud_server_template);
break;
default:
$this->messenger->addError($this->t('@object launch not supported.', ['@object' => $k8s_obj]));
}
return $route;
}
/**
* {@inheritdoc}
*/
public function buildListHeader() {
return [
[
'data' => t('Namespace'),
'specifier' => 'field_namespace',
'field' => 'field_namespace',
],
[
'data' => t('Object'),
'specifier' => 'field_object',
'field' => 'field_object',
],
];
}
/**
* {@inheritdoc}
*/
public function buildListRow(CloudServerTemplateInterface $entity) {
$row['field_namespace'] = [
'data' => $this->entityLinkRenderer->renderViewElement(
$entity->get('field_namespace')->value,
'k8s_namespace',
'name',
[]
),
];
$row['field_object'] = [
'data' => $this->renderField($entity, 'field_object'),
];
return $row;
}
/**
* Render a server template entity field.
*
* @param \Drupal\cloud\Entity\CloudServerTemplateInterface $entity
* The server template entity.
* @param string $field_name
* The field to render.
* @param string $view
* The view to render.
*
* @return array
* A fully loaded render array for that field or empty array.
*/
private function renderField(CloudServerTemplateInterface $entity, $field_name, $view = 'default') {
$field = [];
if ($entity->hasField($field_name)) {
$field = $entity->get($field_name)->view($view);
// Hide the label.
$field['#label_display'] = 'hidden';
}
return $field;
}
/**
* Launch a K8s deployment from a server template.
*
* @param \Drupal\cloud\Entity\CloudServerTemplateInterface $cloud_server_template
* Cloud server template interface.
*
* @return array
* The route to redirect after launch.
*/
private function launchDeployment(CloudServerTemplateInterface $cloud_server_template) {
$params = Yaml::decode($cloud_server_template->get('field_detail')->value);
$route = [
'route_name' => 'view.k8s_deployment.list',
'params' => ['cloud_context' => $cloud_server_template->getCloudContext()],
];
try {
$result = $this->k8sService->createDeployment(
$cloud_server_template->get('field_namespace')->value,
$params
);
$this->k8sService->updateDeployments([
'metadata.name' => $result['metadata']['name'],
], FALSE);
$this->messenger->addStatus($this->t('Deployment @name launched.', ['@name' => $result['metadata']['name']]));
}
catch (K8sServiceException $e) {
$message = $this->t('The @label "%label" could not be launched.', [
'@label' => $cloud_server_template->getEntityType()->getLabel(),
'%label' => $cloud_server_template->label(),
]);
$this->messenger->addError($message);
$route = [
'route_name' => 'entity.cloud_server_template.canonical',
'params' => [
'cloud_server_template' => $cloud_server_template->id(),
'cloud_context' => $cloud_server_template->getCloudContext(),
],
];
}
return $route;
}
/**
* Launch a K8s pod from a server template.
*
* @param \Drupal\cloud\Entity\CloudServerTemplateInterface $cloud_server_template
* Cloud server template interface.
*
* @return array
* The route to redirect after launch.
*/
private function launchPod(CloudServerTemplateInterface $cloud_server_template) {
$params = Yaml::decode($cloud_server_template->get('field_detail')->value);
$route = [
'route_name' => 'view.k8s_pod.list',
'params' => ['cloud_context' => $cloud_server_template->getCloudContext()],
];
try {
$result = $this->k8sService->createPod(
$cloud_server_template->get('field_namespace')->value,
$params
);
$this->k8sService->updatePods([
'metadata.name' => $result['metadata']['name'],
], FALSE);
// Update creation_yaml field of k8s_pod entity.
$entities = $this->entityTypeManager->getStorage('k8s_pod')->loadByProperties(
[
'cloud_context' => $cloud_server_template->getCloudContext(),
'name' => $result['metadata']['name'],
]
);
if (!empty($entities)) {
$entity = reset($entities);
$entity->setCreationYaml($cloud_server_template->get('field_detail')->value);
$entity->save();
}
$this->messenger->addStatus($this->t('Pod @name launched.', ['@name' => $result['metadata']['name']]));
}
catch (K8sServiceException $e) {
$message = $this->t('The @label "%label" could not be launched.', [
'@label' => $cloud_server_template->getEntityType()->getLabel(),
'%label' => $cloud_server_template->label(),
]);
$this->messenger->addError($message);
$route = [
'route_name' => 'entity.cloud_server_template.canonical',
'params' => [
'cloud_server_template' => $cloud_server_template->id(),
'cloud_context' => $cloud_server_template->getCloudContext(),
],
];
}
return $route;
}
}
