diff --git a/modules/cloud_service_providers/aws_cloud/src/Plugin/AwsCloudServerTemplatePlugin.php b/modules/cloud_service_providers/aws_cloud/src/Plugin/AwsCloudServerTemplatePlugin.php index 390e32b..35fed36 100644 --- a/modules/cloud_service_providers/aws_cloud/src/Plugin/AwsCloudServerTemplatePlugin.php +++ b/modules/cloud_service_providers/aws_cloud/src/Plugin/AwsCloudServerTemplatePlugin.php @@ -105,10 +105,10 @@ class AwsCloudServerTemplatePlugin extends PluginBase implements CloudServerTemp $params['Placement']['AvailabilityZone'] = $cloud_server_template->get('field_availability_zone')->value; } - $params['SecurityGroup'] = []; + $params['SecurityGroups'] = []; foreach ($cloud_server_template->get('field_security_group') as $group) { if (isset($group->entity)) { - $params['SecurityGroup'][] = $group->entity->get('group_name')->value; + $params['SecurityGroups'][] = $group->entity->get('group_name')->value; } } diff --git a/modules/cloud_service_providers/aws_cloud/tests/src/Unit/Plugin/AwsCloudServerTemplatePluginTest.php b/modules/cloud_service_providers/aws_cloud/tests/src/Unit/Plugin/AwsCloudServerTemplatePluginTest.php new file mode 100644 index 0000000..50ead46 --- /dev/null +++ b/modules/cloud_service_providers/aws_cloud/tests/src/Unit/Plugin/AwsCloudServerTemplatePluginTest.php @@ -0,0 +1,228 @@ +mockAwsEc2Service = $this->getMockBuilder(AwsEc2ServiceInterface::class) + ->getMock(); + + $this->plugin = new AwsCloudServerTemplatePlugin( + [], '', [], + $this->mockAwsEc2Service, + $this->getMockBuilder(Messenger::class) + ->disableOriginalConstructor() + ->getMock(), + $this->getMock(EntityTypeManagerInterface::class) + ); + + $this->random = new Random(); + } + + /** + * Tests launching a instance. + */ + public function testLaunch() { + $random = $this->random; + + // Mock object of Image. + $mock_image = $this->getMock(ImageInterface::class); + $image_value_map = [ + ['image_id', (object)['value' => 'ami-' . $random->name(8, TRUE)]], + ['root_device_type', 'ebs'], + ]; + $mock_image->expects($this->any()) + ->method('get') + ->will($this->returnValueMap($image_value_map)); + + // Mock object of KeyPair. + $mock_ssh_key = $this->getMock(KeyPairInterface::class); + $ssh_key_value_map = [ + ['key_pair_name', (object)['value' => $random->name(8, TRUE)]], + ]; + $mock_ssh_key->expects($this->any()) + ->method('get') + ->will($this->returnValueMap($ssh_key_value_map)); + + // Mock object of NetworkInterface. + $mock_network = $this->getMock(NetworkInterfaceInterface::class); + $mock_network_value_map = [ + ['group_name', (object)['value' => $random->name(8, TRUE)]], + ]; + $mock_network->expects($this->any()) + ->method('subnet_id') + ->will($this->returnValueMap($mock_network_value_map)); + + $field_security_groups_test_cases = $this->createFieldSecurityGroupsTestCases(); + + // Run test cases. + foreach ($field_security_groups_test_cases as $field_security_groups_test_case) { + $mock_template = $this->getMock(CloudServerTemplateInterface::class); + $template_value_map = [ + ['field_test_only', (object)['value' => '1']], + ['field_image_id', (object)['entity' => $mock_image]], + ['field_max_count', (object)['value' => 1]], + ['field_min_count', (object)['value' => 1]], + ['field_monitoring', (object)['value' => '1']], + ['field_instance_type', (object)['value' => $random->name(5, TRUE)]], + ['field_ssh_key', (object)['entity' => $mock_ssh_key]], + ['field_kernel_id', (object)['value' => 'aki-' . $random->name(8, TRUE)]], + ['field_ram', (object)['value' => 'ari-' . $random->name(8, TRUE)]], + ['field_user_data', (object)['value' => $random->string(32, TRUE)]], + ['field_availability_zone', (object)['value' => $random->name(7, TRUE)]], + ['field_security_group', $this->extract_array_item($field_security_groups_test_case, 0)], + ['field_network', (object)['entity' => $mock_network]], + ['field_instance_shutdown_behavior', (object)['value' => '1']], + ]; + $mock_template->expects($this->any()) + ->method('get') + ->will($this->returnValueMap($template_value_map)); + + // Assert followings for the first argument of method runInstances, + // 1. Has key SecurityGroups, + // 2. Doesn't have key SecurityGroup, + // 3. Contains the array of group1 and group2. + $this->mockAwsEc2Service + ->expects($this->any()) + ->method('runInstances') + ->with($this->logicalAnd( + $this->arrayHasKey('SecurityGroups'), + $this->logicalNot($this->arrayHasKey('SecurityGroup')), + $this->contains($this->extract_array_item($field_security_groups_test_case, 1)) + )) + ->will($this->returnValue(TRUE)); + + $return = $this->plugin->launch( + $mock_template, + $this->getMock(FormStateInterface::class) + ); + $this->assertNotNull($return); + } + + } + + private function extract_array_item($array, $index) { + $extracted = []; + foreach ($array as $item) { + $extracted[] = $item[$index]; + } + + return $extracted; + } + + private function createFieldSecurityGroupsTestCases() { + $random = $this->random; + + $mock_security_group_and_names = []; + for ($i = 0; $i < MAX_SECURITY_GROUPS_COUNT; $i++) { + // Mock object of SecurityGroup. + $mock_security_group = $this->getMock(SecurityGroupInterface::class); + $group_name = $random->name(8, TRUE); + $mock_security_group_value_map[] = [ + ['group_name', (object)['value' => $group_name]], + ]; + $mock_security_group->expects($this->any()) + ->method('get') + ->will($this->returnValueMap($mock_security_group_value_map)); + + $mock_security_group_and_names[] = [$mock_security_group, $group_name]; + } + var_dump(count($mock_security_group_and_names)); + + $mock_security_group_and_names_exclude_first_last = array_slice( + $mock_security_group_and_names, + 1, + count($mock_security_group_and_names) - 2 + ); + + $field_security_groups_test_cases = []; + + // Test cases. + // Test when Security Groups has the only one item, the first item only. + $field_security_groups_test_cases[] = [reset($mock_security_group_and_names)]; + + // Test when Security Groups has more than two items. + if (MAX_SECURITY_GROUPS_COUNT > 1) { + + // The last item only. + $field_security_groups_test_cases[] = [end($mock_security_group_and_names)]; + + // The first item and the last one only. + $field_security_groups_test_cases[] = [ + reset($mock_security_group_and_names), + end($mock_security_group_and_names) + ]; + + if (MAX_SECURITY_GROUPS_COUNT > 2) { + + // Randomly picking up the only one item. + + $field_security_groups_test_cases[] = [ + // Pickup one index randomly (array index: 1 to the (last index -2)) + $mock_security_group_and_names_exclude_first_last[ + array_rand($mock_security_group_and_names_exclude_first_last) + ] + ]; + + $field_security_groups_test_cases[] = [ + reset($mock_security_group_and_names), + // Pickup one index randomly (array index: 1 to the (last index -2)) + $mock_security_group_and_names_exclude_first_last[ + array_rand($mock_security_group_and_names_exclude_first_last) + ], + ]; + + $field_security_groups_test_cases[] = [ + // Pickup one index randomly (array index: 1 to the (last index -2)) + $mock_security_group_and_names_exclude_first_last[ + array_rand($mock_security_group_and_names_exclude_first_last) + ], + end($mock_security_group_and_names), + ]; + + if (MAX_SECURITY_GROUPS_COUNT > 3) { + // Pickup one index randomly (array index: 1 to the (last index -2)) + // Pickup *another* one index randomly (array index: 1 to the (last index -2)) + $array_indice = array_rand($mock_security_group_and_names_exclude_first_last, 2); + $field_security_groups_test_cases[] = [ + $mock_security_group_and_names_exclude_first_last[ + $array_indice[0] + ], + $mock_security_group_and_names_exclude_first_last[ + $array_indice[1] + ], + ]; + } + } + } + + return $field_security_groups_test_cases; + } + +}