summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Stephen <alexstephen@google.com>2018-08-15 11:27:41 -0700
committerRyan Brown <sb@ryansb.com>2018-08-15 14:27:41 -0400
commit87c6d4be57d1a4c02e5f4786a3622258b5466e40 (patch)
tree52d9d60d24dc55144323440136572ad120dc09ae
parent528f81a8d5003791c4a2bf7e7bb3b9a704b9518b (diff)
downloadansible-87c6d4be57d1a4c02e5f4786a3622258b5466e40.tar.gz
Bug fixes for gcp_storage_bucket (#42835)
-rw-r--r--lib/ansible/modules/cloud/google/gcp_storage_bucket.py644
-rw-r--r--test/integration/targets/gcp_storage_bucket/tasks/main.yml20
2 files changed, 411 insertions, 253 deletions
diff --git a/lib/ansible/modules/cloud/google/gcp_storage_bucket.py b/lib/ansible/modules/cloud/google/gcp_storage_bucket.py
index c2601fa43a..0f47994284 100644
--- a/lib/ansible/modules/cloud/google/gcp_storage_bucket.py
+++ b/lib/ansible/modules/cloud/google/gcp_storage_bucket.py
@@ -32,12 +32,11 @@ DOCUMENTATION = '''
---
module: gcp_storage_bucket
description:
- - The Buckets resource represents a bucket in Google Cloud Storage. There is
- a single global namespace shared by all buckets. For more information, see
- Bucket Name Requirements.
- - Buckets contain objects which can be accessed by their own methods. In
- addition to the acl property, buckets contain bucketAccessControls, for
- use in fine-grained manipulation of an existing bucket's access controls.
+ - The Buckets resource represents a bucket in Google Cloud Storage. There is a single
+ global namespace shared by all buckets. For more information, see Bucket Name Requirements.
+ - Buckets contain objects which can be accessed by their own methods. In addition
+ to the acl property, buckets contain bucketAccessControls, for use in fine-grained
+ manipulation of an existing bucket's access controls.
- A bucket is always owned by the project team owners group.
short_description: Creates a GCP Bucket
version_added: 2.6
@@ -50,7 +49,6 @@ options:
state:
description:
- Whether the given object should exist in GCP
- required: true
choices: ['present', 'absent']
default: 'present'
acl:
@@ -60,7 +58,7 @@ options:
suboptions:
bucket:
description:
- - A reference to Bucket resource.
+ - The name of the bucket.
required: true
domain:
description:
@@ -72,16 +70,13 @@ options:
required: false
entity:
description:
- - |
- The entity holding the permission, in one of the following
- forms: user-userId user-email group-groupId
- group-email domain-domain project-team-projectId
- allUsers allAuthenticatedUsers Examples: The user
- liz@example.com would be user-liz@example.com.
- - The group example@googlegroups.com would be
- group-example@googlegroups.com.
- - To refer to all members of the Google Apps for Business domain
- example.com, the entity would be domain-example.com.
+ - 'The entity holding the permission, in one of the following forms: user-userId
+ user-email group-groupId group-email domain-domain project-team-projectId allUsers
+ allAuthenticatedUsers Examples: The user liz@example.com would be
+ user-liz@example.com.'
+ - The group example@googlegroups.com would be group-example@googlegroups.com.
+ - To refer to all members of the Google Apps for Business domain example.com, the
+ entity would be domain-example.com.
required: true
entity_id:
description:
@@ -117,41 +112,97 @@ options:
suboptions:
max_age_seconds:
description:
- - The value, in seconds, to return in the Access-Control-Max-Age
- header used in preflight responses.
+ - The value, in seconds, to return in the Access-Control-Max-Age header used in preflight
+ responses.
required: false
method:
description:
- - |
- The list of HTTP methods on which to include CORS response
- headers, (GET, OPTIONS, POST, etc) Note: "*" is permitted in
- the list of methods, and means "any method".
+ - 'The list of HTTP methods on which to include CORS response headers, (GET, OPTIONS,
+ POST, etc) Note: "*" is permitted in the list of methods, and means "any method".'
required: false
origin:
description:
- The list of Origins eligible to receive CORS response headers.
- - |
- Note: "*" is permitted in the list of origins, and means "any
- Origin".
+ - 'Note: "*" is permitted in the list of origins, and means "any Origin".'
required: false
response_header:
description:
- - The list of HTTP headers other than the simple response
- headers to give permission for the user-agent to share across
- domains.
+ - The list of HTTP headers other than the simple response headers to give permission
+ for the user-agent to share across domains.
required: false
+ default_object_acl:
+ description:
+ - Default access controls to apply to new objects when no ACL is provided.
+ required: false
+ version_added: 2.7
+ suboptions:
+ bucket:
+ description:
+ - The name of the bucket.
+ required: true
+ domain:
+ description:
+ - The domain associated with the entity.
+ required: false
+ email:
+ description:
+ - The email address associated with the entity.
+ required: false
+ entity:
+ description:
+ - 'The entity holding the permission, in one of the following forms: user-userId
+ user-email group-groupId group-email domain-domain project-team-projectId allUsers
+ allAuthenticatedUsers Examples: The user liz@example.com would be
+ user-liz@example.com.'
+ - The group example@googlegroups.com would be group-example@googlegroups.com.
+ - To refer to all members of the Google Apps for Business domain example.com, the
+ entity would be domain-example.com.
+ required: true
+ entity_id:
+ description:
+ - The ID for the entity.
+ required: false
+ generation:
+ description:
+ - The content generation of the object, if applied to an object.
+ required: false
+ id:
+ description:
+ - The ID of the access-control entry.
+ required: false
+ object:
+ description:
+ - The name of the object, if applied to an object.
+ required: false
+ project_team:
+ description:
+ - The project team associated with the entity.
+ required: false
+ suboptions:
+ project_number:
+ description:
+ - The project team associated with the entity.
+ required: false
+ team:
+ description:
+ - The team.
+ required: false
+ choices: ['editors', 'owners', 'viewers']
+ role:
+ description:
+ - The access permission for the entity.
+ required: false
+ choices: ['OWNER', 'READER']
lifecycle:
description:
- The bucket's lifecycle configuration.
- - |
- See https://developers.google.com/storage/docs/lifecycle for more
- information.
+ - See U(https://developers.google.com/storage/docs/lifecycle) for more information.
required: false
suboptions:
rule:
description:
- - A lifecycle management rule, which is made of an action to
- take and the condition(s) under which the action will be taken.
+ - A lifecycle management rule, which is made of an action to take and the condition(s)
+ under which the action will be taken.
required: false
suboptions:
action:
@@ -161,13 +212,11 @@ options:
suboptions:
storage_class:
description:
- - Target storage class. Required iff the type of the
- action is SetStorageClass.
+ - Target storage class. Required iff the type of the action is SetStorageClass.
required: false
type:
description:
- - Type of the action. Currently, only Delete and
- SetStorageClass are supported.
+ - Type of the action. Currently, only Delete and SetStorageClass are supported.
required: false
choices: ['Delete', 'SetStorageClass']
condition:
@@ -177,53 +226,47 @@ options:
suboptions:
age_days:
description:
- - Age of an object (in days). This condition is
- satisfied when an object reaches the specified age.
+ - Age of an object (in days). This condition is satisfied when an object reaches the
+ specified age.
required: false
created_before:
description:
- - A date in RFC 3339 format with only the date part (for
- instance, "2013-01-15"). This condition is satisfied
- when an object is created before midnight of the
- specified date in UTC.
+ - A date in RFC 3339 format with only the date part (for instance, "2013-01-15").
+ This condition is satisfied when an object is created before midnight of the specified
+ date in UTC.
required: false
is_live:
description:
- - Relevant only for versioned objects. If the value is
- true, this condition matches live objects; if the
- value is false, it matches archived objects.
+ - Relevant only for versioned objects. If the value is true, this condition matches
+ live objects; if the value is false, it matches archived objects.
required: false
type: bool
matches_storage_class:
description:
- - Objects having any of the storage classes specified by
- this condition will be matched. Values include
- MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE,
- STANDARD, and DURABLE_REDUCED_AVAILABILITY.
+ - Objects having any of the storage classes specified by this condition will be matched.
+ Values include MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, STANDARD, and DURABLE_REDUCED_AVAILABILITY.
required: false
num_newer_versions:
description:
- - Relevant only for versioned objects. If the value is
- N, this condition is satisfied when there are at least
- N versions (including the live version) newer than
- this version of the object.
+ - Relevant only for versioned objects. If the value is N, this condition is satisfied
+ when there are at least N versions (including the live version) newer than this
+ version of the object.
required: false
location:
description:
- - The location of the bucket. Object data for objects in the bucket
- resides in physical storage within this region. Defaults to US.
- See the developer's guide for the authoritative list.
+ - The location of the bucket. Object data for objects in the bucket resides in physical
+ storage within this region. Defaults to US. See the developer's guide for the authoritative
+ list.
required: false
logging:
description:
- - The bucket's logging configuration, which defines the destination
- bucket and optional name prefix for the current bucket's logs.
+ - The bucket's logging configuration, which defines the destination bucket and optional
+ name prefix for the current bucket's logs.
required: false
suboptions:
log_bucket:
description:
- - The destination bucket where the current bucket's logs should
- be placed.
+ - The destination bucket where the current bucket's logs should be placed.
required: false
log_object_prefix:
description:
@@ -239,8 +282,7 @@ options:
required: false
owner:
description:
- - The owner of the bucket. This is always the project team's owner
- group.
+ - The owner of the bucket. This is always the project team's owner group.
required: false
suboptions:
entity:
@@ -253,13 +295,11 @@ options:
required: false
storage_class:
description:
- - The bucket's default storage class, used whenever no storageClass
- is specified for a newly-created object. This defines how objects
- in the bucket are stored and determines the SLA and the cost of
- storage.
- - Values include MULTI_REGIONAL, REGIONAL, STANDARD, NEARLINE,
- COLDLINE, and DURABLE_REDUCED_AVAILABILITY. If this value is not
- specified when the bucket is created, it will default to STANDARD.
+ - The bucket's default storage class, used whenever no storageClass is specified for
+ a newly-created object. This defines how objects in the bucket are stored and determines
+ the SLA and the cost of storage.
+ - Values include MULTI_REGIONAL, REGIONAL, STANDARD, NEARLINE, COLDLINE, and DURABLE_REDUCED_AVAILABILITY.
+ If this value is not specified when the bucket is created, it will default to STANDARD.
For more information, see storage classes.
required: false
choices: ['MULTI_REGIONAL', 'REGIONAL', 'STANDARD', 'NEARLINE', 'COLDLINE', 'DURABLE_REDUCED_AVAILABILITY']
@@ -275,24 +315,21 @@ options:
type: bool
website:
description:
- - The bucket's website configuration, controlling how the service
- behaves when accessing bucket contents as a web site. See the
- Static Website Examples for more information.
+ - The bucket's website configuration, controlling how the service behaves when accessing
+ bucket contents as a web site. See the Static Website Examples for more information.
required: false
suboptions:
main_page_suffix:
description:
- - If the requested object path is missing, the service will
- ensure the path has a trailing '/', append this suffix, and
- attempt to retrieve the resulting object. This allows the
- creation of index.html objects to represent directory pages.
+ - If the requested object path is missing, the service will ensure the path has a
+ trailing '/', append this suffix, and attempt to retrieve the resulting object.
+ This allows the creation of index.html objects to represent directory pages.
required: false
not_found_page:
description:
- - If the requested object path is missing, and any
- mainPageSuffix object is missing, if applicable, the service
- will return the named object from this bucket as the content
- for a 404 Not Found result.
+ - If the requested object path is missing, and any mainPageSuffix object is missing,
+ if applicable, the service will return the named object from this bucket as the
+ content for a 404 Not Found result.
required: false
project:
description:
@@ -300,25 +337,17 @@ options:
required: false
predefined_default_object_acl:
description:
- - Apply a predefined set of default object access controls to this
- bucket.
- - |
- Acceptable values are: - "authenticatedRead": Object owner gets
- OWNER access, and allAuthenticatedUsers get READER access.
- - |
- - "bucketOwnerFullControl": Object owner gets OWNER access, and
- project team owners get OWNER access.
- - |
- - "bucketOwnerRead": Object owner gets OWNER access, and project
- team owners get READER access.
- - |
- - "private": Object owner gets OWNER access.
- - |
- - "projectPrivate": Object owner gets OWNER access, and project
- team members get access according to their roles.
- - |
- - "publicRead": Object owner gets OWNER access, and allUsers get
- READER access.
+ - Apply a predefined set of default object access controls to this bucket.
+ - 'Acceptable values are: - "authenticatedRead": Object owner gets OWNER access,
+ and allAuthenticatedUsers get READER access.'
+ - '- "bucketOwnerFullControl": Object owner gets OWNER access, and project team
+ owners get OWNER access.'
+ - '- "bucketOwnerRead": Object owner gets OWNER access, and project team owners
+ get READER access.'
+ - '- "private": Object owner gets OWNER access.'
+ - '- "projectPrivate": Object owner gets OWNER access, and project team members
+ get access according to their roles.'
+ - '- "publicRead": Object owner gets OWNER access, and allUsers get READER access.'
required: false
choices: ['authenticatedRead', 'bucketOwnerFullControl', 'bucketOwnerRead', 'private', 'projectPrivate', 'publicRead']
extends_documentation_fragment: gcp
@@ -327,12 +356,10 @@ extends_documentation_fragment: gcp
EXAMPLES = '''
- name: create a bucket
gcp_storage_bucket:
- name: 'ansible-storage-module'
- project: testProject
- auth_kind: service_account
- service_account_file: /tmp/auth.pem
- scopes:
- - https://www.googleapis.com/auth/devstorage.full_control
+ name: ansible-storage-module
+ project: "test_project"
+ auth_kind: "service_account"
+ service_account_file: "/tmp/auth.pem"
state: present
'''
@@ -345,7 +372,7 @@ RETURN = '''
contains:
bucket:
description:
- - A reference to Bucket resource.
+ - The name of the bucket.
returned: success
type: dict
domain:
@@ -360,16 +387,13 @@ RETURN = '''
type: str
entity:
description:
- - |
- The entity holding the permission, in one of the following
- forms: user-userId user-email group-groupId
- group-email domain-domain project-team-projectId
- allUsers allAuthenticatedUsers Examples: The user
- liz@example.com would be user-liz@example.com.
- - The group example@googlegroups.com would be
- group-example@googlegroups.com.
- - To refer to all members of the Google Apps for Business domain
- example.com, the entity would be domain-example.com.
+ - 'The entity holding the permission, in one of the following forms: user-userId
+ user-email group-groupId group-email domain-domain project-team-projectId allUsers
+ allAuthenticatedUsers Examples: The user liz@example.com would be
+ user-liz@example.com.'
+ - The group example@googlegroups.com would be group-example@googlegroups.com.
+ - To refer to all members of the Google Apps for Business domain example.com, the
+ entity would be domain-example.com.
returned: success
type: str
entity_id:
@@ -411,52 +435,117 @@ RETURN = '''
contains:
max_age_seconds:
description:
- - The value, in seconds, to return in the Access-Control-Max-Age
- header used in preflight responses.
+ - The value, in seconds, to return in the Access-Control-Max-Age header used in preflight
+ responses.
returned: success
type: int
method:
description:
- - |
- The list of HTTP methods on which to include CORS response
- headers, (GET, OPTIONS, POST, etc) Note: "*" is permitted in
- the list of methods, and means "any method".
+ - 'The list of HTTP methods on which to include CORS response headers, (GET, OPTIONS,
+ POST, etc) Note: "*" is permitted in the list of methods, and means "any method".'
returned: success
type: list
origin:
description:
- The list of Origins eligible to receive CORS response headers.
- - |
- Note: "*" is permitted in the list of origins, and means "any
- Origin".
+ - 'Note: "*" is permitted in the list of origins, and means "any Origin".'
returned: success
type: list
response_header:
description:
- - The list of HTTP headers other than the simple response
- headers to give permission for the user-agent to share across
- domains.
+ - The list of HTTP headers other than the simple response headers to give permission
+ for the user-agent to share across domains.
returned: success
type: list
+ default_object_acl:
+ description:
+ - Default access controls to apply to new objects when no ACL is provided.
+ returned: success
+ type: complex
+ contains:
+ bucket:
+ description:
+ - The name of the bucket.
+ returned: success
+ type: dict
+ domain:
+ description:
+ - The domain associated with the entity.
+ returned: success
+ type: str
+ email:
+ description:
+ - The email address associated with the entity.
+ returned: success
+ type: str
+ entity:
+ description:
+ - 'The entity holding the permission, in one of the following forms: user-userId
+ user-email group-groupId group-email domain-domain project-team-projectId allUsers
+ allAuthenticatedUsers Examples: The user liz@example.com would be
+ user-liz@example.com.'
+ - The group example@googlegroups.com would be group-example@googlegroups.com.
+ - To refer to all members of the Google Apps for Business domain example.com, the
+ entity would be domain-example.com.
+ returned: success
+ type: str
+ entity_id:
+ description:
+ - The ID for the entity.
+ returned: success
+ type: str
+ generation:
+ description:
+ - The content generation of the object, if applied to an object.
+ returned: success
+ type: int
+ id:
+ description:
+ - The ID of the access-control entry.
+ returned: success
+ type: str
+ object:
+ description:
+ - The name of the object, if applied to an object.
+ returned: success
+ type: str
+ project_team:
+ description:
+ - The project team associated with the entity.
+ returned: success
+ type: complex
+ contains:
+ project_number:
+ description:
+ - The project team associated with the entity.
+ returned: success
+ type: str
+ team:
+ description:
+ - The team.
+ returned: success
+ type: str
+ role:
+ description:
+ - The access permission for the entity.
+ returned: success
+ type: str
id:
description:
- - The ID of the bucket. For buckets, the id and name properities are
- the same.
+ - The ID of the bucket. For buckets, the id and name properities are the same.
returned: success
type: str
lifecycle:
description:
- The bucket's lifecycle configuration.
- - |
- See https://developers.google.com/storage/docs/lifecycle for more
- information.
+ - See U(https://developers.google.com/storage/docs/lifecycle) for more information.
returned: success
type: complex
contains:
rule:
description:
- - A lifecycle management rule, which is made of an action to
- take and the condition(s) under which the action will be taken.
+ - A lifecycle management rule, which is made of an action to take and the condition(s)
+ under which the action will be taken.
returned: success
type: complex
contains:
@@ -468,14 +557,12 @@ RETURN = '''
contains:
storage_class:
description:
- - Target storage class. Required iff the type of the
- action is SetStorageClass.
+ - Target storage class. Required iff the type of the action is SetStorageClass.
returned: success
type: str
type:
description:
- - Type of the action. Currently, only Delete and
- SetStorageClass are supported.
+ - Type of the action. Currently, only Delete and SetStorageClass are supported.
returned: success
type: str
condition:
@@ -486,59 +573,53 @@ RETURN = '''
contains:
age_days:
description:
- - Age of an object (in days). This condition is
- satisfied when an object reaches the specified age.
+ - Age of an object (in days). This condition is satisfied when an object reaches the
+ specified age.
returned: success
type: int
created_before:
description:
- - A date in RFC 3339 format with only the date part (for
- instance, "2013-01-15"). This condition is satisfied
- when an object is created before midnight of the
- specified date in UTC.
+ - A date in RFC 3339 format with only the date part (for instance, "2013-01-15").
+ This condition is satisfied when an object is created before midnight of the specified
+ date in UTC.
returned: success
type: str
is_live:
description:
- - Relevant only for versioned objects. If the value is
- true, this condition matches live objects; if the
- value is false, it matches archived objects.
+ - Relevant only for versioned objects. If the value is true, this condition matches
+ live objects; if the value is false, it matches archived objects.
returned: success
type: bool
matches_storage_class:
description:
- - Objects having any of the storage classes specified by
- this condition will be matched. Values include
- MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE,
- STANDARD, and DURABLE_REDUCED_AVAILABILITY.
+ - Objects having any of the storage classes specified by this condition will be matched.
+ Values include MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, STANDARD, and DURABLE_REDUCED_AVAILABILITY.
returned: success
type: list
num_newer_versions:
description:
- - Relevant only for versioned objects. If the value is
- N, this condition is satisfied when there are at least
- N versions (including the live version) newer than
- this version of the object.
+ - Relevant only for versioned objects. If the value is N, this condition is satisfied
+ when there are at least N versions (including the live version) newer than this
+ version of the object.
returned: success
type: int
location:
description:
- - The location of the bucket. Object data for objects in the bucket
- resides in physical storage within this region. Defaults to US.
- See the developer's guide for the authoritative list.
+ - The location of the bucket. Object data for objects in the bucket resides in physical
+ storage within this region. Defaults to US. See the developer's guide for the authoritative
+ list.
returned: success
type: str
logging:
description:
- - The bucket's logging configuration, which defines the destination
- bucket and optional name prefix for the current bucket's logs.
+ - The bucket's logging configuration, which defines the destination bucket and optional
+ name prefix for the current bucket's logs.
returned: success
type: complex
contains:
log_bucket:
description:
- - The destination bucket where the current bucket's logs should
- be placed.
+ - The destination bucket where the current bucket's logs should be placed.
returned: success
type: str
log_object_prefix:
@@ -558,8 +639,7 @@ RETURN = '''
type: str
owner:
description:
- - The owner of the bucket. This is always the project team's owner
- group.
+ - The owner of the bucket. This is always the project team's owner group.
returned: success
type: complex
contains:
@@ -580,13 +660,11 @@ RETURN = '''
type: int
storage_class:
description:
- - The bucket's default storage class, used whenever no storageClass
- is specified for a newly-created object. This defines how objects
- in the bucket are stored and determines the SLA and the cost of
- storage.
- - Values include MULTI_REGIONAL, REGIONAL, STANDARD, NEARLINE,
- COLDLINE, and DURABLE_REDUCED_AVAILABILITY. If this value is not
- specified when the bucket is created, it will default to STANDARD.
+ - The bucket's default storage class, used whenever no storageClass is specified for
+ a newly-created object. This defines how objects in the bucket are stored and determines
+ the SLA and the cost of storage.
+ - Values include MULTI_REGIONAL, REGIONAL, STANDARD, NEARLINE, COLDLINE, and DURABLE_REDUCED_AVAILABILITY.
+ If this value is not specified when the bucket is created, it will default to STANDARD.
For more information, see storage classes.
returned: success
type: str
@@ -613,26 +691,23 @@ RETURN = '''
type: bool
website:
description:
- - The bucket's website configuration, controlling how the service
- behaves when accessing bucket contents as a web site. See the
- Static Website Examples for more information.
+ - The bucket's website configuration, controlling how the service behaves when accessing
+ bucket contents as a web site. See the Static Website Examples for more information.
returned: success
type: complex
contains:
main_page_suffix:
description:
- - If the requested object path is missing, the service will
- ensure the path has a trailing '/', append this suffix, and
- attempt to retrieve the resulting object. This allows the
- creation of index.html objects to represent directory pages.
+ - If the requested object path is missing, the service will ensure the path has a
+ trailing '/', append this suffix, and attempt to retrieve the resulting object.
+ This allows the creation of index.html objects to represent directory pages.
returned: success
type: str
not_found_page:
description:
- - If the requested object path is missing, and any
- mainPageSuffix object is missing, if applicable, the service
- will return the named object from this bucket as the content
- for a 404 Not Found result.
+ - If the requested object path is missing, and any mainPageSuffix object is missing,
+ if applicable, the service will return the named object from this bucket as the
+ content for a 404 Not Found result.
returned: success
type: str
project:
@@ -642,25 +717,17 @@ RETURN = '''
type: str
predefined_default_object_acl:
description:
- - Apply a predefined set of default object access controls to this
- bucket.
- - |
- Acceptable values are: - "authenticatedRead": Object owner gets
- OWNER access, and allAuthenticatedUsers get READER access.
- - |
- - "bucketOwnerFullControl": Object owner gets OWNER access, and
- project team owners get OWNER access.
- - |
- - "bucketOwnerRead": Object owner gets OWNER access, and project
- team owners get READER access.
- - |
- - "private": Object owner gets OWNER access.
- - |
- - "projectPrivate": Object owner gets OWNER access, and project
- team members get access according to their roles.
- - |
- - "publicRead": Object owner gets OWNER access, and allUsers get
- READER access.
+ - Apply a predefined set of default object access controls to this bucket.
+ - 'Acceptable values are: - "authenticatedRead": Object owner gets OWNER access,
+ and allAuthenticatedUsers get READER access.'
+ - '- "bucketOwnerFullControl": Object owner gets OWNER access, and project team
+ owners get OWNER access.'
+ - '- "bucketOwnerRead": Object owner gets OWNER access, and project team owners
+ get READER access.'
+ - '- "private": Object owner gets OWNER access.'
+ - '- "projectPrivate": Object owner gets OWNER access, and project team members
+ get access according to their roles.'
+ - '- "publicRead": Object owner gets OWNER access, and allUsers get READER access.'
returned: success
type: str
'''
@@ -702,6 +769,21 @@ def main():
origin=dict(type='list', elements='str'),
response_header=dict(type='list', elements='str')
)),
+ default_object_acl=dict(type='list', elements='dict', options=dict(
+ bucket=dict(required=True, type='dict'),
+ domain=dict(type='str'),
+ email=dict(type='str'),
+ entity=dict(required=True, type='str'),
+ entity_id=dict(type='str'),
+ generation=dict(type='int'),
+ id=dict(type='str'),
+ object=dict(type='str'),
+ project_team=dict(type='dict', options=dict(
+ project_number=dict(type='str'),
+ team=dict(type='str', choices=['editors', 'owners', 'viewers'])
+ )),
+ role=dict(type='str', choices=['OWNER', 'READER'])
+ )),
lifecycle=dict(type='dict', options=dict(
rule=dict(type='list', elements='dict', options=dict(
action=dict(type='dict', options=dict(
@@ -746,6 +828,9 @@ def main():
)
)
+ if not module.params['scopes']:
+ module.params['scopes'] = ['https://www.googleapis.com/auth/devstorage.full_control']
+
state = module.params['state']
kind = 'storage#bucket'
@@ -793,17 +878,18 @@ def resource_to_request(module):
u'kind': 'storage#bucket',
u'project': module.params.get('project'),
u'predefinedDefaultObjectAcl': module.params.get('predefined_default_object_acl'),
- u'acl': BucketAclArray(module.params.get('acl', [])).to_request(),
- u'cors': BucketCorsArray(module.params.get('cors', [])).to_request(),
- u'lifecycle': BucketLifecycle(module.params.get('lifecycle', {})).to_request(),
+ u'acl': BucketAclArray(module.params.get('acl', []), module).to_request(),
+ u'cors': BucketCorsArray(module.params.get('cors', []), module).to_request(),
+ u'defaultObjectAcl': BucketDefaultObjectAclArray(module.params.get('default_object_acl', []), module).to_request(),
+ u'lifecycle': BucketLifecycle(module.params.get('lifecycle', {}), module).to_request(),
u'location': module.params.get('location'),
- u'logging': BucketLogging(module.params.get('logging', {})).to_request(),
+ u'logging': BucketLogging(module.params.get('logging', {}), module).to_request(),
u'metageneration': module.params.get('metageneration'),
u'name': module.params.get('name'),
- u'owner': BucketOwner(module.params.get('owner', {})).to_request(),
+ u'owner': BucketOwner(module.params.get('owner', {}), module).to_request(),
u'storageClass': module.params.get('storage_class'),
- u'versioning': BucketVersioning(module.params.get('versioning', {})).to_request(),
- u'website': BucketWebsite(module.params.get('website', {})).to_request()
+ u'versioning': BucketVersioning(module.params.get('versioning', {}), module).to_request(),
+ u'website': BucketWebsite(module.params.get('website', {}), module).to_request()
}
return_vals = {}
for k, v in request.items():
@@ -871,26 +957,28 @@ def is_different(module, response):
# This is for doing comparisons with Ansible's current parameters.
def response_to_hash(module, response):
return {
- u'acl': BucketAclArray(response.get(u'acl', [])).from_response(),
- u'cors': BucketCorsArray(response.get(u'cors', [])).from_response(),
+ u'acl': BucketAclArray(response.get(u'acl', []), module).from_response(),
+ u'cors': BucketCorsArray(response.get(u'cors', []), module).from_response(),
+ u'defaultObjectAcl': BucketDefaultObjectAclArray(module.params.get('default_object_acl', []), module).to_request(),
u'id': response.get(u'id'),
- u'lifecycle': BucketLifecycle(response.get(u'lifecycle', {})).from_response(),
+ u'lifecycle': BucketLifecycle(response.get(u'lifecycle', {}), module).from_response(),
u'location': response.get(u'location'),
- u'logging': BucketLogging(response.get(u'logging', {})).from_response(),
+ u'logging': BucketLogging(response.get(u'logging', {}), module).from_response(),
u'metageneration': response.get(u'metageneration'),
u'name': response.get(u'name'),
- u'owner': BucketOwner(response.get(u'owner', {})).from_response(),
+ u'owner': BucketOwner(response.get(u'owner', {}), module).from_response(),
u'projectNumber': response.get(u'projectNumber'),
u'storageClass': response.get(u'storageClass'),
u'timeCreated': response.get(u'timeCreated'),
u'updated': response.get(u'updated'),
- u'versioning': BucketVersioning(response.get(u'versioning', {})).from_response(),
- u'website': BucketWebsite(response.get(u'website', {})).from_response()
+ u'versioning': BucketVersioning(response.get(u'versioning', {}), module).from_response(),
+ u'website': BucketWebsite(response.get(u'website', {}), module).from_response()
}
class BucketAclArray(object):
- def __init__(self, request):
+ def __init__(self, request, module):
+ self.module = module
if request:
self.request = request
else:
@@ -916,7 +1004,7 @@ class BucketAclArray(object):
u'entity': item.get('entity'),
u'entityId': item.get('entity_id'),
u'id': item.get('id'),
- u'projectTeam': BucketProjectTeam(item.get('project_team', {})).to_request(),
+ u'projectTeam': BucketProjectTeam(item.get('project_team', {}), self.module).to_request(),
u'role': item.get('role')
})
@@ -928,13 +1016,14 @@ class BucketAclArray(object):
u'entity': item.get(u'entity'),
u'entityId': item.get(u'entityId'),
u'id': item.get(u'id'),
- u'projectTeam': BucketProjectTeam(item.get(u'projectTeam', {})).from_response(),
+ u'projectTeam': BucketProjectTeam(item.get(u'projectTeam', {}), self.module).from_response(),
u'role': item.get(u'role')
})
class BucketProjectTeam(object):
- def __init__(self, request):
+ def __init__(self, request, module):
+ self.module = module
if request:
self.request = request
else:
@@ -954,7 +1043,8 @@ class BucketProjectTeam(object):
class BucketCorsArray(object):
- def __init__(self, request):
+ def __init__(self, request, module):
+ self.module = module
if request:
self.request = request
else:
@@ -989,8 +1079,79 @@ class BucketCorsArray(object):
})
+class BucketDefaultObjectAclArray(object):
+ def __init__(self, request, module):
+ self.module = module
+ if request:
+ self.request = request
+ else:
+ self.request = []
+
+ def to_request(self):
+ items = []
+ for item in self.request:
+ items.append(self._request_for_item(item))
+ return items
+
+ def from_response(self):
+ items = []
+ for item in self.request:
+ items.append(self._response_from_item(item))
+ return items
+
+ def _request_for_item(self, item):
+ return remove_nones_from_dict({
+ u'bucket': replace_resource_dict(item.get(u'bucket', {}), 'name'),
+ u'domain': item.get('domain'),
+ u'email': item.get('email'),
+ u'entity': item.get('entity'),
+ u'entityId': item.get('entity_id'),
+ u'generation': item.get('generation'),
+ u'id': item.get('id'),
+ u'object': item.get('object'),
+ u'projectTeam': BucketProjectTeam(item.get('project_team', {}), self.module).to_request(),
+ u'role': item.get('role')
+ })
+
+ def _response_from_item(self, item):
+ return remove_nones_from_dict({
+ u'bucket': item.get(u'bucket'),
+ u'domain': item.get(u'domain'),
+ u'email': item.get(u'email'),
+ u'entity': item.get(u'entity'),
+ u'entityId': item.get(u'entityId'),
+ u'generation': item.get(u'generation'),
+ u'id': item.get(u'id'),
+ u'object': item.get(u'object'),
+ u'projectTeam': BucketProjectTeam(item.get(u'projectTeam', {}), self.module).from_response(),
+ u'role': item.get(u'role')
+ })
+
+
+class BucketProjectTeam(object):
+ def __init__(self, request, module):
+ self.module = module
+ if request:
+ self.request = request
+ else:
+ self.request = {}
+
+ def to_request(self):
+ return remove_nones_from_dict({
+ u'projectNumber': self.request.get('project_number'),
+ u'team': self.request.get('team')
+ })
+
+ def from_response(self):
+ return remove_nones_from_dict({
+ u'projectNumber': self.request.get(u'projectNumber'),
+ u'team': self.request.get(u'team')
+ })
+
+
class BucketLifecycle(object):
- def __init__(self, request):
+ def __init__(self, request, module):
+ self.module = module
if request:
self.request = request
else:
@@ -998,17 +1159,18 @@ class BucketLifecycle(object):
def to_request(self):
return remove_nones_from_dict({
- u'rule': BucketRuleArray(self.request.get('rule', [])).to_request()
+ u'rule': BucketRuleArray(self.request.get('rule', []), self.module).to_request()
})
def from_response(self):
return remove_nones_from_dict({
- u'rule': BucketRuleArray(self.request.get(u'rule', [])).from_response()
+ u'rule': BucketRuleArray(self.request.get(u'rule', []), self.module).from_response()
})
class BucketRuleArray(object):
- def __init__(self, request):
+ def __init__(self, request, module):
+ self.module = module
if request:
self.request = request
else:
@@ -1028,19 +1190,20 @@ class BucketRuleArray(object):
def _request_for_item(self, item):
return remove_nones_from_dict({
- u'action': BucketAction(item.get('action', {})).to_request(),
- u'condition': BucketCondition(item.get('condition', {})).to_request()
+ u'action': BucketAction(item.get('action', {}), self.module).to_request(),
+ u'condition': BucketCondition(item.get('condition', {}), self.module).to_request()
})
def _response_from_item(self, item):
return remove_nones_from_dict({
- u'action': BucketAction(item.get(u'action', {})).from_response(),
- u'condition': BucketCondition(item.get(u'condition', {})).from_response()
+ u'action': BucketAction(item.get(u'action', {}), self.module).from_response(),
+ u'condition': BucketCondition(item.get(u'condition', {}), self.module).from_response()
})
class BucketAction(object):
- def __init__(self, request):
+ def __init__(self, request, module):
+ self.module = module
if request:
self.request = request
else:
@@ -1060,7 +1223,8 @@ class BucketAction(object):
class BucketCondition(object):
- def __init__(self, request):
+ def __init__(self, request, module):
+ self.module = module
if request:
self.request = request
else:
@@ -1086,7 +1250,8 @@ class BucketCondition(object):
class BucketLogging(object):
- def __init__(self, request):
+ def __init__(self, request, module):
+ self.module = module
if request:
self.request = request
else:
@@ -1106,7 +1271,8 @@ class BucketLogging(object):
class BucketOwner(object):
- def __init__(self, request):
+ def __init__(self, request, module):
+ self.module = module
if request:
self.request = request
else:
@@ -1126,7 +1292,8 @@ class BucketOwner(object):
class BucketVersioning(object):
- def __init__(self, request):
+ def __init__(self, request, module):
+ self.module = module
if request:
self.request = request
else:
@@ -1144,7 +1311,8 @@ class BucketVersioning(object):
class BucketWebsite(object):
- def __init__(self, request):
+ def __init__(self, request, module):
+ self.module = module
if request:
self.request = request
else:
diff --git a/test/integration/targets/gcp_storage_bucket/tasks/main.yml b/test/integration/targets/gcp_storage_bucket/tasks/main.yml
index 2becee5214..56363734e1 100644
--- a/test/integration/targets/gcp_storage_bucket/tasks/main.yml
+++ b/test/integration/targets/gcp_storage_bucket/tasks/main.yml
@@ -15,22 +15,18 @@
# Pre-test setup
- name: delete a bucket
gcp_storage_bucket:
- name: 'ansible-storage-module'
+ name: ansible-storage-module
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
- scopes:
- - https://www.googleapis.com/auth/devstorage.full_control
state: absent
#----------------------------------------------------------
- name: create a bucket
gcp_storage_bucket:
- name: 'ansible-storage-module'
+ name: ansible-storage-module
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
- scopes:
- - https://www.googleapis.com/auth/devstorage.full_control
state: present
register: result
- name: assert changed is true
@@ -41,12 +37,10 @@
# ----------------------------------------------------------------------------
- name: create a bucket that already exists
gcp_storage_bucket:
- name: 'ansible-storage-module'
+ name: ansible-storage-module
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
- scopes:
- - https://www.googleapis.com/auth/devstorage.full_control
state: present
register: result
- name: assert changed is false
@@ -57,12 +51,10 @@
#----------------------------------------------------------
- name: delete a bucket
gcp_storage_bucket:
- name: 'ansible-storage-module'
+ name: ansible-storage-module
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
- scopes:
- - https://www.googleapis.com/auth/devstorage.full_control
state: absent
register: result
- name: assert changed is true
@@ -73,12 +65,10 @@
# ----------------------------------------------------------------------------
- name: delete a bucket that does not exist
gcp_storage_bucket:
- name: 'ansible-storage-module'
+ name: ansible-storage-module
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
- scopes:
- - https://www.googleapis.com/auth/devstorage.full_control
state: absent
register: result
- name: assert changed is false