AWS S3 : Fixup sanity test issues and deprecate 2 unused options (#63989)

* S3 module Sanity check fixes.

* s3_lifecycle: deprecate unused 'requester_pays' option

* s3_sync: deprecate unused retries option

* Add changelog fragment
pull/64020/head
Mark Chappell 6 years ago committed by John R Barker
parent fd54c54b51
commit 8d7580a59f

@ -0,0 +1,3 @@
deprecated_features:
- "s3_sync - The ``retries`` option had no effect and will be removed in Ansible 2.14"
- "s3_lifecycle - The ``requester_pays`` option had no effect and will be removed in Ansible 2.14"

@ -54,6 +54,8 @@ The following functionality will be removed in Ansible 2.14. Please update updat
* The :ref:`openssl_csr <openssl_csr_module>` module's option ``version`` no longer supports values other than ``1`` (the current only standardized CSR version). * The :ref:`openssl_csr <openssl_csr_module>` module's option ``version`` no longer supports values other than ``1`` (the current only standardized CSR version).
* :ref:`docker_container <docker_container_module>`: the ``trust_image_content`` option will be removed. It has always been ignored by the module. * :ref:`docker_container <docker_container_module>`: the ``trust_image_content`` option will be removed. It has always been ignored by the module.
* :ref:`iam_managed_policy <iam_managed_policy_module>`: the ``fail_on_delete`` option wil be removed. It has always been ignored by the module. * :ref:`iam_managed_policy <iam_managed_policy_module>`: the ``fail_on_delete`` option wil be removed. It has always been ignored by the module.
* :ref:`s3_lifecycle <s3_lifecycle_module>`: the ``requester_pays`` option will be removed. It has always been ignored by the module.
* :ref:`s3_sync <s3_sync_module>`: the ``retries`` option will be removed. It has always been ignored by the module.
Noteworthy module changes Noteworthy module changes

@ -2,6 +2,10 @@
# Copyright (c) 2017 Ansible Project # Copyright (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # 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
ANSIBLE_METADATA = {'metadata_version': '1.1', ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'], 'status': ['preview'],
'supported_by': 'community'} 'supported_by': 'community'}
@ -19,14 +23,17 @@ options:
description: description:
- Name of the s3 bucket - Name of the s3 bucket
required: true required: true
type: str
rules: rules:
description: description:
- Cors rules to put on the s3 bucket - Cors rules to put on the s3 bucket
type: list
state: state:
description: description:
- Create or remove cors on the s3 bucket - Create or remove cors on the s3 bucket
required: true required: true
choices: [ 'present', 'absent' ] choices: [ 'present', 'absent' ]
type: str
extends_documentation_fragment: extends_documentation_fragment:
- aws - aws
- ec2 - ec2

@ -13,6 +13,9 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>. # along with this library. If not, see <http://www.gnu.org/licenses/>.
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1', ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['stableinterface'], 'status': ['stableinterface'],
'supported_by': 'core'} 'supported_by': 'core'}
@ -38,15 +41,18 @@ options:
description: description:
- Name of the s3 bucket - Name of the s3 bucket
required: true required: true
type: str
policy: policy:
description: description:
- The JSON policy as a string. - The JSON policy as a string.
type: json
s3_url: s3_url:
description: description:
- S3 URL endpoint for usage with DigitalOcean, Ceph, Eucalyptus and fakes3 etc. - S3 URL endpoint for usage with DigitalOcean, Ceph, Eucalyptus and fakes3 etc.
- Assumes AWS if not specified. - Assumes AWS if not specified.
- For Walrus, use FQDN of the endpoint without scheme nor path. - For Walrus, use FQDN of the endpoint without scheme nor path.
aliases: [ S3_URL ] aliases: [ S3_URL ]
type: str
ceph: ceph:
description: description:
- Enable API compatibility with Ceph. It takes into account the S3 API subset working - Enable API compatibility with Ceph. It takes into account the S3 API subset working
@ -65,9 +71,11 @@ options:
required: false required: false
default: present default: present
choices: [ 'present', 'absent' ] choices: [ 'present', 'absent' ]
type: str
tags: tags:
description: description:
- tags dict to apply to bucket - tags dict to apply to bucket
type: dict
purge_tags: purge_tags:
description: description:
- whether to remove tags that aren't present in the C(tags) parameter - whether to remove tags that aren't present in the C(tags) parameter
@ -84,10 +92,12 @@ options:
In order to remove the server-side encryption, the encryption needs to be set to 'none' explicitly. In order to remove the server-side encryption, the encryption needs to be set to 'none' explicitly.
choices: [ 'none', 'AES256', 'aws:kms' ] choices: [ 'none', 'AES256', 'aws:kms' ]
version_added: "2.9" version_added: "2.9"
type: str
encryption_key_id: encryption_key_id:
description: KMS master key ID to use for the default encryption. This parameter is allowed if encryption is aws:kms. If description: KMS master key ID to use for the default encryption. This parameter is allowed if encryption is aws:kms. If
not specified then it will default to the AWS provided KMS key. not specified then it will default to the AWS provided KMS key.
version_added: "2.9" version_added: "2.9"
type: str
extends_documentation_fragment: extends_documentation_fragment:
- aws - aws
- ec2 - ec2

@ -29,17 +29,21 @@ options:
description: description:
- "Name of the s3 bucket" - "Name of the s3 bucket"
required: true required: true
type: str
expiration_date: expiration_date:
description: description:
- > - >
Indicates the lifetime of the objects that are subject to the rule by the date they will expire. The value must be ISO-8601 format, the time must Indicates the lifetime of the objects that are subject to the rule by the date they will expire. The value must be ISO-8601 format, the time must
be midnight and a GMT timezone must be specified. be midnight and a GMT timezone must be specified.
type: str
expiration_days: expiration_days:
description: description:
- "Indicates the lifetime, in days, of the objects that are subject to the rule. The value must be a non-zero positive integer." - "Indicates the lifetime, in days, of the objects that are subject to the rule. The value must be a non-zero positive integer."
type: int
prefix: prefix:
description: description:
- "Prefix identifying one or more objects to which the rule applies. If no prefix is specified, the rule will apply to the whole bucket." - "Prefix identifying one or more objects to which the rule applies. If no prefix is specified, the rule will apply to the whole bucket."
type: str
purge_transitions: purge_transitions:
description: description:
- > - >
@ -54,6 +58,7 @@ options:
- 'Delete noncurrent versions this many days after they become noncurrent' - 'Delete noncurrent versions this many days after they become noncurrent'
required: false required: false
version_added: 2.6 version_added: 2.6
type: int
noncurrent_version_storage_class: noncurrent_version_storage_class:
description: description:
- 'Transition noncurrent versions to this storage class' - 'Transition noncurrent versions to this storage class'
@ -61,11 +66,13 @@ options:
choices: ['glacier', 'onezone_ia', 'standard_ia'] choices: ['glacier', 'onezone_ia', 'standard_ia']
required: false required: false
version_added: 2.6 version_added: 2.6
type: str
noncurrent_version_transition_days: noncurrent_version_transition_days:
description: description:
- 'Transition noncurrent versions this many days after they become noncurrent' - 'Transition noncurrent versions this many days after they become noncurrent'
required: false required: false
version_added: 2.6 version_added: 2.6
type: int
noncurrent_version_transitions: noncurrent_version_transitions:
description: description:
- > - >
@ -74,34 +81,41 @@ options:
I(transition_days) I(transition_days)
I(storage_class) I(storage_class)
version_added: 2.6 version_added: 2.6
type: list
rule_id: rule_id:
description: description:
- "Unique identifier for the rule. The value cannot be longer than 255 characters. A unique value for the rule will be generated if no value is provided." - "Unique identifier for the rule. The value cannot be longer than 255 characters. A unique value for the rule will be generated if no value is provided."
type: str
state: state:
description: description:
- "Create or remove the lifecycle rule" - "Create or remove the lifecycle rule"
default: present default: present
choices: [ 'present', 'absent' ] choices: [ 'present', 'absent' ]
type: str
status: status:
description: description:
- "If 'enabled', the rule is currently being applied. If 'disabled', the rule is not currently being applied." - "If 'enabled', the rule is currently being applied. If 'disabled', the rule is not currently being applied."
default: enabled default: enabled
choices: [ 'enabled', 'disabled' ] choices: [ 'enabled', 'disabled' ]
type: str
storage_class: storage_class:
description: description:
- "The storage class to transition to. Currently there are two supported values - 'glacier', 'onezone_ia', or 'standard_ia'." - "The storage class to transition to. Currently there are two supported values - 'glacier', 'onezone_ia', or 'standard_ia'."
- "The 'standard_ia' class is only being available from Ansible version 2.2." - "The 'standard_ia' class is only being available from Ansible version 2.2."
default: glacier default: glacier
choices: [ 'glacier', 'onezone_ia', 'standard_ia'] choices: [ 'glacier', 'onezone_ia', 'standard_ia']
type: str
transition_date: transition_date:
description: description:
- > - >
Indicates the lifetime of the objects that are subject to the rule by the date they will transition to a different storage class. Indicates the lifetime of the objects that are subject to the rule by the date they will transition to a different storage class.
The value must be ISO-8601 format, the time must be midnight and a GMT timezone must be specified. If transition_days is not specified, The value must be ISO-8601 format, the time must be midnight and a GMT timezone must be specified. If transition_days is not specified,
this parameter is required." this parameter is required."
type: str
transition_days: transition_days:
description: description:
- "Indicates when, in days, an object transitions to a different storage class. If transition_date is not specified, this parameter is required." - "Indicates when, in days, an object transitions to a different storage class. If transition_date is not specified, this parameter is required."
type: int
transitions: transitions:
description: description:
- A list of transition behaviors to be applied to the rule. Each storage class may be used only once. Each transition - A list of transition behaviors to be applied to the rule. Each storage class may be used only once. Each transition
@ -110,6 +124,11 @@ options:
I(transition_date) I(transition_date)
I(storage_class) I(storage_class)
version_added: 2.6 version_added: 2.6
type: list
requester_pays:
description:
- The I(requester_pays) option does nothing and will be removed in Ansible 2.14.
type: bool
extends_documentation_fragment: extends_documentation_fragment:
- aws - aws
- ec2 - ec2
@ -435,7 +454,7 @@ def main():
noncurrent_version_transition_days=dict(type='int'), noncurrent_version_transition_days=dict(type='int'),
noncurrent_version_transitions=dict(type='list'), noncurrent_version_transitions=dict(type='list'),
prefix=dict(), prefix=dict(),
requester_pays=dict(default='no', type='bool'), requester_pays=dict(type='bool', removed_in_version='2.14'),
rule_id=dict(), rule_id=dict(),
state=dict(default='present', choices=['present', 'absent']), state=dict(default='present', choices=['present', 'absent']),
status=dict(default='enabled', choices=['enabled', 'disabled']), status=dict(default='enabled', choices=['enabled', 'disabled']),

