Skip to content

Commit

Permalink
VMware: Handle user unauthorization in tagging scenarios (ansible#58405)
Browse files Browse the repository at this point in the history
Handle unauthorization scenarios in VMware tagging APIs.

Fixes: ansible#58326

Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
  • Loading branch information
Akasurde committed Jun 28, 2019
1 parent 242f160 commit e2d159c
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- Handle user unauthorization errors in VMware REST API code for tagging (https://github.com/ansible/ansible/issues/58326).
17 changes: 17 additions & 0 deletions lib/ansible/module_utils/vmware_rest_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
try:
from com.vmware.vapi.std_client import DynamicID
from vmware.vapi.vsphere.client import create_vsphere_client
from com.vmware.vapi.std.errors_client import Unauthorized
HAS_VSPHERE = True
except ImportError:
VSPHERE_IMP_ERR = traceback.format_exc()
Expand All @@ -49,6 +50,22 @@ def __init__(self, module):
self.check_required_library()
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):
"""
Check required libraries
Expand Down
19 changes: 15 additions & 4 deletions lib/ansible/modules/cloud/vmware/vmware_category.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
from ansible.module_utils.vmware_rest_client import VmwareRestClient
try:
from com.vmware.cis.tagging_client import CategoryModel
from com.vmware.vapi.std.errors_client import Error
except ImportError:
pass

Expand Down Expand Up @@ -159,7 +160,11 @@ def state_create_category(self):

category_spec.associable_types = set()

category_id = self.category_service.create(category_spec)
try:
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:
self.module.exit_json(changed=True,
category_results=dict(msg="Category '%s' created." % category_spec.name,
Expand Down Expand Up @@ -199,16 +204,22 @@ def state_update_category(self):
change_list.append(True)

if any(change_list):
self.category_service.update(category_id, category_update_spec)
changed = True
try:
self.category_service.update(category_id, category_update_spec)
changed = True
except Error as error:
self.module.fail_json(msg="%s" % self.get_error_message(error))

self.module.exit_json(changed=changed,
category_results=results)

def state_delete_category(self):
"""Delete category."""
category_id = self.global_categories[self.category_name]['category_id']
self.category_service.delete(category_id=category_id)
try:
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,
category_results=dict(msg="Category '%s' deleted." % self.category_name,
category_id=category_id))
Expand Down
24 changes: 20 additions & 4 deletions lib/ansible/modules/cloud/vmware/vmware_tag.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@

from ansible.module_utils.basic import AnsibleModule
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):
Expand Down Expand Up @@ -160,13 +164,18 @@ def state_create_tag(self):
self.module.fail_json(msg="Unable to find category specified using 'category_id' - %s" % category_id)

tag_spec.category_id = category_id
tag_id = self.tag_service.create(tag_spec)
tag_id = ''
try:
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:
self.module.exit_json(changed=True,
results=dict(msg="Tag '%s' created." % tag_spec.name,
tag_id=tag_id))
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):
"""
Expand All @@ -189,7 +198,11 @@ def state_update_tag(self):
desired_tag_desc = self.params.get('tag_description')
if tag_desc != desired_tag_desc:
tag_update_spec.description = desired_tag_desc
self.tag_service.update(tag_id, tag_update_spec)
try:
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
changed = True

Expand All @@ -201,7 +214,10 @@ def state_delete_tag(self):
"""
tag_id = self.global_tags[self.tag_name]['tag_id']
self.tag_service.delete(tag_id=tag_id)
try:
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,
results=dict(msg="Tag '%s' deleted." % self.tag_name,
tag_id=tag_id))
Expand Down
32 changes: 22 additions & 10 deletions lib/ansible/modules/cloud/vmware/vmware_tag_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@
from ansible.module_utils.vmware import (PyVmomi, find_dvs_by_name, find_dvspg_by_name)
try:
from com.vmware.vapi.std_client import DynamicID
from com.vmware.vapi.std.errors_client import Error
except ImportError:
pass

Expand Down Expand Up @@ -239,20 +240,31 @@ def ensure_state(self):
if action in ('add', 'present'):
if tag_obj not in available_tag_obj:
# Tag is not already applied
self.tag_association_svc.attach(tag_id=tag_obj.id, object_id=self.dynamic_managed_object)
changed = True
try:
self.tag_association_svc.attach(tag_id=tag_obj.id, object_id=self.dynamic_managed_object)
changed = True
except Error as error:
self.module.fail_json(msg="%s" % self.get_error_message(error))

elif action == 'set':
# Remove all tags first
if not removed_tags_for_set:
for av_tag in available_tag_obj:
self.tag_association_svc.detach(tag_id=av_tag.id, object_id=self.dynamic_managed_object)
removed_tags_for_set = True
self.tag_association_svc.attach(tag_id=tag_obj.id, object_id=self.dynamic_managed_object)
changed = True
try:
if not removed_tags_for_set:
for av_tag in available_tag_obj:
self.tag_association_svc.detach(tag_id=av_tag.id, object_id=self.dynamic_managed_object)
removed_tags_for_set = True
self.tag_association_svc.attach(tag_id=tag_obj.id, object_id=self.dynamic_managed_object)
changed = True
except Error as error:
self.module.fail_json(msg="%s" % self.get_error_message(error))

elif action in ('remove', 'absent'):
if tag_obj in available_tag_obj:
self.tag_association_svc.detach(tag_id=tag_obj.id, object_id=self.dynamic_managed_object)
changed = True
try:
self.tag_association_svc.detach(tag_id=tag_obj.id, object_id=self.dynamic_managed_object)
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,
self.tag_association_svc,
Expand Down

0 comments on commit e2d159c

Please sign in to comment.