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

Issue #3311749 by Ryo Yamashita, yas: Add a REST API to copy the AWS Cloud...

Issue #3311749 by Ryo Yamashita, yas: Add a REST API to copy the AWS Cloud launch template in the Cloud module
parent bad6140f
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -1261,6 +1261,9 @@ class ApiController extends ControllerBase implements ApiControllerInterface {
          $method_name = 'editInternetGateway';
          break;

        case 'copy_aws_cloud_cloud_launch_template':
          $method_name = 'copyCloudLaunchTemplate';
          break;
      }
    }
    catch (\JsonException $e) {
@@ -2085,6 +2088,7 @@ class ApiController extends ControllerBase implements ApiControllerInterface {

    $options = [];
    foreach ($gateways as $gateway) {
      /** @var \Drupal\aws_cloud\Entity\Vpc\InternetGateway $gateway */
      if (empty($gateway->getVpcId())) {
        continue;
      }
+5 −0
Original line number Diff line number Diff line
@@ -17,6 +17,11 @@ interface VpcPeeringConnectionInterface extends ContentEntityInterface, EntityOw
   */
  public function getCloudContext(): ?string;

  /**
   * {@inheritdoc}
   */
  public function getName(): ?string;

  /**
   * Get the VPC peering connection ID.
   */
+180 −0
Original line number Diff line number Diff line
@@ -25,6 +25,9 @@ use Drupal\aws_cloud\Service\Ec2\Ec2ServiceInterface;
use Drupal\aws_cloud\Traits\AwsCloudEntityCheckTrait;
use Drupal\cloud\Entity\CloudConfig;
use Drupal\cloud\Entity\CloudConfigInterface;
use Drupal\cloud\Entity\CloudLaunchTemplateInterface;
use Drupal\cloud\Event\CloudEntityEvent;
use Drupal\cloud\Event\CloudEntityEventType;
use Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface;
use Drupal\cloud\Service\CloudServiceInterface;
use Drupal\cloud\Service\EntityLinkRendererInterface;
@@ -1181,6 +1184,7 @@ class AwsCloudOperationsService implements AwsCloudOperationsServiceInterface {
        ->getStorage('aws_cloud_vpc')
        ->resetCache([$entity->id()]);

      /** @var \Drupal\aws_cloud\Entity\Vpc\VpcInterface $old_vpc */
      $old_vpc = $this->entityTypeManager
        ->getStorage('aws_cloud_vpc')
        ->load($entity->id());
@@ -3806,6 +3810,15 @@ class AwsCloudOperationsService implements AwsCloudOperationsServiceInterface {
    return TRUE;
  }

  /**
   * {@inheritdoc}
   */
  public function copyCloudLaunchTemplate(CloudLaunchTemplateInterface $entity, array &$form, FormStateInterface $form_state): bool {
    $this->alterCloudLaunchTemplateCopyForm($entity, $form, $form_state, NULL);
    $this->submitCloudLaunchTemplateCopyForm($entity, $form, $form_state);
    return FALSE;
  }

  /**
   * Save a cloud content.
   *
@@ -4677,6 +4690,7 @@ class AwsCloudOperationsService implements AwsCloudOperationsServiceInterface {
      return $snapshot_name;
    }

    /** @var \Drupal\aws_cloud\Entity\Ec2\SnapshotInterface[] $snapshots */
    $snapshots = $this->entityTypeManager
      ->getStorage("{$module_name}_snapshot")
      ->loadByProperties([
@@ -4708,4 +4722,170 @@ class AwsCloudOperationsService implements AwsCloudOperationsServiceInterface {
      || $old_volume->getIops() !== $new_volume->getIops();
  }

  /**
   * Common alter function for edit and add forms.
   *
   * @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 alterCloudLaunchTemplateCommonForm(CloudLaunchTemplateInterface $entity, array &$form, FormStateInterface $form_state) {
    \Drupal::service('cloud')->reorderForm($form, aws_cloud_launch_template_field_orders());

    $form['instance']['field_iam_role']['widget']['#options']['_none'] = $this->t('No Role');

    $form['instance']['field_instance_type']['widget']['#ajax'] = [
      'callback' => 'aws_cloud_ajax_callback_get_image_ids',
    ];

    $form['ami']['field_image_id']['widget']['#ajax'] = [
      'callback' => 'aws_cloud_ajax_callback_get_instance_types',
    ];

    $form['network']['field_vpc']['widget']['#ajax'] = [
      'callback' => 'aws_cloud_ajax_callback_get_fields',
    ];

    $vpc_id = '_none';
    if (!empty($form['network']['field_vpc']['widget']['#default_value'])) {
      $vpc_id = $form['network']['field_vpc']['widget']['#default_value'][0];
    }

    // If validation happened, we should get vpc_id from user input.
    $user_input = $form_state->getUserInput();
    if (isset($user_input['field_vpc'])) {
      $vpc_id = $user_input['field_vpc'];
    }

    /** @var \Drupal\Core\Entity\EntityFormInterface $form_object */
    $form_object = $form_state->getFormObject();
    $server_template = $entity->createDuplicate();
    $form_object->setEntity($server_template);
    $subnet_options = aws_cloud_get_subnet_options_by_vpc_id($vpc_id, $form_object->getEntity());
    $form['#attached']['library'][] = 'aws_cloud/aws_cloud_form';
    $form['#attached']['drupalSettings']['aws_cloud']['field_subnet_default_values']
      = array_keys($subnet_options);

    $security_group_options = aws_cloud_get_security_group_options_by_vpc_id($vpc_id, $form_object->getEntity());
    $security_group_default_values = [];
    foreach ($security_group_options ?: [] as $id => $security_group_option) {
      $security_group_default_values[] = (string) $id;
    }

    $form['#attached']['drupalSettings']['aws_cloud']['field_security_group_default_values']
      = $security_group_default_values;

    $config = \Drupal::config('aws_cloud.settings');
    $form['#attached']['drupalSettings']['aws_cloud']['aws_cloud_instance_type_cost']
      = $config->get('aws_cloud_instance_type_cost');

    // Hide labels of field_tags.
    $form['tags']['field_tags']['widget']['#title'] = NULL;
  }

  /**
   * 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] = 'aws_cloud_form_cloud_launch_template_aws_cloud_copy_form_submit';
  }

  /**
   * Submit function for form cloud_launch_template_aws_cloud_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.
   */
  private function submitCloudLaunchTemplateCopyForm(CloudLaunchTemplateInterface $entity, array &$form, FormStateInterface $form_state) {
    $server_template = $entity->createDuplicate();
    /** @var \Drupal\Core\Entity\EntityFormInterface $form_object */
    $form_object = $form_state->getFormObject();
    $form_object->setEntity($server_template);

    $this->submitCloudLaunchTemplateAddForm($entity, $form, $form_state);
  }

  /**
   * Submit function for form cloud_launch_template_aws_cloud_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.
   */
  private function submitCloudLaunchTemplateAddForm(CloudLaunchTemplateInterface $entity, array &$form, FormStateInterface $form_state) {
    $ec2_service = \Drupal::service('aws_cloud.ec2');
    $cloud_context = $entity->getCloudContext();
    $ec2_service->setCloudContext($cloud_context);

    $params = [];
    $params['LaunchTemplateName'] = $entity->getName();
    $params['VersionDescription'] = $entity->getRevisionLogMessage();
    $params['LaunchTemplateData'] = aws_cloud_get_launch_template_data($entity);

    $result = $ec2_service->createLaunchTemplate($params);
    $success = isset($result['LaunchTemplate']);
    if ($success) {
      aws_cloud_launch_template_update_field_tags($entity, $params['LaunchTemplateData']);
      $entity->set('field_version', $result['LaunchTemplate']['LatestVersionNumber']);
    }

    if ($success && $entity->save()
    ) {

      aws_cloud_dispatch_event(new CloudEntityEvent($entity, CloudEntityEventType::FORM_SUBMIT));

      \Drupal::service('cloud')->processOperationStatus($entity, 'created');

      $form_state->setRedirect(
        'entity.cloud_launch_template.canonical',
        [
          'cloud_context' => $cloud_context,
          'cloud_launch_template' => $entity->id(),
        ]
      );
    }
    else {
      \Drupal::service('cloud')->processOperationErrorStatus($entity, 'created');
    }
  }

}
+16 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ use Drupal\aws_cloud\Entity\Vpc\SubnetInterface;
use Drupal\aws_cloud\Entity\Vpc\TransitGatewayInterface;
use Drupal\aws_cloud\Entity\Vpc\VpcInterface;
use Drupal\aws_cloud\Entity\Vpc\VpcPeeringConnectionInterface;
use Drupal\cloud\Entity\CloudLaunchTemplateInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\FieldItemList;
@@ -1156,4 +1157,19 @@ interface AwsCloudOperationsServiceInterface {
   */
  public function detachInternetGateway(InternetGatewayInterface $entity, array &$form, FormStateInterface $form_state): bool;

  /**
   * Copy 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 copyCloudLaunchTemplate(CloudLaunchTemplateInterface $entity, array &$form, FormStateInterface $form_state): bool;

}