Commit cb9a5a84 authored by Ryo Yamashita's avatar Ryo Yamashita Committed by Yas Naoi
Browse files

Issue #3318463 by Ryo Yamashita, yas: Add REST API to copy the OpenStack...

Issue #3318463 by Ryo Yamashita, yas: Add REST API to copy the OpenStack launch template in the Cloud module
parent 21e72874
Loading
Loading
Loading
Loading
+14 −0
Changes for modules/cloud_service_providers/openstack/openstack.routing.yml: 14 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -1033,6 +1033,20 @@ entity.openstack_volume.instances:
  requirements:
    _custom_access: '\Drupal\openstack\Controller\ApiController::access'

entity.openstack_cloud_launch_template.copy:
  path: '/cloud_dashboard/openstack/{cloud_context}/cloud_launch_template/{entity_id}/copy'
  defaults:
    _controller: '\Drupal\openstack\Controller\ApiController::operateEntity'
    entity_type_id: cloud_launch_template
    command: copy
  methods: [POST]
  requirements:
    # Use custom access that will check for cloud_context and the desired permission.
    # Desired permission is passed as an option in the "perm" variable
    _custom_access: '\Drupal\cloud\Controller\CloudConfigController::access'
  options:
    perm: 'edit any cloud server templates+edit own cloud server templates'

entity.openstack_cloud_launch_template.edit:
  path: '/cloud_dashboard/openstack/{cloud_context}/cloud_launch_template/{entity_id}/edit'
  defaults:
+4 −0
Changes for modules/cloud_service_providers/openstack/src/Controller/ApiController.php: 4 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -713,6 +713,10 @@ class ApiController extends ControllerBase implements ApiControllerInterface {
        $method_name = 'detachOpenStackVolume';
        break;

      case 'copy_openstack_cloud_launch_template':
        $method_name = 'copyOpenStackCloudLaunchTemplate';
        break;

      case 'edit_openstack_cloud_launch_template':
        $method_name = 'editOpenStackCloudLaunchTemplate';
        break;
+123 −2
Changes for modules/cloud_service_providers/openstack/src/Service/OpenStackOperationsService.php: 123 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\Messenger;
use Drupal\Core\Render\Markup;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\openstack\Entity\OpenStackNetworkExInterface;
use Drupal\openstack\Entity\OpenStackPortInterface;
use Drupal\openstack\Entity\OpenStackRouterInterface;
@@ -42,6 +43,7 @@ class OpenStackOperationsService implements OpenStackOperationsServiceInterface
  use AwsCloudEntityCheckTrait;
  use CloudContentEntityTrait;
  use EntityDeleteFormTrait;
  use StringTranslationTrait;

  public const SECURITY_GROUP_DELIMITER = ', ';

@@ -1190,7 +1192,9 @@ class OpenStackOperationsService implements OpenStackOperationsServiceInterface
    ];

    $this->ec2Service->setCloudContext($entity->getCloudContext());
    $result = $this->ec2Service->removeRouterInterface($params);
    /** @var \Drupal\openstack\Service\Rest\OpenStackService $ec2_service */
    $ec2_service = $this->ec2Service;
    $result = $ec2_service->removeRouterInterface($params);

    if ($result === NULL) {
      $this->processOperationErrorStatus($entity, 'removed an interface');
@@ -1203,7 +1207,9 @@ class OpenStackOperationsService implements OpenStackOperationsServiceInterface
    }

    // Update the Port entity.
    $this->ec2Service->updatePorts([
    /** @var \Drupal\openstack\Service\Rest\OpenStackService $ec2_service */
    $ec2_service = $this->ec2Service;
    $ec2_service->updatePorts([
      'PortId' => $result['PortId'],
    ]);

@@ -3053,4 +3059,119 @@ class OpenStackOperationsService implements OpenStackOperationsServiceInterface
    return TRUE;
  }

  /**
   * Implements hook_form_FORM_ID_alter().
   *
   * @param \Drupal\cloud\Entity\CloudLaunchTemplateInterface $entity
   *   The CloudLaunchTemplate entity.
   * @param array $form
   *   Array of form object.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current form state.
   */
  private function alterCloudLaunchTemplateCopyForm(CloudLaunchTemplateInterface $entity, array &$form, FormStateInterface $form_state) {
    $this->alterCloudLaunchTemplateCommonForm($entity, $form, $form_state);

    // Change name for copy.
    $name = $form['instance']['name']['widget'][0]['value']['#default_value'];
    $form['instance']['name']['widget'][0]['value']['#default_value'] = $this->t('copy_of_@name',
    [
      '@name' => $name,
    ]);

    // Hide new revision checkbox.
    $form['new_revision']['#access'] = FALSE;

    // Clear the revision log message.
    $form['others']['revision_log_message']['widget'][0]['value']['#default_value'] = NULL;

    // Change value of the submit button.
    $form['actions']['submit']['#value'] = $this->t('Copy');

    // Delete the delete button.
    $form['actions']['delete']['#access'] = FALSE;

    // Overwrite function ::save.
    $form['actions']['submit']['#submit'][1] = 'openstack_form_cloud_launch_template_openstack_copy_form_submit';
  }

  /**
   * Submit function for form cloud_launch_template_openstack_copy_form.
   *
   * @param \Drupal\cloud\Entity\CloudLaunchTemplateInterface $entity
   *   The CloudLaunchTemplate entity.
   * @param array $form
   *   Array of form object.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current form state.
   *
   * @return bool
   *   TRUE when the process succeeds.
   */
  private function submitCloudLaunchTemplateCopyForm(CloudLaunchTemplateInterface $entity, array &$form, FormStateInterface $form_state): bool {
    /** @var \Drupal\Core\Entity\EntityFormInterface $form_object */
    $form_object = $form_state->getFormObject();
    /** @var \Drupal\cloud\Entity\CloudLaunchTemplateInterface $server_template */
    $server_template = $form_object->getEntity();

    $cloud_context = $server_template->getCloudContext();

    $server_template = $server_template->createDuplicate();
    $form_object->setEntity($server_template);

    $is_ec2_service = $this->openStackServiceFactory->isEc2ServiceType('cloud_config', $cloud_context);
    if (empty($is_ec2_service)) {
      $form_values = $form_state->getValues();
      $uid = $form_values['uid'][0]['target_id'] ?? 0;
      /** @var \Drupal\openstack\Service\OpenStackServiceInterface|\Drupal\cloud\Service\CloudResourceTagInterface $openstack_service */
      $openstack_service = $this->openStackServiceFactory->get($cloud_context);
      $uid_key_name = $openstack_service->getTagKeyCreatedByUid(
        'openstack',
        $cloud_context,
        $uid
      );

      $form_tags = ($server_template->hasField('field_tags') && !$server_template->get('field_tags')->isEmpty())
        ? $server_template->get('field_tags')->getValue() : [];

      // Update tags if authored id is changed.
      foreach ($form_tags ?: [] as $form_tag) {
        $item_key = $form_tag['item_key'];
        if ($form_tag['item_key'] === $uid_key_name) {
          $tags[] = ['item_key' => $item_key, 'item_value' => $uid];
        }
      }

      $server_template->set('field_tags', $tags);
    }
    $server_template->save();

    $this->processOperationStatus($server_template, 'created');

    $form_state->setRedirect(
      'entity.cloud_launch_template.canonical',
      [
        'cloud_context' => $cloud_context,
        'cloud_launch_template' => $server_template->id(),
      ]
    );

    return TRUE;
  }

  /**
   * {@inheritdoc}
   */
  public function copyOpenStackCloudLaunchTemplate(CloudLaunchTemplateInterface $entity, array &$form, FormStateInterface $form_state): bool {
    try {
      $this->alterCloudLaunchTemplateCopyForm($entity, $form, $form_state);
      return $this->submitCloudLaunchTemplateCopyForm($entity, $form, $form_state);
    }
    catch (\Exception $e) {
      $this->handleException($e);
      $this->processOperationErrorStatus($entity, 'edited');
      return FALSE;
    }
  }

}
+15 −0
Changes for modules/cloud_service_providers/openstack/src/Service/OpenStackOperationsServiceInterface.php: 15 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -731,6 +731,21 @@ interface OpenStackOperationsServiceInterface {
   */
  public function detachOpenStackVolume(VolumeInterface $entity, array &$form, FormStateInterface $form_state): bool;

  /**
   * Copy an OpenStack CloudLaunchTemplate.
   *
   * @param \Drupal\cloud\Entity\CloudLaunchTemplateInterface $entity
   *   The CloudLaunchTemplate entity.
   * @param array $form
   *   Array of form object.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current form state.
   *
   * @return bool
   *   TRUE when the process succeeds.
   */
  public function copyOpenStackCloudLaunchTemplate(CloudLaunchTemplateInterface $entity, array &$form, FormStateInterface $form_state): bool;

  /**
   * Edit an OpenStack CloudLaunchTemplate.
   *