Repository: ansible-collections/amazon.aws

Issue:
Add support for OutpostArn in ec2_vol
##### SUMMARY
Add support for OutpostArn in ec2_vol.

##### ISSUE TYPE
- Feature Idea

##### COMPONENT NAME
Add a module option for OutpostArn in the ec2_vol module. When creating a volume in an Outposts the OutpostARN is needed.

##### ADDITIONAL INFORMATION
This option would allow to create volumes in Outposts 



Discussion:
Files identified in the description:
* [`plugins/modules/ec2_vol.py`](https://github.com/['ansible-collections/amazon.aws', 'ansible-collections/community.aws', 'ansible-collections/community.vmware']/blob/main/plugins/modules/ec2_vol.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @jillr @lwade @s-hertel @tremble @wimnat
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/plugins/module_utils/ec2.py b/plugins/module_utils/ec2.py
--- a/plugins/module_utils/ec2.py
+++ b/plugins/module_utils/ec2.py
@@ -742,3 +742,16 @@ def normalize_ec2_vpc_dhcp_config(option_config):
                 config_data[option] = [val['Value'] for val in config_item['Values']]
 
     return config_data
+
+
+def is_outposts_arn(input_regex):
+    """
+    Validates the provided regex pattern of outpost arn as per API specification document.
+
+    API Specification Document:
+    https://docs.aws.amazon.com/outposts/latest/APIReference/API_Outpost.html
+    """
+    regex_pattern = r'^arn:aws([a-z-]+)?:outposts:[a-z\d-]+:\d{12}:outpost/op-[a-f0-9]{17}$'
+    if not re.match(regex_pattern, input_regex):
+        return False
+    return True
diff --git a/plugins/modules/ec2_vol.py b/plugins/modules/ec2_vol.py
--- a/plugins/modules/ec2_vol.py
+++ b/plugins/modules/ec2_vol.py
@@ -111,6 +111,12 @@
       - This parameter is supported with io1 and io2 volumes only.
     type: bool
     version_added: 2.0.0
+  outpost_arn:
+    description:
+      - The Amazon Resource Name (ARN) of the Outpost.
+      - If set, allows to create volume in an Outpost.
+    type: str
+    version_added: 3.1.0
 author: "Lester Wade (@lwade)"
 extends_documentation_fragment:
 - amazon.aws.aws
@@ -262,6 +268,7 @@
 from ..module_utils.ec2 import ansible_dict_to_boto3_filter_list
 from ..module_utils.ec2 import describe_ec2_tags
 from ..module_utils.ec2 import ensure_ec2_tags
+from ..module_utils.ec2 import is_outposts_arn
 from ..module_utils.ec2 import AWSRetry
 from ..module_utils.core import is_boto3_error_code
 from ..module_utils.tagging import boto3_tag_specifications
@@ -459,6 +466,7 @@ def create_volume(module, ec2_conn, zone):
     snapshot = module.params.get('snapshot')
     throughput = module.params.get('throughput')
     multi_attach = module.params.get('multi_attach')
+    outpost_arn = module.params.get('outpost_arn')
     tags = module.params.get('tags')
     name = module.params.get('name')
 
@@ -495,6 +503,12 @@ def create_volume(module, ec2_conn, zone):
             if multi_attach:
                 additional_params['MultiAttachEnabled'] = True
 
+            if outpost_arn:
+                if is_outposts_arn(outpost_arn):
+                    additional_params['OutpostArn'] = outpost_arn
+                else:
+                    module.fail_json('OutpostArn does not match the pattern specified in API specifications.')
+
             if name:
                 tags['Name'] = name
 
@@ -713,6 +727,7 @@ def main():
         tags=dict(default={}, type='dict'),
         modify_volume=dict(default=False, type='bool'),
         throughput=dict(type='int'),
+        outpost_arn=dict(type='str'),
         purge_tags=dict(type='bool', default=False),
         multi_attach=dict(type='bool'),
     )


Test patch:
diff --git a/tests/unit/module_utils/test_ec2.py b/tests/unit/module_utils/test_ec2.py
--- a/tests/unit/module_utils/test_ec2.py
+++ b/tests/unit/module_utils/test_ec2.py
@@ -4,9 +4,12 @@
 # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
 
 from __future__ import (absolute_import, division, print_function)
+
+from plugins.module_utils.ec2 import is_outposts_arn
 __metaclass__ = type
 
 import unittest
+import pytest
 
 from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ansible_dict_to_boto3_filter_list
 from ansible_collections.amazon.aws.plugins.module_utils.ec2 import map_complex_type
@@ -76,3 +79,21 @@ def test_ansible_dict_with_integer_to_boto3_filter_list(self):
 
         converted_filters_int = ansible_dict_to_boto3_filter_list(filters)
         self.assertEqual(converted_filters_int, filter_list_integer)
+
+# ========================================================
+#   ec2.is_outposts_arn
+# ========================================================
+
+
+outpost_arn_test_inputs = [
+    ("arn:aws:outposts:us-east-1:123456789012:outpost/op-1234567890abcdef0", True),
+    ("arn:aws:outposts:us-east-1:123456789012:outpost/op-1234567890abcdef0123", False),
+    ("arn:aws:outpost:us-east-1: 123456789012:outpost/ op-1234567890abcdef0", False),
+    ("ars:aws:outposts:us-east-1: 123456789012:outpost/ op-1234567890abcdef0", False),
+    ("arn:was:outposts:us-east-1: 123456789012:outpost/ op-1234567890abcdef0", False),
+]
+
+
+@pytest.mark.parametrize("outpost_arn, result", outpost_arn_test_inputs)
+def test_is_outposts_arn(outpost_arn, result):
+    assert is_outposts_arn(outpost_arn) == result