@ -14,6 +14,9 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>. # along with Ansible. If not, see <http://www.gnu.org/licenses/>.
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1', ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'], 'status': ['preview'],
'supported_by': 'community'} 'supported_by': 'community'}
@ -32,7 +35,8 @@ options:
description: description:
- sync direction. - sync direction.
default: 'push' default: 'push'
choices: [ push ] choices: [ 'push' ]
type: str
file_change_strategy: file_change_strategy:
description: description:
- Difference determination method to allow changes-only syncing. Unlike rsync, files are not patched- they are fully skipped or fully uploaded. - Difference determination method to allow changes-only syncing. Unlike rsync, files are not patched- they are fully skipped or fully uploaded.
@ -41,32 +45,45 @@ options:
- force will always upload all files. - force will always upload all files.
required: false required: false
default: 'date_size' default: 'date_size'
choices: [ force, checksum, date_size ] choices: [ 'force', 'checksum', 'date_size' ]
type: str
bucket: bucket:
description: description:
- Bucket name. - Bucket name.
required: true required: true
type: str
key_prefix: key_prefix:
description: description:
- In addition to file path, prepend s3 path with this prefix. Module will add slash at end of prefix if necessary. - In addition to file path, prepend s3 path with this prefix. Module will add slash at end of prefix if necessary.
required: false required: false
type: str
file_root: file_root:
description: description:
- File/directory path for synchronization. This is a local path. - File/directory path for synchronization. This is a local path.
- This root path is scrubbed from the key name, so subdirectories will remain as keys. - This root path is scrubbed from the key name, so subdirectories will remain as keys.
required: true required: true
type: path
permission: permission:
description: description:
- Canned ACL to apply to synced files. - Canned ACL to apply to synced files.
- Changing this ACL only changes newly synced files, it does not trigger a full reupload. - Changing this ACL only changes newly synced files, it does not trigger a full reupload.
required: false required: false
choices: [ '', private, public-read, public-read-write, authenticated-read, aws-exec-read, bucket-owner-read, bucket-owner-full-control ] choices:
- 'private'
- 'public-read'
- 'public-read-write'
- 'authenticated-read'
- 'aws-exec-read'
- 'bucket-owner-read'
- 'bucket-owner-full-control'
type: str
mime_map: mime_map:
description: description:
- > - >
Dict entry from extension to MIME type. This will override any default/sniffed MIME type. Dict entry from extension to MIME type. This will override any default/sniffed MIME type.
For example C({".txt": "application/text", ".yml": "application/text"}) For example C({".txt": "application/text", ".yml": "application/text"})
required: false required: false
type: dict
include: include:
description: description:
- Shell pattern-style file matching. - Shell pattern-style file matching.
@ -74,6 +91,7 @@ options:
- For multiple patterns, comma-separate them. - For multiple patterns, comma-separate them.
required: false required: false
default: "*" default: "*"
type: str
exclude: exclude:
description: description:
- Shell pattern-style file matching. - Shell pattern-style file matching.
@ -81,13 +99,14 @@ options:
- For multiple patterns, comma-separate them. - For multiple patterns, comma-separate them.
required: false required: false
default: ".*" default: ".*"
type: str
cache_control: cache_control:
description: description:
- This is a string.
- Cache-Control header set on uploaded objects. - Cache-Control header set on uploaded objects.
- Directives are separated by commas. - Directives are separated by commas.
required: false required: false
version_added: "2.4" version_added: "2.4"
type: str
delete: delete:
description: description:
- Remove remote files that exist in bucket but are not present in the file root. - Remove remote files that exist in bucket but are not present in the file root.
@ -95,6 +114,10 @@ options:
default: no default: no
version_added: "2.4" version_added: "2.4"
type: bool type: bool
retries:
description:
- The I(retries) option does nothing and will be removed in Ansible 2.14.
type: str
requirements: requirements:
- boto3 >= 1.4.4 - boto3 >= 1.4.4
@ -356,7 +379,7 @@ def determine_mimetypes(filelist, override_map):
localfile = fileentry['fullpath'] localfile = fileentry['fullpath']
# reminder: file extension is '.txt', not 'txt'. # reminder: file extension is '.txt', not 'txt'.
_, file_extension = os.path.splitext(localfile) file_extension = os.path.splitext(localfile)[1]
if override_map and override_map.get(file_extension): if override_map and override_map.get(file_extension):
# override? use it. # override? use it.
retentry['mime_type'] = override_map[file_extension] retentry['mime_type'] = override_map[file_extension]
@ -489,7 +512,7 @@ def main():
file_root=dict(required=True, type='path'), file_root=dict(required=True, type='path'),
permission=dict(required=False, choices=['private', 'public-read', 'public-read-write', 'authenticated-read', permission=dict(required=False, choices=['private', 'public-read', 'public-read-write', 'authenticated-read',
'aws-exec-read', 'bucket-owner-read', 'bucket-owner-full-control']), 'aws-exec-read', 'bucket-owner-read', 'bucket-owner-full-control']),
retries=dict(required=False), retries=dict(required=False, removed_in_version='2.14'),
mime_map=dict(required=False, type='dict'), mime_map=dict(required=False, type='dict'),
exclude=dict(required=False, default=".*"), exclude=dict(required=False, default=".*"),
include=dict(required=False, default="*"), include=dict(required=False, default="*"),

