Repository: ansible-collections/community.general

Issue:
Allow tags to be supplied to proxmox_lxc
### Summary

Tags have been added to `proxmox_qemu` (see #1989) ; at the time, there was [a bug](https://forum.proxmox.com/threads/api-parse-errors-when-lxc-tags-are-null.85197/) with LXC tags. 

From what I can tell, the bug has been fixed on proxmox 7 - I don't have a proxmox 6 node to test, but it should be fixed too (at least according to proxmox developer on the forum). So I think we can finally add tags to LXC :)

Looking at the MR(#2000), the code change seems straightforward, so I can provide a PR if needed

Cheers,

### Issue Type

Feature Idea

### Component Name

proxmox module

### Additional Information

_No response_

### Code of Conduct

- [X] I agree to follow the Ansible Code of Conduct


Discussion:
Files identified in the description:
* [`plugins/modules/proxmox.py`](https://github.com/ansible-collections/community.general/blob/main/plugins/modules/proxmox.py)

If these files are incorrect, 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/devel/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @Ajpantuso @Thulium-Drake @UnderGreen @joshainglis @karmab @tleguern
[click here for bot help](https://github.com/ansible/ansibullbot/blob/devel/ISSUE_HELP.md)
<!--- boilerplate: notify --->
hi @GuillaumeV-cemea thanks for reporting this request. A PR would be very welcome, and we would be happy to review it.

Resolving patch:
diff --git a/plugins/modules/proxmox.py b/plugins/modules/proxmox.py
--- a/plugins/modules/proxmox.py
+++ b/plugins/modules/proxmox.py
@@ -106,6 +106,14 @@
     description:
       - sets DNS search domain for a container
     type: str
+  tags:
+    description:
+      - List of tags to apply to the container.
+      - Tags must start with C([a-z0-9_]) followed by zero or more of the following characters C([a-z0-9_-+.]).
+      - Tags are only available in Proxmox 7+.
+    type: list
+    elements: str
+    version_added: 6.2.0
   timeout:
     description:
       - timeout for operations
@@ -391,6 +399,7 @@
     state: absent
 '''
 
+import re
 import time
 
 from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
@@ -415,11 +424,25 @@ def is_template_container(self, node, vmid):
         return config['template']
 
     def create_instance(self, vmid, node, disk, storage, cpus, memory, swap, timeout, clone, **kwargs):
+
+        # Version limited features
+        minimum_version = {
+            'tags': 7,
+        }
         proxmox_node = self.proxmox_api.nodes(node)
 
         # Remove all empty kwarg entries
         kwargs = dict((k, v) for k, v in kwargs.items() if v is not None)
 
+        version = self.version()
+        pve_major_version = 3 if version < LooseVersion('4.0') else version.version[0]
+
+        # Fail on unsupported features
+        for option, version in minimum_version.items():
+            if pve_major_version < version and option in kwargs:
+                self.module.fail_json(changed=False, msg="Feature {option} is only supported in PVE {version}+, and you're using PVE {pve_major_version}".
+                                      format(option=option, version=version, pve_major_version=pve_major_version))
+
         if VZ_TYPE == 'lxc':
             kwargs['cpulimit'] = cpus
             kwargs['rootfs'] = disk
@@ -437,6 +460,14 @@ def create_instance(self, vmid, node, disk, storage, cpus, memory, swap, timeout
             kwargs['cpus'] = cpus
             kwargs['disk'] = disk
 
+        # LXC tags are expected to be valid and presented as a comma/semi-colon delimited string
+        if 'tags' in kwargs:
+            re_tag = re.compile(r'^[a-z0-9_][a-z0-9_\-\+\.]*$')
+            for tag in kwargs['tags']:
+                if not re_tag.match(tag):
+                    self.module.fail_json(msg='%s is not a valid tag' % tag)
+            kwargs['tags'] = ",".join(kwargs['tags'])
+
         if clone is not None:
             if VZ_TYPE != 'lxc':
                 self.module.fail_json(changed=False, msg="Clone operator is only supported for LXC enabled proxmox clusters.")
@@ -569,6 +600,7 @@ def main():
         proxmox_default_behavior=dict(type='str', default='no_defaults', choices=['compatibility', 'no_defaults']),
         clone=dict(type='int'),
         clone_type=dict(default='opportunistic', choices=['full', 'linked', 'opportunistic']),
+        tags=dict(type='list', elements='str')
     )
     module_args.update(proxmox_args)
 
@@ -674,7 +706,8 @@ def main():
                                     features=",".join(module.params['features']) if module.params['features'] is not None else None,
                                     unprivileged=ansible_to_proxmox_bool(module.params['unprivileged']),
                                     description=module.params['description'],
-                                    hookscript=module.params['hookscript'])
+                                    hookscript=module.params['hookscript'],
+                                    tags=module.params['tags'])
 
             module.exit_json(changed=True, msg="Deployed VM %s from template %s" % (vmid, module.params['ostemplate']))
         except Exception as e:


Test patch: