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

Issue #3313812 by Ryo Yamashita, yas: Add the SPA form and REST API to edit...

Issue #3313812 by Ryo Yamashita, yas: Add the SPA form and REST API to edit the AWS Cloud launch template in the Cloud module
parent df9689c2
Loading
Loading
Loading
Loading
+163 −0
Changes for modules/cloud_dashboard/cloud_dashboard/src/constant/form_template/launch_template/aws_cloud.ts: 163 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -175,6 +175,169 @@ const AWS_CLOUD_LAUNCH_TEMPLATE: EntityFormTemplate[] = [
    ],
    submitButtonLabel: 'Delete'
  },
  {
    cloudServiceProvider: 'aws_cloud',
    entityName: 'cloud_launch_template',
    actionType: 'edit',
    entityRecords: [
      {
        type: 'panel',
        panelName: 'Instance',
        keyValueRecords: [
          {
            type: 'default', labelName: 'Name', name: 'name',
            defaultValue: '', readOnly: true, required: true
          },
          {
            type: 'textarea', labelName: 'Description', name: 'field_description',
            defaultValue: ''
          },
          {
            type: 'select', labelName: 'Instance type', name: 'field_instance_type',
            url: '/cloud_dashboard/aws_cloud/{cloud_context}/instance_types',
            defaultValue: '', required: true
          },
          {
            type: 'select', labelName: 'IAM role', name: 'field_iam_role',
            url: '/cloud_dashboard/aws_cloud/{cloud_context}/iam_role_options',
            defaultValue: ''
          },
          {
            type: 'number', labelName: 'Min count', name: 'field_min_count',
            defaultValue: 1, required: true
          },
          {
            type: 'number', labelName: 'Max count', name: 'field_max_count',
            defaultValue: 1 
          },
          {
            type: 'boolean', labelName: 'Test only', name: 'field_test_only',
            defaultValue: false
          },
        ]
      },
      {
        type: 'panel',
        panelName: 'AMI',
        keyValueRecords: [
          {
            type: 'select', labelName: 'Image ID', name: 'field_image_id',
            url: '/cloud_dashboard/cloud/{cloud_context}/cloud_launch_template/image_options',
            defaultValue: '', required: true
          },
          {
            type: 'default', labelName: 'Kernel ID', name: 'field_kernel_id',
            defaultValue: '',
          },
          {
            type: 'default', labelName: 'Ramdisk ID', name: 'field_ram',
            defaultValue: '',
          },
        ]
      },
      {
        type: 'panel',
        panelName: 'Network',
        keyValueRecords: [
          {
            type: 'select', labelName: 'Availability Zone', name: 'field_availability_zone',
            url: '/cloud_dashboard/aws_cloud/{cloud_context}/availability_zone',
            defaultValue: '', required: true
          },
          {
            labelName: 'VPC', 'name': 'field_vpc', type: 'join', info: {
              entityTypeId: 'aws_cloud_vpc',
              keyColumn: 'vpc_id',
              label: '{name} ({vpc_id} | {cidr_block})',
            }, defaultValue: '', required: true
          },
          {
            type: 'select', labelName: 'Subnet', name: 'field_subnet',
            url: '/cloud_dashboard/aws_cloud/{cloud_context}/aws_cloud_network_interface/subnet_options',
            defaultValue: '', required: true
          },
          {
            type: 'multi-select', labelName: 'Security groups', name: 'security_groups',
            url: '/cloud_dashboard/aws_cloud/{cloud_context}/aws_cloud_network_interface/security_group_options/{subnet_id}',
            defaultValue: ["{tryNotNull(getValue(aws_cloud_security_group,relationship(field_security_group,drupal_internal__target_id),drupal_internal__id,name),'')}"],
            required: true
          },
          {
            type: 'join', labelName: 'SSH key', name: 'ssh_key', info: {
              entityTypeId: 'aws_cloud_key_pair',
              keyColumn: 'key_pair_name',
              label: '{key_pair_name}'
            },
            defaultValue: "{tryNotNull(getValue(aws_cloud_key_pair,relationship(field_ssh_key,drupal_internal__target_id),drupal_internal__id,key_pair_name),'')}",
            required: true
          },
          {
            type: 'select', labelName: 'Network interface', name: 'network_interface_id',
            url: '/cloud_dashboard/aws_cloud/{cloud_context}/aws_cloud_elastic_ip/{entity_id}/unassociated_network_interface_ids',
            defaultValue: "{tryNotNull(relationship(field_security_group,drupal_internal__target_id), '')}"
          },
        ]
      },
      {
        type: 'panel',
        panelName: 'Tags',
        keyValueRecords: [
          {
            type: 'key-value', labelName: 'Tags', name: 'field_tags',
            defaultValue: []
          },
        ]
      },
      {
        type: 'panel',
        panelName: 'Workflow',
        keyValueRecords: [
          { type: 'select-local', name: 'field_workflow_status', labelName: 'Status', defaultValue: 'Draft', value: [
            { name: 'Draft', labelName: 'Draft' },
            { name: 'Review', labelName: 'Review' },
            { name: 'Approved', labelName: 'Approved' },
          ], required: true },
        ]
      },
      {
        type: 'panel',
        panelName: 'Option',
        keyValueRecords: [
          { type: 'select-local', name: 'field_instance_shutdown_behavior', labelName: 'Instance shutdown behavior', defaultValue: 'stop', value: [
            { name: 'stop', labelName: 'Stop' },
            { name: 'terminate', labelName: 'Terminate' },
          ]},
          {
            type: 'boolean', labelName: 'Termination protection', name: 'field_termination_protection',
            defaultValue: false
          },
          {
            type: 'boolean', labelName: 'Monitoring', name: 'field_monitoring',
            defaultValue: false
          },
          {
            type: 'select', labelName: 'Schedule', name: 'field_schedule',
            url: '/cloud_dashboard/schedule_options',
            defaultValue: '',
          },
          {
            type: 'textarea', labelName: 'User data', name: 'field_user_data',
            defaultValue: ''
          },
        ]
      },
      {
        type: 'panel',
        panelName: 'Others',
        keyValueRecords: [
          {
            type: 'textarea', labelName: 'Revision log message', name: 'revision_log_message',
            defaultValue: ''
          },
        ]
      }
    ]
  },
  {
    cloudServiceProvider: 'aws_cloud',
    entityName: 'cloud_launch_template',
+4 −0
Changes for modules/cloud_service_providers/aws_cloud/src/Controller/Ec2/ApiController.php: 4 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -1265,6 +1265,10 @@ class ApiController extends ControllerBase implements ApiControllerInterface {
          $method_name = 'copyCloudLaunchTemplate';
          break;

        case 'edit_aws_cloud_cloud_launch_template':
          $method_name = 'editCloudLaunchTemplate';
          break;

        case 'review_aws_cloud_cloud_launch_template':
          $method_name = 'reviewCloudLaunchTemplate';
          break;
+146 −5
Changes for modules/cloud_service_providers/aws_cloud/src/Service/AwsCloud/AwsCloudOperationsService.php: 146 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -3815,10 +3815,31 @@ class AwsCloudOperationsService implements AwsCloudOperationsServiceInterface {
   * {@inheritdoc}
   */
  public function copyCloudLaunchTemplate(CloudLaunchTemplateInterface $entity, array &$form, FormStateInterface $form_state): bool {
    try {
      $this->alterCloudLaunchTemplateCopyForm($entity, $form, $form_state, NULL);
    $this->submitCloudLaunchTemplateCopyForm($entity, $form, $form_state);
      return $this->submitCloudLaunchTemplateCopyForm($entity, $form, $form_state);
    }
    catch (\Exception $e) {
      $this->handleException($e);
      $this->processOperationErrorStatus($entity, 'copied');
      return FALSE;
    }
  }

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

  /**
   * {@inheritdoc}
@@ -4870,14 +4891,17 @@ class AwsCloudOperationsService implements AwsCloudOperationsServiceInterface {
   *   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) {
  private function submitCloudLaunchTemplateCopyForm(CloudLaunchTemplateInterface $entity, array &$form, FormStateInterface $form_state): bool {
    $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);
    return $this->submitCloudLaunchTemplateAddForm($entity, $form, $form_state);
  }

  /**
@@ -4889,8 +4913,11 @@ class AwsCloudOperationsService implements AwsCloudOperationsServiceInterface {
   *   Array of form object.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current form state.
   *
   * @return bool
   *   TRUE when the process succeeds.
   */
  private function submitCloudLaunchTemplateAddForm(CloudLaunchTemplateInterface $entity, array &$form, FormStateInterface $form_state) {
  private function submitCloudLaunchTemplateAddForm(CloudLaunchTemplateInterface $entity, array &$form, FormStateInterface $form_state): bool {
    $ec2_service = \Drupal::service('aws_cloud.ec2');
    $cloud_context = $entity->getCloudContext();
    $ec2_service->setCloudContext($cloud_context);
@@ -4921,10 +4948,124 @@ class AwsCloudOperationsService implements AwsCloudOperationsServiceInterface {
          'cloud_launch_template' => $entity->id(),
        ]
      );
      return TRUE;
    }
    else {

    \Drupal::service('cloud')->processOperationErrorStatus($entity, 'created');
    return FALSE;
  }

  /**
   * 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 alterCloudLaunchTemplateEditForm(CloudLaunchTemplateInterface $entity, array &$form, FormStateInterface $form_state) {
    $this->alterCloudLaunchTemplateCommonForm($entity, $form, $form_state);

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

    // Disable name field.
    $form['instance']['name']['#disabled'] = TRUE;

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

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

    $entity_storage = \Drupal::entityTypeManager()
      ->getStorage('cloud_launch_template');
    /** @var \Drupal\cloud\Entity\CloudLaunchTemplateInterface $template_storage */
    $template_storage = $entity_storage->loadRevision($server_template->getRevisionId());

    if (!empty($server_template)
    && !empty($server_template->get('field_workflow_status'))
    && !empty($template_storage)
    && !empty($template_storage->get('field_workflow_status'))
    && $template_storage->get('field_workflow_status')->value === CloudLaunchTemplateInterface::APPROVED
    && aws_cloud_launch_template_edit_is_changed($server_template, $template_storage)) {
      $server_template->get('field_workflow_status')->setValue(CloudLaunchTemplateInterface::DRAFT);
      $server_template->validate();
    }

    if (!empty($server_template)
    && !empty($server_template->get('field_workflow_status'))
    && !empty($template_storage)
    && !empty($template_storage->get('field_workflow_status'))) {
      \Drupal::service('cloud')->notifyLaunchTemplateWorkflowStatusChanged('aws_cloud', $server_template, $template_storage->get('field_workflow_status')->value);
    }

    $ec2_service = \Drupal::service('aws_cloud.ec2');
    $cloud_context = $server_template->getCloudContext();
    $ec2_service->setCloudContext($cloud_context);

    // Always create a new revision.
    $server_template->setRevisionUserId(\Drupal::currentUser()->id());
    $server_template->setNewRevision(TRUE);

    $params = [];
    $params['LaunchTemplateName'] = $server_template->getName();
    $params['VersionDescription'] = $server_template->getRevisionLogMessage();
    $params['LaunchTemplateData'] = aws_cloud_get_launch_template_data($server_template);
    $result = $ec2_service->createLaunchTemplateVersion($params);

    $success = isset($result['LaunchTemplateVersion']);
    if ($success) {
      aws_cloud_launch_template_update_field_tags($server_template, $params['LaunchTemplateData']);

      $version = $result['LaunchTemplateVersion']['VersionNumber'];
      $server_template->set('field_version', $version);

      // Set default version.
      $params = [];
      $params['LaunchTemplateName'] = $server_template->getName();
      $params['DefaultVersion'] = $version;
      // Set the revision creation time using `CreateTime` from results.
      $server_template->setRevisionCreationTime(strtotime($result['LaunchTemplateVersion']['CreateTime']));

      $ec2_service->modifyLaunchTemplate($params);
    }

    if ($success && $server_template->save()) {
      aws_cloud_dispatch_event(new CloudEntityEvent($server_template, CloudEntityEventType::FORM_SUBMIT));
      \Drupal::service('cloud')->processOperationStatus($server_template, 'updated');

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

    \Drupal::service('cloud')->processOperationErrorStatus($server_template, 'updated');
    return FALSE;
  }

}
+15 −0
Changes for modules/cloud_service_providers/aws_cloud/src/Service/AwsCloud/AwsCloudOperationsServiceInterface.php: 15 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -1172,6 +1172,21 @@ interface AwsCloudOperationsServiceInterface {
   */
  public function copyCloudLaunchTemplate(CloudLaunchTemplateInterface $entity, array &$form, FormStateInterface $form_state): bool;

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

  /**
   * Review CloudLaunchTemplate.
   *