@ -25,23 +25,21 @@ options:
description: description:
- "Name of the s3 bucket" - "Name of the s3 bucket"
required: true required: true
type: str
error_key: error_key:
description: description:
- "The object key name to use when a 4XX class error occurs. To remove an error key, set to None." - "The object key name to use when a 4XX class error occurs. To remove an error key, set to None."
type: str
redirect_all_requests: redirect_all_requests:
description: description:
- "Describes the redirect behavior for every request to this s3 bucket website endpoint" - "Describes the redirect behavior for every request to this s3 bucket website endpoint"
region: type: str
description:
- >
AWS region to create the bucket in. If not set then the value of the AWS_REGION and EC2_REGION environment variables are checked,
followed by the aws_region and ec2_region settings in the Boto config file. If none of those are set the region defaults to the
S3 Location: US Standard.
state: state:
description: description:
- "Add or remove s3 website configuration" - "Add or remove s3 website configuration"
default: present
choices: [ 'present', 'absent' ] choices: [ 'present', 'absent' ]
required: true
type: str
suffix: suffix:
description: description:
- > - >
@ -49,6 +47,7 @@ options:
samplebucket/images/ the data that is returned will be for the object with the key name images/index.html). The suffix must not include a slash samplebucket/images/ the data that is returned will be for the object with the key name images/index.html). The suffix must not include a slash
character. character.
default: index.html default: index.html
type: str
extends_documentation_fragment: extends_documentation_fragment:
- aws - aws
@ -109,30 +108,59 @@ redirect_all_requests_to:
returned: when redirect all requests parameter set returned: when redirect all requests parameter set
type: str type: str
sample: ansible.com sample: ansible.com
protocol:
description: protocol to use when redirecting requests.
returned: when redirect all requests parameter set
type: str
sample: https
routing_rules: routing_rules:
description: routing rules description: routing rules
type: complex type: list
returned: always returned: always
contains: contains:
routing_rule:
host_name:
description: name of the host where requests will be redirected.
returned: when host name set as part of redirect rule
type: str
sample: ansible.com
condition: condition:
key_prefix_equals: type: complex
description: object key name prefix when the redirect is applied. For example, to redirect requests for ExamplePage.html, the key prefix will be description: A container for describing a condition that must be met for the specified redirect to apply.
ExamplePage.html contains:
returned: when routing rule present http_error_code_returned_equals:
type: str description: The HTTP error code when the redirect is applied.
sample: docs/ returned: always
type: str
key_prefix_equals:
description: object key name prefix when the redirect is applied. For example, to redirect
requests for ExamplePage.html, the key prefix will be ExamplePage.html
returned: when routing rule present
type: str
sample: docs/
redirect: redirect:
replace_key_prefix_with: type: complex
description: object key prefix to use in the redirect request description: Container for redirect information.
returned: when routing rule present returned: always
type: str contains:
sample: documents/ host_name:
description: name of the host where requests will be redirected.
returned: when host name set as part of redirect rule
type: str
sample: ansible.com
http_redirect_code:
description: The HTTP redirect code to use on the response.
returned: when routing rule present
type: str
protocol:
description: Protocol to use when redirecting requests.
returned: when routing rule present
type: str
sample: http
replace_key_prefix_with:
description: object key prefix to use in the redirect request
returned: when routing rule present
type: str
sample: documents/
replace_key_with:
description: object key prefix to use in the redirect request
returned: when routing rule present
type: str
sample: documents/
''' '''
import time import time

@ -606,9 +606,6 @@ lib/ansible/modules/cloud/amazon/aws_s3.py validate-modules:undocumented-paramet
lib/ansible/modules/cloud/amazon/aws_s3.py validate-modules:doc-default-does-not-match-spec lib/ansible/modules/cloud/amazon/aws_s3.py validate-modules:doc-default-does-not-match-spec
lib/ansible/modules/cloud/amazon/aws_s3.py validate-modules:parameter-type-not-in-doc lib/ansible/modules/cloud/amazon/aws_s3.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/cloud/amazon/aws_s3.py validate-modules:doc-missing-type lib/ansible/modules/cloud/amazon/aws_s3.py validate-modules:doc-missing-type
lib/ansible/modules/cloud/amazon/aws_s3_cors.py future-import-boilerplate
lib/ansible/modules/cloud/amazon/aws_s3_cors.py metaclass-boilerplate
lib/ansible/modules/cloud/amazon/aws_s3_cors.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/cloud/amazon/aws_secret.py validate-modules:parameter-type-not-in-doc lib/ansible/modules/cloud/amazon/aws_secret.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/cloud/amazon/aws_secret.py validate-modules:doc-missing-type lib/ansible/modules/cloud/amazon/aws_secret.py validate-modules:doc-missing-type
lib/ansible/modules/cloud/amazon/aws_ses_identity.py future-import-boilerplate lib/ansible/modules/cloud/amazon/aws_ses_identity.py future-import-boilerplate
@ -1020,23 +1017,6 @@ lib/ansible/modules/cloud/amazon/route53_info.py validate-modules:doc-missing-ty
lib/ansible/modules/cloud/amazon/route53_zone.py future-import-boilerplate lib/ansible/modules/cloud/amazon/route53_zone.py future-import-boilerplate
lib/ansible/modules/cloud/amazon/route53_zone.py metaclass-boilerplate lib/ansible/modules/cloud/amazon/route53_zone.py metaclass-boilerplate
lib/ansible/modules/cloud/amazon/route53_zone.py validate-modules:doc-missing-type lib/ansible/modules/cloud/amazon/route53_zone.py validate-modules:doc-missing-type
lib/ansible/modules/cloud/amazon/s3_bucket.py future-import-boilerplate
lib/ansible/modules/cloud/amazon/s3_bucket.py metaclass-boilerplate
lib/ansible/modules/cloud/amazon/s3_bucket.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/cloud/amazon/s3_bucket.py validate-modules:doc-missing-type
lib/ansible/modules/cloud/amazon/s3_lifecycle.py validate-modules:undocumented-parameter
lib/ansible/modules/cloud/amazon/s3_lifecycle.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/cloud/amazon/s3_lifecycle.py validate-modules:doc-missing-type
lib/ansible/modules/cloud/amazon/s3_sync.py future-import-boilerplate
lib/ansible/modules/cloud/amazon/s3_sync.py metaclass-boilerplate
lib/ansible/modules/cloud/amazon/s3_sync.py pylint:blacklisted-name
lib/ansible/modules/cloud/amazon/s3_sync.py validate-modules:undocumented-parameter
lib/ansible/modules/cloud/amazon/s3_sync.py validate-modules:doc-choices-do-not-match-spec
lib/ansible/modules/cloud/amazon/s3_sync.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/cloud/amazon/s3_sync.py validate-modules:doc-missing-type
lib/ansible/modules/cloud/amazon/s3_website.py validate-modules:doc-default-does-not-match-spec
lib/ansible/modules/cloud/amazon/s3_website.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/cloud/amazon/s3_website.py validate-modules:return-syntax-error
lib/ansible/modules/cloud/amazon/sns.py validate-modules:parameter-type-not-in-doc lib/ansible/modules/cloud/amazon/sns.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/cloud/amazon/sns.py validate-modules:doc-missing-type lib/ansible/modules/cloud/amazon/sns.py validate-modules:doc-missing-type
lib/ansible/modules/cloud/amazon/sns_topic.py validate-modules:parameter-type-not-in-doc lib/ansible/modules/cloud/amazon/sns_topic.py validate-modules:parameter-type-not-in-doc

Loading…
Cancel
Save