mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-07-23 13:20:23 -07:00
[cloud] Add encryption support to efs module (#32815)
* Add encryption support to efs module * Update the exception handling in AWS EFS module
This commit is contained in:
parent
f0cf1b35d5
commit
2616f9d713
1 changed files with 86 additions and 24 deletions
|
@ -23,6 +23,29 @@ author:
|
||||||
- "Ryan Sydnor (@ryansydnor)"
|
- "Ryan Sydnor (@ryansydnor)"
|
||||||
- "Artem Kazakov (@akazakov)"
|
- "Artem Kazakov (@akazakov)"
|
||||||
options:
|
options:
|
||||||
|
encrypt:
|
||||||
|
description:
|
||||||
|
- A boolean value that, if true, creates an encrypted file system. This can not be modfied after the file
|
||||||
|
system is created.
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
choices: ['yes', 'no']
|
||||||
|
version_added: 2.5
|
||||||
|
kms_key_id:
|
||||||
|
description:
|
||||||
|
- The id of the AWS KMS CMK that will be used to protect the encrypted file system. This parameter is only
|
||||||
|
required if you want to use a non-default CMK. If this parameter is not specified, the default CMK for
|
||||||
|
Amazon EFS is used. The key id can be Key ID, Key ID ARN, Key Alias or Key Alias ARN.
|
||||||
|
required: false
|
||||||
|
version_added: 2.5
|
||||||
|
purge_tags:
|
||||||
|
description:
|
||||||
|
- If yes, existing tags will be purged from the resource to match exactly what is defined by I(tags) parameter. If the I(tags) parameter
|
||||||
|
is not set then tags will not be modified.
|
||||||
|
required: false
|
||||||
|
default: yes
|
||||||
|
choices: [ 'yes', 'no' ]
|
||||||
|
version_added: 2.5
|
||||||
state:
|
state:
|
||||||
description:
|
description:
|
||||||
- Allows to create, search and destroy Amazon EFS file system
|
- Allows to create, search and destroy Amazon EFS file system
|
||||||
|
@ -74,6 +97,7 @@ options:
|
||||||
default: 0
|
default: 0
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- aws
|
- aws
|
||||||
|
- ec2
|
||||||
'''
|
'''
|
||||||
|
|
||||||
EXAMPLES = '''
|
EXAMPLES = '''
|
||||||
|
@ -193,15 +217,18 @@ tags:
|
||||||
|
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from time import time as timestamp
|
from time import time as timestamp
|
||||||
|
import traceback
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from botocore.exceptions import ClientError
|
from botocore.exceptions import ClientError, BotoCoreError
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
pass # Taken care of by ec2.HAS_BOTO3
|
pass # Taken care of by ec2.HAS_BOTO3
|
||||||
|
|
||||||
|
from ansible.module_utils._text import to_native
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils.ec2 import (HAS_BOTO3, boto3_conn, camel_dict_to_snake_dict,
|
from ansible.module_utils.ec2 import (HAS_BOTO3, boto3_conn, camel_dict_to_snake_dict,
|
||||||
ec2_argument_spec, get_aws_connection_info)
|
ec2_argument_spec, get_aws_connection_info, ansible_dict_to_boto3_tag_list,
|
||||||
|
compare_aws_tags, boto3_tag_list_to_ansible_dict)
|
||||||
|
|
||||||
|
|
||||||
def _index_by_key(key, items):
|
def _index_by_key(key, items):
|
||||||
|
@ -221,6 +248,8 @@ class EFSConnection(object):
|
||||||
self.connection = boto3_conn(module, conn_type='client',
|
self.connection = boto3_conn(module, conn_type='client',
|
||||||
resource='efs', region=region,
|
resource='efs', region=region,
|
||||||
**aws_connect_params)
|
**aws_connect_params)
|
||||||
|
|
||||||
|
self.module = module
|
||||||
self.region = region
|
self.region = region
|
||||||
self.wait = module.params.get('wait')
|
self.wait = module.params.get('wait')
|
||||||
self.wait_timeout = module.params.get('wait_timeout')
|
self.wait_timeout = module.params.get('wait_timeout')
|
||||||
|
@ -256,12 +285,8 @@ class EFSConnection(object):
|
||||||
"""
|
"""
|
||||||
Returns tag list for selected instance of EFS
|
Returns tag list for selected instance of EFS
|
||||||
"""
|
"""
|
||||||
tags = iterate_all(
|
tags = self.connection.describe_tags(**kwargs)['Tags']
|
||||||
'Tags',
|
return tags
|
||||||
self.connection.describe_tags,
|
|
||||||
**kwargs
|
|
||||||
)
|
|
||||||
return dict((tag['Key'], tag['Value']) for tag in tags)
|
|
||||||
|
|
||||||
def get_mount_targets(self, **kwargs):
|
def get_mount_targets(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -331,19 +356,34 @@ class EFSConnection(object):
|
||||||
|
|
||||||
return list(targets)
|
return list(targets)
|
||||||
|
|
||||||
def create_file_system(self, name, performance_mode):
|
def create_file_system(self, name, performance_mode, encrypt, kms_key_id):
|
||||||
"""
|
"""
|
||||||
Creates new filesystem with selected name
|
Creates new filesystem with selected name
|
||||||
"""
|
"""
|
||||||
changed = False
|
changed = False
|
||||||
state = self.get_file_system_state(name)
|
state = self.get_file_system_state(name)
|
||||||
|
params = {}
|
||||||
|
params['CreationToken'] = name
|
||||||
|
params['PerformanceMode'] = performance_mode
|
||||||
|
if encrypt:
|
||||||
|
params['Encrypted'] = encrypt
|
||||||
|
if kms_key_id is not None:
|
||||||
|
params['KmsKeyId'] = kms_key_id
|
||||||
|
|
||||||
if state in [self.STATE_DELETING, self.STATE_DELETED]:
|
if state in [self.STATE_DELETING, self.STATE_DELETED]:
|
||||||
wait_for(
|
wait_for(
|
||||||
lambda: self.get_file_system_state(name),
|
lambda: self.get_file_system_state(name),
|
||||||
self.STATE_DELETED
|
self.STATE_DELETED
|
||||||
)
|
)
|
||||||
self.connection.create_file_system(CreationToken=name, PerformanceMode=performance_mode)
|
try:
|
||||||
changed = True
|
self.connection.create_file_system(**params)
|
||||||
|
changed = True
|
||||||
|
except ClientError as e:
|
||||||
|
self.module.fail_json(msg="Unable to create file system: {0}".format(to_native(e)),
|
||||||
|
exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response))
|
||||||
|
except BotoCoreError as e:
|
||||||
|
self.module.fail_json(msg="Unable to create file system: {0}".format(to_native(e)),
|
||||||
|
exception=traceback.format_exc())
|
||||||
|
|
||||||
# we always wait for the state to be available when creating.
|
# we always wait for the state to be available when creating.
|
||||||
# if we try to take any actions on the file system before it's available
|
# if we try to take any actions on the file system before it's available
|
||||||
|
@ -356,7 +396,7 @@ class EFSConnection(object):
|
||||||
|
|
||||||
return changed
|
return changed
|
||||||
|
|
||||||
def converge_file_system(self, name, tags, targets):
|
def converge_file_system(self, name, tags, purge_tags, targets):
|
||||||
"""
|
"""
|
||||||
Change attributes (mount targets and tags) of filesystem by name
|
Change attributes (mount targets and tags) of filesystem by name
|
||||||
"""
|
"""
|
||||||
|
@ -364,20 +404,36 @@ class EFSConnection(object):
|
||||||
fs_id = self.get_file_system_id(name)
|
fs_id = self.get_file_system_id(name)
|
||||||
|
|
||||||
if tags is not None:
|
if tags is not None:
|
||||||
tags_to_create, _, tags_to_delete = dict_diff(self.get_tags(FileSystemId=fs_id), tags)
|
tags_need_modify, tags_to_delete = compare_aws_tags(boto3_tag_list_to_ansible_dict(self.get_tags(FileSystemId=fs_id)), tags, purge_tags)
|
||||||
|
|
||||||
if tags_to_delete:
|
if tags_to_delete:
|
||||||
self.connection.delete_tags(
|
try:
|
||||||
FileSystemId=fs_id,
|
self.connection.delete_tags(
|
||||||
TagKeys=[item[0] for item in tags_to_delete]
|
FileSystemId=fs_id,
|
||||||
)
|
TagKeys=tags_to_delete
|
||||||
|
)
|
||||||
|
except ClientError as e:
|
||||||
|
self.module.fail_json(msg="Unable to delete tags: {0}".format(to_native(e)),
|
||||||
|
exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response))
|
||||||
|
except BotoCoreError as e:
|
||||||
|
self.module.fail_json(msg="Unable to delete tags: {0}".format(to_native(e)),
|
||||||
|
exception=traceback.format_exc())
|
||||||
|
|
||||||
result = True
|
result = True
|
||||||
|
|
||||||
if tags_to_create:
|
if tags_need_modify:
|
||||||
self.connection.create_tags(
|
try:
|
||||||
FileSystemId=fs_id,
|
self.connection.create_tags(
|
||||||
Tags=[{'Key': item[0], 'Value': item[1]} for item in tags_to_create]
|
FileSystemId=fs_id,
|
||||||
)
|
Tags=ansible_dict_to_boto3_tag_list(tags_need_modify)
|
||||||
|
)
|
||||||
|
except ClientError as e:
|
||||||
|
self.module.fail_json(msg="Unable to create tags: {0}".format(to_native(e)),
|
||||||
|
exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response))
|
||||||
|
except BotoCoreError as e:
|
||||||
|
self.module.fail_json(msg="Unable to create tags: {0}".format(to_native(e)),
|
||||||
|
exception=traceback.format_exc())
|
||||||
|
|
||||||
result = True
|
result = True
|
||||||
|
|
||||||
if targets is not None:
|
if targets is not None:
|
||||||
|
@ -561,7 +617,10 @@ def main():
|
||||||
"""
|
"""
|
||||||
argument_spec = ec2_argument_spec()
|
argument_spec = ec2_argument_spec()
|
||||||
argument_spec.update(dict(
|
argument_spec.update(dict(
|
||||||
|
encrypt=dict(required=False, type="bool", default=False),
|
||||||
state=dict(required=False, type='str', choices=["present", "absent"], default="present"),
|
state=dict(required=False, type='str', choices=["present", "absent"], default="present"),
|
||||||
|
kms_key_id=dict(required=False, type='str', default=None),
|
||||||
|
purge_tags=dict(default=True, type='bool'),
|
||||||
id=dict(required=False, type='str', default=None),
|
id=dict(required=False, type='str', default=None),
|
||||||
name=dict(required=False, type='str', default=None),
|
name=dict(required=False, type='str', default=None),
|
||||||
tags=dict(required=False, type="dict", default={}),
|
tags=dict(required=False, type="dict", default={}),
|
||||||
|
@ -592,7 +651,10 @@ def main():
|
||||||
'general_purpose': 'generalPurpose',
|
'general_purpose': 'generalPurpose',
|
||||||
'max_io': 'maxIO'
|
'max_io': 'maxIO'
|
||||||
}
|
}
|
||||||
|
encrypt = module.params.get('encrypt')
|
||||||
|
kms_key_id = module.params.get('kms_key_id')
|
||||||
performance_mode = performance_mode_translations[module.params.get('performance_mode')]
|
performance_mode = performance_mode_translations[module.params.get('performance_mode')]
|
||||||
|
purge_tags = module.params.get('purge_tags')
|
||||||
changed = False
|
changed = False
|
||||||
|
|
||||||
state = str(module.params.get('state')).lower()
|
state = str(module.params.get('state')).lower()
|
||||||
|
@ -601,8 +663,8 @@ def main():
|
||||||
if not name:
|
if not name:
|
||||||
module.fail_json(msg='Name parameter is required for create')
|
module.fail_json(msg='Name parameter is required for create')
|
||||||
|
|
||||||
changed = connection.create_file_system(name, performance_mode)
|
changed = connection.create_file_system(name, performance_mode, encrypt, kms_key_id)
|
||||||
changed = connection.converge_file_system(name=name, tags=tags, targets=targets) or changed
|
changed = connection.converge_file_system(name=name, tags=tags, purge_tags=purge_tags, targets=targets) or changed
|
||||||
result = first_or_default(connection.get_file_systems(CreationToken=name))
|
result = first_or_default(connection.get_file_systems(CreationToken=name))
|
||||||
|
|
||||||
elif state == 'absent':
|
elif state == 'absent':
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue