Skip to content

Commit

Permalink
Refacter connection_info et al
Browse files Browse the repository at this point in the history
  • Loading branch information
tremble committed Nov 1, 2022
1 parent 63cca2c commit 28eae36
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 23 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/1231-boto3_connections.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- module_utils.botocore - refactorization of ``get_aws_region``, ``get_aws_connection_info`` and ``get_aws_connection_info`` so that the code can be reused by non-module plugins (https://github.com/ansible-collections/amazon.aws/pull/1231).
59 changes: 40 additions & 19 deletions plugins/module_utils/botocore.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
from ansible.module_utils.six import binary_type
from ansible.module_utils.six import text_type

from .exceptions import AnsibleBotocoreError
from .retries import AWSRetry


Expand Down Expand Up @@ -137,42 +138,52 @@ def boto_exception(err):
return error


def get_aws_region(module, boto3=None):
region = module.params.get('region')
def _aws_region(params):
region = params.get('region')

if region:
return region

if not HAS_BOTO3:
module.fail_json(msg=missing_required_lib('boto3'), exception=BOTO3_IMP_ERR)
raise AnsibleBotocoreError(msg=missing_required_lib('boto3'), exception=BOTO3_IMP_ERR)

# here we don't need to make an additional call, will default to 'us-east-1' if the below evaluates to None.
try:
# Botocore doesn't like empty strings, make sure we default to None in the case of an empty
# string.
profile_name = module.params.get('profile') or None
profile_name = params.get('profile') or None
return botocore.session.Session(profile=profile_name).get_config_variable('region')
except botocore.exceptions.ProfileNotFound:
return None


def get_aws_connection_info(module, boto3=None):

# Check module args for credentials, then check environment vars
# access_key

endpoint_url = module.params.get('endpoint_url')
access_key = module.params.get('access_key')
secret_key = module.params.get('secret_key')
session_token = module.params.get('session_token')
region = get_aws_region(module)
profile_name = module.params.get('profile')
validate_certs = module.params.get('validate_certs')
ca_bundle = module.params.get('aws_ca_bundle')
config = module.params.get('aws_config')
def get_aws_region(module, boto3=None):

try:
return _aws_region(module.params)
except AnsibleBotocoreError as e:
if e.exception:
module.fail_json(msg=e.message, exception=e.exception)
else:
module.fail_json(msg=e.message)


def _get_aws_connection_info(params):

endpoint_url = params.get('endpoint_url')
access_key = params.get('access_key')
secret_key = params.get('secret_key')
session_token = params.get('session_token')
region = _aws_region(params)
profile_name = params.get('profile')
validate_certs = params.get('validate_certs')
ca_bundle = params.get('aws_ca_bundle')
config = params.get('aws_config')

# Caught here so that they can be deliberately set to '' to avoid conflicts when environment
# variables are also being used
if profile_name and (access_key or secret_key or session_token):
module.fail_json(msg="Passing both a profile and access tokens is not supported.")
raise AnsibleBotocoreError(msg="Passing both a profile and access tokens is not supported.")

# Botocore doesn't like empty strings, make sure we default to None in the case of an empty
# string.
Expand Down Expand Up @@ -212,6 +223,16 @@ def get_aws_connection_info(module, boto3=None):
return region, endpoint_url, boto_params


def get_aws_connection_info(module, boto3=None):
try:
return _get_aws_connection_info(module.params)
except AnsibleBotocoreError as e:
if e.exception:
module.fail_json(msg=e.message, exception=e.exception)
else:
module.fail_json(msg=e.message)


def _paginated_query(client, paginator_name, **params):
paginator = client.get_paginator(paginator_name)
result = paginator.paginate(**params).build_full_result()
Expand Down
7 changes: 3 additions & 4 deletions plugins/module_utils/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@
from .botocore import get_boto3_client_method_parameters # pylint: disable=unused-import
from .botocore import normalize_boto3_result # pylint: disable=unused-import

# Used to live here, moved into ansible_collections.amazon.aws.plugins.module_utils.exceptions
from .exceptions import AnsibleAWSError # pylint: disable=unused-import

# Used to live here, moved into ansible_collections.amazon.aws.plugins.module_utils.modules
from .modules import AnsibleAWSModule # pylint: disable=unused-import

Expand All @@ -71,7 +74,3 @@

# We will also export HAS_BOTO3 so end user modules can use it.
__all__ = ('AnsibleAWSModule', 'HAS_BOTO3', 'is_boto3_error_code', 'is_boto3_error_message')


class AnsibleAWSError(Exception):
pass
38 changes: 38 additions & 0 deletions plugins/module_utils/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# (c) 2022 Red Hat Inc.
#
# This file is part of Ansible
# 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)
__metaclass__ = type

from ansible.module_utils._text import to_native


class AnsibleAWSError(Exception):

def __str__(self):
if self.exception and self.message:
return "{0}: {1}".format(self.message, to_native(self.exception))

return super(AnsibleAWSError, self).__str__()

def __init__(self, message=None, exception=None, **kwargs):
if not message and not exception:
super(AnsibleAWSError, self).__init__()
if not message:
super(AnsibleAWSError, self).__init__(exception)
if not exception:
super(AnsibleAWSError, self).__init__(message)

self.exception = exception
self.message = message

# In places where passing more information to module.fail_json would be helpful
# store the extra info. Other plugin types have to raise the correct exception
# such as AnsibleLookupError, so can't easily consume this.
self.kwargs = kwargs or {}


class AnsibleBotocoreError(AnsibleAWSError):
pass

0 comments on commit 28eae36

Please sign in to comment.