Bug fixes for gcp_compute_disk (#42806)

pull/44018/merge
Alex Stephen 6 years ago committed by Ryan Brown
parent 146c126780
commit c8418a709b

@ -61,6 +61,11 @@ options:
- An optional description of this resource. Provide this property when you create - An optional description of this resource. Provide this property when you create
the resource. the resource.
required: false required: false
labels:
description:
- Labels to apply to this disk. A list of key->value pairs.
required: false
version_added: 2.7
licenses: licenses:
description: description:
- Any applicable publicly visible licenses. - Any applicable publicly visible licenses.
@ -73,7 +78,7 @@ options:
which means the first character must be a lowercase letter, and all following characters which means the first character must be a lowercase letter, and all following characters
must be a dash, lowercase letter, or digit, except the last character, which cannot must be a dash, lowercase letter, or digit, except the last character, which cannot
be a dash. be a dash.
required: false required: true
size_gb: size_gb:
description: description:
- Size of the persistent disk, specified in GB. You can specify this field when creating - Size of the persistent disk, specified in GB. You can specify this field when creating
@ -82,6 +87,12 @@ options:
- If you specify this field along with sourceImage or sourceSnapshot, the value of - If you specify this field along with sourceImage or sourceSnapshot, the value of
sizeGb must not be less than the size of the sourceImage or the size of the snapshot. sizeGb must not be less than the size of the sourceImage or the size of the snapshot.
required: false required: false
type:
description:
- URL of the disk type resource describing which disk type to use to create the disk.
Provide this when creating the disk.
required: false
version_added: 2.7
source_image: source_image:
description: description:
- The source image used to create this disk. If the source image is deleted, this - The source image used to create this disk. If the source image is deleted, this
@ -98,18 +109,12 @@ options:
required: false required: false
zone: zone:
description: description:
- A reference to Zone resource. - A reference to the zone where the disk resides.
required: true required: true
disk_encryption_key: source_image_encryption_key:
description: description:
- Encrypts the disk using a customer-supplied encryption key. - The customer-supplied encryption key of the source image. Required if the source
- After you encrypt a disk with a customer-supplied key, you must provide the same image is protected by a customer-supplied encryption key.
key if you use the disk later (e.g. to create a disk snapshot or an image, or to
attach the disk to a virtual machine).
- Customer-supplied encryption keys do not protect access to metadata of the disk.
- If you do not provide an encryption key when creating the disk, then the disk will
be encrypted using an automatically generated key and you do not need to provide
a key to use the disk later.
required: false required: false
suboptions: suboptions:
raw_key: raw_key:
@ -122,10 +127,16 @@ options:
- The RFC 4648 base64 encoded SHA-256 hash of the customer-supplied encryption key - The RFC 4648 base64 encoded SHA-256 hash of the customer-supplied encryption key
that protects this resource. that protects this resource.
required: false required: false
source_image_encryption_key: disk_encryption_key:
description: description:
- The customer-supplied encryption key of the source image. Required if the source - Encrypts the disk using a customer-supplied encryption key.
image is protected by a customer-supplied encryption key. - After you encrypt a disk with a customer-supplied key, you must provide the same
key if you use the disk later (e.g. to create a disk snapshot or an image, or to
attach the disk to a virtual machine).
- Customer-supplied encryption keys do not protect access to metadata of the disk.
- If you do not provide an encryption key when creating the disk, then the disk will
be encrypted using an automatically generated key and you do not need to provide
a key to use the disk later.
required: false required: false
suboptions: suboptions:
raw_key: raw_key:
@ -140,12 +151,10 @@ options:
required: false required: false
source_snapshot: source_snapshot:
description: description:
- 'The source snapshot used to create this disk. You can provide - 'The source snapshot used to create this disk. You can provide this as a partial or
this as a partial or full URL to the resource. For example, the full URL to the resource. For example, the following are valid values: *
following are valid values: * `U(https://www.googleapis.com/compute/v1/projects/project/global/snapshots/snapshot`)
U(https://www.googleapis.com/compute/v1/projects/project/global/) * `projects/project/global/snapshots/snapshot` * `global/snapshots/snapshot` .'
snapshots/snapshot * projects/project/global/snapshots/snapshot *
global/snapshots/snapshot .'
required: false required: false
source_snapshot_encryption_key: source_snapshot_encryption_key:
description: description:
@ -164,21 +173,22 @@ options:
that protects this resource. that protects this resource.
required: false required: false
extends_documentation_fragment: gcp extends_documentation_fragment: gcp
notes:
- "API Reference: U(https://cloud.google.com/compute/docs/reference/latest/disks)"
- "Adding a persistent disk: U(https://cloud.google.com/compute/docs/disks/add-persistent-disk)"
''' '''
EXAMPLES = ''' EXAMPLES = '''
- name: create a disk - name: create a disk
gcp_compute_disk: gcp_compute_disk:
name: testObject name: "test_object"
size_gb: 50 size_gb: 50
disk_encryption_key: disk_encryption_key:
raw_key: 'SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=' raw_key: SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=
zone: 'us-central1-a' zone: us-central1-a
project: testProject project: "test_project"
auth_kind: service_account auth_kind: "service_account"
service_account_file: /tmp/auth.pem service_account_file: "/tmp/auth.pem"
scopes:
- https://www.googleapis.com/auth/compute
state: present state: present
''' '''
@ -209,6 +219,11 @@ RETURN = '''
- Last dettach timestamp in RFC3339 text format. - Last dettach timestamp in RFC3339 text format.
returned: success returned: success
type: str type: str
labels:
description:
- Labels to apply to this disk. A list of key->value pairs.
returned: success
type: dict
licenses: licenses:
description: description:
- Any applicable publicly visible licenses. - Any applicable publicly visible licenses.
@ -233,6 +248,18 @@ RETURN = '''
sizeGb must not be less than the size of the sourceImage or the size of the snapshot. sizeGb must not be less than the size of the sourceImage or the size of the snapshot.
returned: success returned: success
type: int type: int
type:
description:
- URL of the disk type resource describing which disk type to use to create the disk.
Provide this when creating the disk.
returned: success
type: str
users:
description:
- 'Links to the users of the disk (attached instances) in form: project/zones/zone/instances/instance
.'
returned: success
type: list
source_image: source_image:
description: description:
- The source image used to create this disk. If the source image is deleted, this - The source image used to create this disk. If the source image is deleted, this
@ -248,33 +275,15 @@ RETURN = '''
.' .'
returned: success returned: success
type: str type: str
type:
description:
- URL of the disk type resource describing which disk type to use to create the disk.
Provide this when creating the disk.
returned: success
type: str
users:
description:
- 'Links to the users of the disk (attached instances) in form: project/zones/zone/instances/instance
.'
returned: success
type: list
zone: zone:
description: description:
- A reference to Zone resource. - A reference to the zone where the disk resides.
returned: success returned: success
type: str type: str
disk_encryption_key: source_image_encryption_key:
description: description:
- Encrypts the disk using a customer-supplied encryption key. - The customer-supplied encryption key of the source image. Required if the source
- After you encrypt a disk with a customer-supplied key, you must provide the same image is protected by a customer-supplied encryption key.
key if you use the disk later (e.g. to create a disk snapshot or an image, or to
attach the disk to a virtual machine).
- Customer-supplied encryption keys do not protect access to metadata of the disk.
- If you do not provide an encryption key when creating the disk, then the disk will
be encrypted using an automatically generated key and you do not need to provide
a key to use the disk later.
returned: success returned: success
type: complex type: complex
contains: contains:
@ -290,10 +299,25 @@ RETURN = '''
that protects this resource. that protects this resource.
returned: success returned: success
type: str type: str
source_image_encryption_key: source_image_id:
description: description:
- The customer-supplied encryption key of the source image. Required if the source - The ID value of the image used to create this disk. This value identifies the exact
image is protected by a customer-supplied encryption key. image that was used to create this persistent disk. For example, if you created
the persistent disk from an image that was later deleted and recreated under the
same name, the source image ID would identify the exact version of the image that
was used.
returned: success
type: str
disk_encryption_key:
description:
- Encrypts the disk using a customer-supplied encryption key.
- After you encrypt a disk with a customer-supplied key, you must provide the same
key if you use the disk later (e.g. to create a disk snapshot or an image, or to
attach the disk to a virtual machine).
- Customer-supplied encryption keys do not protect access to metadata of the disk.
- If you do not provide an encryption key when creating the disk, then the disk will
be encrypted using an automatically generated key and you do not need to provide
a key to use the disk later.
returned: success returned: success
type: complex type: complex
contains: contains:
@ -309,25 +333,14 @@ RETURN = '''
that protects this resource. that protects this resource.
returned: success returned: success
type: str type: str
source_image_id:
description:
- The ID value of the image used to create this disk. This value identifies the exact
image that was used to create this persistent disk. For example, if you created
the persistent disk from an image that was later deleted and recreated under the
same name, the source image ID would identify the exact version of the image that
was used.
returned: success
type: str
source_snapshot: source_snapshot:
description: description:
- 'The source snapshot used to create this disk. You can provide - 'The source snapshot used to create this disk. You can provide this as a partial or
this as a partial or full URL to the resource. For example, the full URL to the resource. For example, the following are valid values: *
following are valid values: * `U(https://www.googleapis.com/compute/v1/projects/project/global/snapshots/snapshot`)
U(https://www.googleapis.com/compute/v1/projects/project/global/) * `projects/project/global/snapshots/snapshot` * `global/snapshots/snapshot` .'
snapshots/snapshot * projects/project/global/snapshots/snapshot *
global/snapshots/snapshot .'
returned: success returned: success
type: str type: dict
source_snapshot_encryption_key: source_snapshot_encryption_key:
description: description:
- The customer-supplied encryption key of the source snapshot. Required if the source - The customer-supplied encryption key of the source snapshot. Required if the source
@ -364,6 +377,7 @@ RETURN = '''
from ansible.module_utils.gcp_utils import navigate_hash, GcpSession, GcpModule, GcpRequest, remove_nones_from_dict, replace_resource_dict from ansible.module_utils.gcp_utils import navigate_hash, GcpSession, GcpModule, GcpRequest, remove_nones_from_dict, replace_resource_dict
import json import json
import re
import time import time
################################################################################ ################################################################################
@ -378,20 +392,22 @@ def main():
argument_spec=dict( argument_spec=dict(
state=dict(default='present', choices=['present', 'absent'], type='str'), state=dict(default='present', choices=['present', 'absent'], type='str'),
description=dict(type='str'), description=dict(type='str'),
labels=dict(type='dict'),
licenses=dict(type='list', elements='str'), licenses=dict(type='list', elements='str'),
name=dict(type='str'), name=dict(required=True, type='str'),
size_gb=dict(type='int'), size_gb=dict(type='int'),
type=dict(type='str'),
source_image=dict(type='str'), source_image=dict(type='str'),
zone=dict(required=True, type='str'), zone=dict(required=True, type='str'),
disk_encryption_key=dict(type='dict', options=dict( source_image_encryption_key=dict(type='dict', options=dict(
raw_key=dict(type='str'), raw_key=dict(type='str'),
sha256=dict(type='str') sha256=dict(type='str')
)), )),
source_image_encryption_key=dict(type='dict', options=dict( disk_encryption_key=dict(type='dict', options=dict(
raw_key=dict(type='str'), raw_key=dict(type='str'),
sha256=dict(type='str') sha256=dict(type='str')
)), )),
source_snapshot=dict(type='str'), source_snapshot=dict(type='dict'),
source_snapshot_encryption_key=dict(type='dict', options=dict( source_snapshot_encryption_key=dict(type='dict', options=dict(
raw_key=dict(type='str'), raw_key=dict(type='str'),
sha256=dict(type='str') sha256=dict(type='str')
@ -399,6 +415,9 @@ def main():
) )
) )
if not module.params['scopes']:
module.params['scopes'] = ['https://www.googleapis.com/auth/compute']
state = module.params['state'] state = module.params['state']
kind = 'compute#disk' kind = 'compute#disk'
@ -408,10 +427,10 @@ def main():
if fetch: if fetch:
if state == 'present': if state == 'present':
if is_different(module, fetch): if is_different(module, fetch):
fetch = update(module, self_link(module), kind, fetch) fetch = update(module, self_link(module), kind)
changed = True changed = True
else: else:
delete(module, self_link(module), kind, fetch) delete(module, self_link(module), kind)
fetch = {} fetch = {}
changed = True changed = True
else: else:
@ -431,11 +450,11 @@ def create(module, link, kind):
return wait_for_operation(module, auth.post(link, resource_to_request(module))) return wait_for_operation(module, auth.post(link, resource_to_request(module)))
def update(module, link, kind, fetch): def update(module, link, kind):
module.fail_json(msg="Disk cannot be edited") module.fail_json(msg="Disk cannot be edited")
def delete(module, link, kind, fetch): def delete(module, link, kind):
auth = GcpSession(module, 'compute') auth = GcpSession(module, 'compute')
return wait_for_operation(module, auth.delete(link)) return wait_for_operation(module, auth.delete(link))
@ -443,13 +462,15 @@ def delete(module, link, kind, fetch):
def resource_to_request(module): def resource_to_request(module):
request = { request = {
u'kind': 'compute#disk', u'kind': 'compute#disk',
u'diskEncryptionKey': DiskDiskEncryKey(module.params.get('disk_encryption_key', {}), module).to_request(), u'sourceImageEncryptionKey': DiskSourceImageEncryptionKey(module.params.get('source_image_encryption_key', {}), module).to_request(),
u'sourceImageEncryptionKey': DiskSourImagEncrKey(module.params.get('source_image_encryption_key', {}), module).to_request(), u'diskEncryptionKey': DiskDiskEncryptionKey(module.params.get('disk_encryption_key', {}), module).to_request(),
u'sourceSnapshotEncryptionKey': DiskSourSnapEncrKey(module.params.get('source_snapshot_encryption_key', {}), module).to_request(), u'sourceSnapshotEncryptionKey': DiskSourceSnapshotEncryptionKey(module.params.get('source_snapshot_encryption_key', {}), module).to_request(),
u'description': module.params.get('description'), u'description': module.params.get('description'),
u'labels': module.params.get('labels'),
u'licenses': module.params.get('licenses'), u'licenses': module.params.get('licenses'),
u'name': module.params.get('name'), u'name': module.params.get('name'),
u'sizeGb': module.params.get('size_gb'), u'sizeGb': module.params.get('size_gb'),
u'type': disk_type_selflink(module.params.get('type'), module.params),
u'sourceImage': module.params.get('source_image') u'sourceImage': module.params.get('source_image')
} }
return_vals = {} return_vals = {}
@ -523,15 +544,25 @@ def response_to_hash(module, response):
u'id': response.get(u'id'), u'id': response.get(u'id'),
u'lastAttachTimestamp': response.get(u'lastAttachTimestamp'), u'lastAttachTimestamp': response.get(u'lastAttachTimestamp'),
u'lastDetachTimestamp': response.get(u'lastDetachTimestamp'), u'lastDetachTimestamp': response.get(u'lastDetachTimestamp'),
u'labels': response.get(u'labels'),
u'licenses': response.get(u'licenses'), u'licenses': response.get(u'licenses'),
u'name': response.get(u'name'), u'name': module.params.get('name'),
u'sizeGb': response.get(u'sizeGb'), u'sizeGb': response.get(u'sizeGb'),
u'sourceImage': module.params.get('source_image'),
u'type': response.get(u'type'), u'type': response.get(u'type'),
u'users': response.get(u'users') u'users': response.get(u'users'),
u'sourceImage': module.params.get('source_image')
} }
def disk_type_selflink(name, params):
if name is None:
return
url = r"https://www.googleapis.com/compute/v1/projects/.*/zones/{zone}/diskTypes/[a-z1-9\-]*"
if not re.match(url, name):
name = "https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/diskTypes/%s".format(**params) % name
return name
def async_op_url(module, extra_data=None): def async_op_url(module, extra_data=None):
if extra_data is None: if extra_data is None:
extra_data = {} extra_data = {}
@ -544,7 +575,7 @@ def async_op_url(module, extra_data=None):
def wait_for_operation(module, response): def wait_for_operation(module, response):
op_result = return_if_object(module, response, 'compute#operation') op_result = return_if_object(module, response, 'compute#operation')
if op_result is None: if op_result is None:
return None return {}
status = navigate_hash(op_result, ['status']) status = navigate_hash(op_result, ['status'])
wait_done = wait_for_completion(status, op_result, module) wait_done = wait_for_completion(status, op_result, module)
return fetch_resource(module, navigate_hash(wait_done, ['targetLink']), 'compute#disk') return fetch_resource(module, navigate_hash(wait_done, ['targetLink']), 'compute#disk')
@ -569,7 +600,7 @@ def raise_if_errors(response, err_path, module):
module.fail_json(msg=errors) module.fail_json(msg=errors)
class DiskDiskEncryKey(object): class DiskSourceImageEncryptionKey(object):
def __init__(self, request, module): def __init__(self, request, module):
self.module = module self.module = module
if request: if request:
@ -590,7 +621,7 @@ class DiskDiskEncryKey(object):
}) })
class DiskSourImagEncrKey(object): class DiskDiskEncryptionKey(object):
def __init__(self, request, module): def __init__(self, request, module):
self.module = module self.module = module
if request: if request:
@ -611,7 +642,7 @@ class DiskSourImagEncrKey(object):
}) })
class DiskSourSnapEncrKey(object): class DiskSourceSnapshotEncryptionKey(object):
def __init__(self, request, module): def __init__(self, request, module):
self.module = module self.module = module
if request: if request:

