Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions plugins/modules/ovh_block_volume_snapshot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

from ansible.module_utils.basic import AnsibleModule
from ansible_collections.synthesio.ovh.plugins.module_utils.ovh import OVH, ovh_argument_spec

DOCUMENTATION = '''
---
module: ovh_block_volume_snapshot
short_description: Create a snapshot of an OVH Cloud block storage volume
description:
- This module creates a snapshot for a given block storage volume on OVH Public Cloud.
options:
service_name:
description: The OVH Cloud project ID
required: true
type: str
volume_id:
description: The ID of the volume to snapshot
required: true
type: str
snapshot_name:
description: Name of the snapshot
required: true
type: str
description:
description: Description of the snapshot
required: false
type: str
author:
- Your Name

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The author field in the DOCUMENTATION block is currently set to "Your Name". Please update this field to reflect the actual author(s) or team responsible for this module.

author:
    - Synthesio SRE team <sre@synthesio.com>

'''

EXAMPLES = '''
- name: Create a snapshot of a volume
ovh_block_volume_snapshot:
service_name: "project-xyz"
volume_id: "vol-abc123"
snapshot_name: "daily-backup"
description: "Snapshot taken automatically"
delegate_to: localhost
'''

RETURN = '''
msg:
description: Message about snapshot creation
returned: always
type: str
'''

def run_module():
argument_spec = ovh_argument_spec()
argument_spec.update(dict(
service_name=dict(required=True, type='str'),
volume_id=dict(required=True, type='str'),
snapshot_name=dict(required=True, type='str'),
description=dict(required=False, type='str', default="Snapshot created by Ansible")
))

module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=False
)

client = OVH(module)

service_name = module.params['service_name']
volume_id = module.params['volume_id']
snapshot_name = module.params['snapshot_name']
description = module.params['description']

try:
result = client.wrap_call(
"POST",
f"/cloud/project/{service_name}/volume/{volume_id}/snapshot",
name=snapshot_name,
description=description
)
module.exit_json(changed=True, msg=f"Snapshot '{snapshot_name}' created successfully.", result=result)
except Exception as e:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exceptions are handled in plugins/module_utils/ovh.py

module.fail_json(msg=f"Failed to create snapshot: {str(e)}")
Comment on lines +75 to +84

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Ansible modules should ideally be idempotent. This means running the module multiple times with the same parameters should result in the same final state and report changed=False after the first successful run.

The current implementation attempts to create the snapshot every time. If a snapshot with the given snapshot_name already exists for the volume, the OVH API will likely return an error, causing the module to fail on subsequent runs.

To make this module idempotent, consider adding logic to check if a snapshot with the specified snapshot_name already exists for the given volume_id before attempting to create it. If it exists, the module should report changed=False and exit successfully. This would likely involve making a GET call to the OVH API (e.g., listing snapshots for the volume and filtering by name) before the POST call to create the snapshot.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be a good point. Did you run the module multiple times with the same name?
Does it replace the snapshot, create a new one with the same name but a different creation date, or throw an error?

Comment on lines +83 to +84

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The except Exception as e: block is very broad and will catch any type of exception, including those not related to the API call itself. While client.wrap_call handles specific OVH API errors and calls module.fail_json, catching a generic Exception here might hide unexpected issues.

It's generally better practice to catch more specific exceptions if possible, or rely on the error handling within wrap_call for API-related issues. If there are other non-API exceptions you anticipate, catch those specifically. If not, you might not need this outer try...except block, or you could refine it.


def main():
run_module()

if __name__ == '__main__':
main()