Remove old boto documentation and promote AnsibleAWSModule (#36763)
There should no longer be a need for boto documentation - it just adds significant extra clutter to the guidelines. AnsibleAWSModule greatly improves the codebase to such an extent that we should mandate it for new code unless there is a documented good reason.
This commit is contained in:
parent
3a161fa157
commit
836d7a42a4
1 changed files with 61 additions and 103 deletions
|
@ -14,9 +14,35 @@ Please do not add new dependencies on the old boto library.
|
|||
|
||||
Prior to 2.0, modules may have been written in boto or boto3. The effort to port all modules to
|
||||
boto3 has begun. From Ansible 2.4 it is permissible for modules which previously required boto to
|
||||
start to require boto3 in order to deliver the functionality previously supported with boto and the
|
||||
start to migrate to boto3 in order to deliver the functionality previously supported with boto and the
|
||||
boto dependency can be deleted.
|
||||
|
||||
From 2.6, all new modules should use AnsibleAWSModule as a base, or have a documented reason not
|
||||
to. Using AnsibleAWSModule greatly simplifies exception handling and library management, reducing
|
||||
the amount of boilerplate code.
|
||||
|
||||
## Porting code to AnsibleAWSModule
|
||||
|
||||
Change
|
||||
|
||||
```
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
...
|
||||
module = AnsibleModule(...)
|
||||
```
|
||||
|
||||
to
|
||||
|
||||
```
|
||||
from ansible.module_utils.aws.core import AnsibleAWSModule
|
||||
...
|
||||
module = AnsibleAWSModule(...)
|
||||
```
|
||||
|
||||
Few other changes are required. One possible issue that you might encounter is that AnsibleAWSModule
|
||||
does not inherit methods from AnsibleModule by default, but most useful methods
|
||||
are included. If you do find an issue, please raise a bug report.
|
||||
|
||||
## Bug fixing
|
||||
|
||||
Bug fixes to code that relies on boto will still be accepted. When possible, the code should be
|
||||
|
@ -57,35 +83,17 @@ else:
|
|||
|
||||
The `ansible.module_utils.ec2` module and `ansible.module_utils.core.aws` modules will both
|
||||
automatically import boto3 and botocore. If boto3 is missing from the system then the variable
|
||||
`HAS_BOTO3` will be set to false. Normally, this means that modules don't need to import either
|
||||
botocore or boto3 directly. There is no need to check `HAS_BOTO3` when using AnsibleAWSModule
|
||||
`HAS_BOTO3` will be set to false. Normally, this means that modules don't need to import
|
||||
boto3 directly. There is no need to check `HAS_BOTO3` when using AnsibleAWSModule
|
||||
as the module does that check.
|
||||
|
||||
If you want to import the modules anyway (for example `from botocore.exception import
|
||||
ClientError`) Wrap import statements in a try block and fail the module later using `HAS_BOTO3` if
|
||||
the import fails. See below as well (`Exception Handling for boto3 and botocore`) for more detail
|
||||
on how to safely import botocore exceptions.
|
||||
|
||||
#### boto
|
||||
|
||||
```python
|
||||
try:
|
||||
import boto.ec2
|
||||
from boto.exception import BotoServerError
|
||||
HAS_BOTO = True
|
||||
except ImportError:
|
||||
HAS_BOTO = False
|
||||
|
||||
def main():
|
||||
|
||||
if not HAS_BOTO:
|
||||
module.fail_json(msg='boto required for this module')
|
||||
```
|
||||
|
||||
#### boto3
|
||||
|
||||
```python
|
||||
from ansible.module_utils.aws.core import AnsibleAWSModule
|
||||
|
||||
try:
|
||||
import botocore
|
||||
except ImportError:
|
||||
pass # handled by AnsibleAWSModule
|
||||
```
|
||||
|
||||
or
|
||||
|
@ -94,6 +102,10 @@ or
|
|||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.ec2 import HAS_BOTO3
|
||||
|
||||
try:
|
||||
import botocore
|
||||
except ImportError:
|
||||
pass # handled by imported HAS_BOTO3
|
||||
|
||||
def main():
|
||||
|
||||
|
@ -103,25 +115,8 @@ def main():
|
|||
|
||||
#### boto and boto3 combined
|
||||
|
||||
Ensure that you clearly document if a new parameter requires requires a specific version. Import
|
||||
boto3 at the top of the module as normal and then use the `HAS_BOTO3` bool when necessary, before the
|
||||
new feature.
|
||||
Modules should be ported to use boto3 rather than use both boto and boto3.
|
||||
|
||||
```python
|
||||
from ansible.module_utils.ec2 import HAS_BOTO3
|
||||
|
||||
try:
|
||||
import boto
|
||||
HAS_BOTO = True
|
||||
except ImportError:
|
||||
HAS_BOTO = False
|
||||
|
||||
if my_new_feature_Parameter_is_set:
|
||||
if HAS_BOTO3:
|
||||
# do feature
|
||||
else:
|
||||
module.fail_json(msg="boto3 is required for this feature")
|
||||
```
|
||||
|
||||
### Connecting to AWS
|
||||
|
||||
|
@ -133,8 +128,6 @@ to connect to AWS as these handle the same range of connection options.
|
|||
|
||||
These helpers also for missing profiles or a region not set when it needs to be, so you don't have to.
|
||||
|
||||
#### boto3
|
||||
|
||||
An example of connecting to ec2 is shown below. Note that unlike boto there is no `NoAuthHandlerFound`
|
||||
exception handling like in boto. Instead, an `AuthFailure` exception will be thrown when you use the
|
||||
connection. To ensure that authorization, parameter validation and permissions errors are all caught,
|
||||
|
@ -158,22 +151,9 @@ region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True
|
|||
connection = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_params)
|
||||
```
|
||||
|
||||
#### boto
|
||||
|
||||
An example of connecting to ec2:
|
||||
|
||||
Some boto services require that the region is specified. You should check for the region parameter
|
||||
if required.
|
||||
|
||||
```python
|
||||
region, ec2_url, aws_connect_params = get_aws_connection_info(module)
|
||||
if region:
|
||||
try:
|
||||
connection = connect_to_aws(boto.ec2, region, **aws_connect_params)
|
||||
except (boto.exception.NoAuthHandlerFound, AnsibleAWSError) as e:
|
||||
module.fail_json(msg=str(e))
|
||||
else:
|
||||
module.fail_json(msg="region must be specified")
|
||||
region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True)
|
||||
connection = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_params)
|
||||
```
|
||||
|
||||
### Common Documentation Fragments for Connection Parameters
|
||||
|
@ -198,35 +178,7 @@ extends_documentation_fragment:
|
|||
'''
|
||||
```
|
||||
|
||||
### Exception Handling for boto
|
||||
|
||||
You should wrap any boto call in a try block. If an exception is thrown, it is up to you decide how
|
||||
to handle it but usually calling fail_json with the error or helpful message and traceback will
|
||||
suffice.
|
||||
|
||||
#### boto
|
||||
|
||||
```python
|
||||
# Import BotoServerError
|
||||
try:
|
||||
import boto.ec2
|
||||
from boto.exception import BotoServerError
|
||||
HAS_BOTO = True
|
||||
except ImportError:
|
||||
HAS_BOTO = False
|
||||
|
||||
# Connect to AWS
|
||||
...
|
||||
|
||||
# Make a call to AWS
|
||||
try:
|
||||
result = connection.aws_call()
|
||||
except BotoServerError as e:
|
||||
module.fail_json(msg="helpful message here", exception=traceback.format_exc(),
|
||||
**camel_dict_to_snake_dict(e.message))
|
||||
```
|
||||
|
||||
### Exception Handling for boto3 and botocore
|
||||
### Exception Handling
|
||||
|
||||
You should wrap any boto3 or botocore call in a try block. If an exception is thrown, then there
|
||||
are a number of possibilities for handling it.
|
||||
|
@ -240,14 +192,14 @@ For more information on botocore exception handling see [the botocore error docu
|
|||
|
||||
#### using fail_json_aws()
|
||||
|
||||
_fail_json_aws() is a new method and may be subject to change. You can use it in modules which are
|
||||
being contributed back to Ansible, however if you are publishing your module separately please
|
||||
don't use it before the start of 2018 / Ansible 2.4_
|
||||
|
||||
In the AnsibleAWSModule there is a special method, `module.fail_json_aws()` for nice reporting of
|
||||
exceptions. Call this on your exception and it will report the error together with a traceback for
|
||||
use in Ansible verbose mode.
|
||||
|
||||
You should use the AnsibleAWSModule for all new modules, unless not possible. If adding significant
|
||||
amounts of exception handling to existing modules, we recommend migrating the module to use AnsibleAWSModule
|
||||
(there are very few changes required to do this)
|
||||
|
||||
```python
|
||||
from ansible.module_utils.aws.core import AnsibleAWSModule
|
||||
|
||||
|
@ -473,6 +425,20 @@ functions detailed below.
|
|||
boto3 returns results in a dict. The keys of the dict are in CamelCase format. In keeping with
|
||||
Ansible format, this function will convert the keys to snake_case.
|
||||
|
||||
`camel_dict_to_snake_dict` takes an optional parameter called `ignore_list` which is a list of
|
||||
keys not to convert (this is usually useful for the `tags` dict, whose child keys should remain with
|
||||
case preserved)
|
||||
|
||||
Another optional parameter is `reversible`. By default, `HTTPEndpoint` is converted to `http_endpoint`,
|
||||
which would then be converted by `snake_dict_to_camel_dict` to `HttpEndpoint`.
|
||||
Passing `reversible=True` converts HTTPEndpoint to `h_t_t_p_endpoint` which converts back to `HTTPEndpoint`.
|
||||
|
||||
#### snake_dict_to_camel_dict
|
||||
|
||||
`snake_dict_to_camel_dict` converts snake cased keys to camel case. By default, because it was
|
||||
first introduced for ECS purposes, this converts to dromedaryCase. An optional
|
||||
parameter called `capitalize_first`, which defaults to `False`, can be used to convert to CamelCase.
|
||||
|
||||
#### ansible_dict_to_boto3_filter_list
|
||||
|
||||
Converts a an Ansible list of filters to a boto3 friendly list of dicts. This is useful for any
|
||||
|
@ -482,15 +448,7 @@ boto3 `_facts` modules.
|
|||
|
||||
Pass an exception returned from boto or boto3, and this function will consistently get the message from the exception.
|
||||
|
||||
```
|
||||
import traceback
|
||||
from ansible.module_utils.ec2 import boto_exception
|
||||
try:
|
||||
...
|
||||
except boto.exception.BotoServerError as err:
|
||||
error_msg = boto_exception(err)
|
||||
module.fail_json(msg=error_msg, exception=traceback.format_exc())
|
||||
```
|
||||
Deprecated: use `AnsibleAWSModule`'s `fail_json_aws` instead.
|
||||
|
||||
|
||||
#### boto3_tag_list_to_ansible_dict
|
||||
|
|
Loading…
Reference in a new issue