@ -18,13 +18,11 @@
name: "{{ resource_name }}" name: "{{ resource_name }}"
size_gb: 50 size_gb: 50
disk_encryption_key: disk_encryption_key:
raw_key: 'SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=' raw_key: SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=
zone: 'us-central1-a' zone: us-central1-a
project: "{{ gcp_project }}" project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}" auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}" service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/compute
state: absent state: absent
#---------------------------------------------------------- #----------------------------------------------------------
- name: create a disk - name: create a disk
@ -32,13 +30,11 @@
name: "{{ resource_name }}" name: "{{ resource_name }}"
size_gb: 50 size_gb: 50
disk_encryption_key: disk_encryption_key:
raw_key: 'SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=' raw_key: SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=
zone: 'us-central1-a' zone: us-central1-a
project: "{{ gcp_project }}" project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}" auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}" service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/compute
state: present state: present
register: result register: result
- name: assert changed is true - name: assert changed is true
@ -47,26 +43,31 @@
- result.changed == true - result.changed == true
- "result.kind == 'compute#disk'" - "result.kind == 'compute#disk'"
- name: verify that disk was created - name: verify that disk was created
shell: | gcp_compute_disk_facts:
gcloud compute disks describe --project="{{ gcp_project}}" --zone="us-central1-a" "{{ resource_name }}" filters:
- name = {{ resource_name }}
zone: us-central1-a
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/compute
register: results register: results
- name: verify that command succeeded - name: verify that command succeeded
assert: assert:
that: that:
- results.rc == 0 - results['items'] | length == 1
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
- name: create a disk that already exists - name: create a disk that already exists
gcp_compute_disk: gcp_compute_disk:
name: "{{ resource_name }}" name: "{{ resource_name }}"
size_gb: 50 size_gb: 50
disk_encryption_key: disk_encryption_key:
raw_key: 'SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=' raw_key: SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=
zone: 'us-central1-a' zone: us-central1-a
project: "{{ gcp_project }}" project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}" auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}" service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/compute
state: present state: present
register: result register: result
- name: assert changed is false - name: assert changed is false
@ -80,13 +81,11 @@
name: "{{ resource_name }}" name: "{{ resource_name }}"
size_gb: 50 size_gb: 50
disk_encryption_key: disk_encryption_key:
raw_key: 'SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=' raw_key: SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=
zone: 'us-central1-a' zone: us-central1-a
project: "{{ gcp_project }}" project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}" auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}" service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/compute
state: absent state: absent
register: result register: result
- name: assert changed is true - name: assert changed is true
@ -95,28 +94,31 @@
- result.changed == true - result.changed == true
- result.has_key('kind') == False - result.has_key('kind') == False
- name: verify that disk was deleted - name: verify that disk was deleted
shell: | gcp_compute_disk_facts:
gcloud compute disks describe --project="{{ gcp_project}}" --zone="us-central1-a" "{{ resource_name }}" filters:
- name = {{ resource_name }}
zone: us-central1-a
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/compute
register: results register: results
failed_when: results.rc == 0
- name: verify that command succeeded - name: verify that command succeeded
assert: assert:
that: that:
- results.rc == 1 - results['items'] | length == 0
- "\"'projects/{{ gcp_project }}/zones/us-central1-a/disks/{{ resource_name }}' was not found\" in results.stderr"
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
- name: delete a disk that does not exist - name: delete a disk that does not exist
gcp_compute_disk: gcp_compute_disk:
name: "{{ resource_name }}" name: "{{ resource_name }}"
size_gb: 50 size_gb: 50
disk_encryption_key: disk_encryption_key:
raw_key: 'SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=' raw_key: SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=
zone: 'us-central1-a' zone: us-central1-a
project: "{{ gcp_project }}" project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}" auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}" service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/compute
state: absent state: absent
register: result register: result
- name: assert changed is false - name: assert changed is false

Loading…
Cancel
Save