VMware: Handle user unauthorization in tagging scenarios (#58405)
Handle unauthorization scenarios in VMware tagging APIs. Fixes: #58326 Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
This commit is contained in:
parent
242f160747
commit
e2d159c40c
5 changed files with 76 additions and 18 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- Handle user unauthorization errors in VMware REST API code for tagging (https://github.com/ansible/ansible/issues/58326).
|
|
@ -29,6 +29,7 @@ VSPHERE_IMP_ERR = None
|
||||||
try:
|
try:
|
||||||
from com.vmware.vapi.std_client import DynamicID
|
from com.vmware.vapi.std_client import DynamicID
|
||||||
from vmware.vapi.vsphere.client import create_vsphere_client
|
from vmware.vapi.vsphere.client import create_vsphere_client
|
||||||
|
from com.vmware.vapi.std.errors_client import Unauthorized
|
||||||
HAS_VSPHERE = True
|
HAS_VSPHERE = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
VSPHERE_IMP_ERR = traceback.format_exc()
|
VSPHERE_IMP_ERR = traceback.format_exc()
|
||||||
|
@ -49,6 +50,22 @@ class VmwareRestClient(object):
|
||||||
self.check_required_library()
|
self.check_required_library()
|
||||||
self.api_client = self.connect_to_vsphere_client()
|
self.api_client = self.connect_to_vsphere_client()
|
||||||
|
|
||||||
|
# Helper function
|
||||||
|
def get_error_message(self, error):
|
||||||
|
"""
|
||||||
|
Helper function to show human readable error messages.
|
||||||
|
"""
|
||||||
|
err_msg = []
|
||||||
|
if not error.messages:
|
||||||
|
if isinstance(error, Unauthorized):
|
||||||
|
return "Authorization required."
|
||||||
|
return "Generic error occurred."
|
||||||
|
|
||||||
|
for err in error.messages:
|
||||||
|
err_msg.append(err.default_message % err.args)
|
||||||
|
|
||||||
|
return " ,".join(err_msg)
|
||||||
|
|
||||||
def check_required_library(self):
|
def check_required_library(self):
|
||||||
"""
|
"""
|
||||||
Check required libraries
|
Check required libraries
|
||||||
|
|
|
@ -119,6 +119,7 @@ from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils.vmware_rest_client import VmwareRestClient
|
from ansible.module_utils.vmware_rest_client import VmwareRestClient
|
||||||
try:
|
try:
|
||||||
from com.vmware.cis.tagging_client import CategoryModel
|
from com.vmware.cis.tagging_client import CategoryModel
|
||||||
|
from com.vmware.vapi.std.errors_client import Error
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -159,7 +160,11 @@ class VmwareCategory(VmwareRestClient):
|
||||||
|
|
||||||
category_spec.associable_types = set()
|
category_spec.associable_types = set()
|
||||||
|
|
||||||
|
try:
|
||||||
category_id = self.category_service.create(category_spec)
|
category_id = self.category_service.create(category_spec)
|
||||||
|
except Error as error:
|
||||||
|
self.module.fail_json(msg="%s" % self.get_error_message(error))
|
||||||
|
|
||||||
if category_id:
|
if category_id:
|
||||||
self.module.exit_json(changed=True,
|
self.module.exit_json(changed=True,
|
||||||
category_results=dict(msg="Category '%s' created." % category_spec.name,
|
category_results=dict(msg="Category '%s' created." % category_spec.name,
|
||||||
|
@ -199,8 +204,11 @@ class VmwareCategory(VmwareRestClient):
|
||||||
change_list.append(True)
|
change_list.append(True)
|
||||||
|
|
||||||
if any(change_list):
|
if any(change_list):
|
||||||
|
try:
|
||||||
self.category_service.update(category_id, category_update_spec)
|
self.category_service.update(category_id, category_update_spec)
|
||||||
changed = True
|
changed = True
|
||||||
|
except Error as error:
|
||||||
|
self.module.fail_json(msg="%s" % self.get_error_message(error))
|
||||||
|
|
||||||
self.module.exit_json(changed=changed,
|
self.module.exit_json(changed=changed,
|
||||||
category_results=results)
|
category_results=results)
|
||||||
|
@ -208,7 +216,10 @@ class VmwareCategory(VmwareRestClient):
|
||||||
def state_delete_category(self):
|
def state_delete_category(self):
|
||||||
"""Delete category."""
|
"""Delete category."""
|
||||||
category_id = self.global_categories[self.category_name]['category_id']
|
category_id = self.global_categories[self.category_name]['category_id']
|
||||||
|
try:
|
||||||
self.category_service.delete(category_id=category_id)
|
self.category_service.delete(category_id=category_id)
|
||||||
|
except Error as error:
|
||||||
|
self.module.fail_json(msg="%s" % self.get_error_message(error))
|
||||||
self.module.exit_json(changed=True,
|
self.module.exit_json(changed=True,
|
||||||
category_results=dict(msg="Category '%s' deleted." % self.category_name,
|
category_results=dict(msg="Category '%s' deleted." % self.category_name,
|
||||||
category_id=category_id))
|
category_id=category_id))
|
||||||
|
|
|
@ -107,6 +107,10 @@ results:
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils.vmware_rest_client import VmwareRestClient
|
from ansible.module_utils.vmware_rest_client import VmwareRestClient
|
||||||
|
try:
|
||||||
|
from com.vmware.vapi.std.errors_client import Error
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class VmwareTag(VmwareRestClient):
|
class VmwareTag(VmwareRestClient):
|
||||||
|
@ -160,13 +164,18 @@ class VmwareTag(VmwareRestClient):
|
||||||
self.module.fail_json(msg="Unable to find category specified using 'category_id' - %s" % category_id)
|
self.module.fail_json(msg="Unable to find category specified using 'category_id' - %s" % category_id)
|
||||||
|
|
||||||
tag_spec.category_id = category_id
|
tag_spec.category_id = category_id
|
||||||
|
tag_id = ''
|
||||||
|
try:
|
||||||
tag_id = self.tag_service.create(tag_spec)
|
tag_id = self.tag_service.create(tag_spec)
|
||||||
|
except Error as error:
|
||||||
|
self.module.fail_json(msg="%s" % self.get_error_message(error))
|
||||||
|
|
||||||
if tag_id:
|
if tag_id:
|
||||||
self.module.exit_json(changed=True,
|
self.module.exit_json(changed=True,
|
||||||
results=dict(msg="Tag '%s' created." % tag_spec.name,
|
results=dict(msg="Tag '%s' created." % tag_spec.name,
|
||||||
tag_id=tag_id))
|
tag_id=tag_id))
|
||||||
self.module.exit_json(changed=False,
|
self.module.exit_json(changed=False,
|
||||||
results=dict(msg="No tag created", tag_id=''))
|
results=dict(msg="No tag created", tag_id=tag_id))
|
||||||
|
|
||||||
def state_unchanged(self):
|
def state_unchanged(self):
|
||||||
"""
|
"""
|
||||||
|
@ -189,7 +198,11 @@ class VmwareTag(VmwareRestClient):
|
||||||
desired_tag_desc = self.params.get('tag_description')
|
desired_tag_desc = self.params.get('tag_description')
|
||||||
if tag_desc != desired_tag_desc:
|
if tag_desc != desired_tag_desc:
|
||||||
tag_update_spec.description = desired_tag_desc
|
tag_update_spec.description = desired_tag_desc
|
||||||
|
try:
|
||||||
self.tag_service.update(tag_id, tag_update_spec)
|
self.tag_service.update(tag_id, tag_update_spec)
|
||||||
|
except Error as error:
|
||||||
|
self.module.fail_json(msg="%s" % self.get_error_message(error))
|
||||||
|
|
||||||
results['msg'] = 'Tag %s updated.' % self.tag_name
|
results['msg'] = 'Tag %s updated.' % self.tag_name
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
|
@ -201,7 +214,10 @@ class VmwareTag(VmwareRestClient):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
tag_id = self.global_tags[self.tag_name]['tag_id']
|
tag_id = self.global_tags[self.tag_name]['tag_id']
|
||||||
|
try:
|
||||||
self.tag_service.delete(tag_id=tag_id)
|
self.tag_service.delete(tag_id=tag_id)
|
||||||
|
except Error as error:
|
||||||
|
self.module.fail_json(msg="%s" % self.get_error_message(error))
|
||||||
self.module.exit_json(changed=True,
|
self.module.exit_json(changed=True,
|
||||||
results=dict(msg="Tag '%s' deleted." % self.tag_name,
|
results=dict(msg="Tag '%s' deleted." % self.tag_name,
|
||||||
tag_id=tag_id))
|
tag_id=tag_id))
|
||||||
|
|
|
@ -137,6 +137,7 @@ from ansible.module_utils.vmware_rest_client import VmwareRestClient
|
||||||
from ansible.module_utils.vmware import (PyVmomi, find_dvs_by_name, find_dvspg_by_name)
|
from ansible.module_utils.vmware import (PyVmomi, find_dvs_by_name, find_dvspg_by_name)
|
||||||
try:
|
try:
|
||||||
from com.vmware.vapi.std_client import DynamicID
|
from com.vmware.vapi.std_client import DynamicID
|
||||||
|
from com.vmware.vapi.std.errors_client import Error
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -239,20 +240,31 @@ class VmwareTagManager(VmwareRestClient):
|
||||||
if action in ('add', 'present'):
|
if action in ('add', 'present'):
|
||||||
if tag_obj not in available_tag_obj:
|
if tag_obj not in available_tag_obj:
|
||||||
# Tag is not already applied
|
# Tag is not already applied
|
||||||
|
try:
|
||||||
self.tag_association_svc.attach(tag_id=tag_obj.id, object_id=self.dynamic_managed_object)
|
self.tag_association_svc.attach(tag_id=tag_obj.id, object_id=self.dynamic_managed_object)
|
||||||
changed = True
|
changed = True
|
||||||
|
except Error as error:
|
||||||
|
self.module.fail_json(msg="%s" % self.get_error_message(error))
|
||||||
|
|
||||||
elif action == 'set':
|
elif action == 'set':
|
||||||
# Remove all tags first
|
# Remove all tags first
|
||||||
|
try:
|
||||||
if not removed_tags_for_set:
|
if not removed_tags_for_set:
|
||||||
for av_tag in available_tag_obj:
|
for av_tag in available_tag_obj:
|
||||||
self.tag_association_svc.detach(tag_id=av_tag.id, object_id=self.dynamic_managed_object)
|
self.tag_association_svc.detach(tag_id=av_tag.id, object_id=self.dynamic_managed_object)
|
||||||
removed_tags_for_set = True
|
removed_tags_for_set = True
|
||||||
self.tag_association_svc.attach(tag_id=tag_obj.id, object_id=self.dynamic_managed_object)
|
self.tag_association_svc.attach(tag_id=tag_obj.id, object_id=self.dynamic_managed_object)
|
||||||
changed = True
|
changed = True
|
||||||
|
except Error as error:
|
||||||
|
self.module.fail_json(msg="%s" % self.get_error_message(error))
|
||||||
|
|
||||||
elif action in ('remove', 'absent'):
|
elif action in ('remove', 'absent'):
|
||||||
if tag_obj in available_tag_obj:
|
if tag_obj in available_tag_obj:
|
||||||
|
try:
|
||||||
self.tag_association_svc.detach(tag_id=tag_obj.id, object_id=self.dynamic_managed_object)
|
self.tag_association_svc.detach(tag_id=tag_obj.id, object_id=self.dynamic_managed_object)
|
||||||
changed = True
|
changed = True
|
||||||
|
except Error as error:
|
||||||
|
self.module.fail_json(msg="%s" % self.get_error_message(error))
|
||||||
|
|
||||||
results['tag_status']['current_tags'] = [tag.name for tag in self.get_tags_for_object(self.tag_service,
|
results['tag_status']['current_tags'] = [tag.name for tag in self.get_tags_for_object(self.tag_service,
|
||||||
self.tag_association_svc,
|
self.tag_association_svc,
|
||||||
|
|
Loading…
Reference in a new issue