Rename modules from plural to singular (#27185)

* First batch of modules renamed from plural to singular

Related to this proposal: https://github.com/ansible/proposals/issues/10

* Emit rename deprication warning

* Update legacy-files.txt and skip.txt to reflect new names
pull/25586/merge
Sam Doran 7 years ago committed by GitHub
parent 9d84a4e530
commit 68060002e8

@ -13,7 +13,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.0',
DOCUMENTATION = """
---
module: ec2_vpc_dhcp_options
module: ec2_vpc_dhcp_option
short_description: Manages DHCP Options, and can ensure the DHCP options for the given VPC match what's
requested
description:
@ -140,7 +140,7 @@ changed:
EXAMPLES = """
# Completely overrides the VPC DHCP options associated with VPC vpc-123456 and deletes any existing
# DHCP option set that may have been attached to that VPC.
- ec2_vpc_dhcp_options:
- ec2_vpc_dhcp_option:
domain_name: "foo.example.com"
region: us-east-1
dns_servers:
@ -160,7 +160,7 @@ EXAMPLES = """
# Ensure the DHCP option set for the VPC has 10.0.0.4 and 10.0.1.4 as the specified DNS servers, but
# keep any other existing settings. Also, keep the old DHCP option set around.
- ec2_vpc_dhcp_options:
- ec2_vpc_dhcp_option:
region: us-east-1
dns_servers:
- "{{groups['dns-primary']}}"
@ -172,7 +172,7 @@ EXAMPLES = """
## Create a DHCP option set with 4.4.4.4 and 8.8.8.8 as the specified DNS servers, with tags
## but do not assign to a VPC
- ec2_vpc_dhcp_options:
- ec2_vpc_dhcp_option:
region: us-east-1
dns_servers:
- 4.4.4.4
@ -182,7 +182,7 @@ EXAMPLES = """
Environment: Test
## Delete a DHCP options set that matches the tags and options specified
- ec2_vpc_dhcp_options:
- ec2_vpc_dhcp_option:
region: us-east-1
dns_servers:
- 4.4.4.4
@ -193,7 +193,7 @@ EXAMPLES = """
state: absent
## Associate a DHCP options set with a VPC by ID
- ec2_vpc_dhcp_options:
- ec2_vpc_dhcp_option:
region: us-east-1
dhcp_options_id: dopt-12345678
vpc_id: vpc-123456

@ -13,7 +13,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.0',
DOCUMENTATION = '''
---
module: ec2_vpc_dhcp_options_facts
module: ec2_vpc_dhcp_option_facts
short_description: Gather facts about dhcp options sets in AWS
description:
- Gather facts about dhcp options sets in AWS
@ -43,13 +43,13 @@ EXAMPLES = '''
# # Note: These examples do not set authentication details, see the AWS Guide for details.
- name: Gather facts about all DHCP Option sets for an account or profile
ec2_vpc_dhcp_options_facts:
ec2_vpc_dhcp_option_facts:
region: ap-southeast-2
profile: production
register: dhcp_facts
- name: Gather facts about a filtered list of DHCP Option sets
ec2_vpc_dhcp_options_facts:
ec2_vpc_dhcp_option_facts:
region: ap-southeast-2
profile: production
filters:
@ -57,7 +57,7 @@ EXAMPLES = '''
register: dhcp_facts
- name: Gather facts about a specific DHCP Option set by DhcpOptionId
ec2_vpc_dhcp_options_facts:
ec2_vpc_dhcp_option_facts:
region: ap-southeast-2
profile: production
DhcpOptionsIds: dopt-123fece2

@ -23,7 +23,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.0',
DOCUMENTATION = '''
---
module: os_server_actions
module: os_server_action
short_description: Perform actions on Compute Instances from OpenStack
extends_documentation_fragment: openstack
version_added: "2.0"
@ -71,15 +71,15 @@ requirements:
EXAMPLES = '''
# Pauses a compute instance
- os_server_actions:
action: pause
auth:
auth_url: https://mycloud.openstack.blueboxgrid.com:5001/v2.0
username: admin
password: admin
project_name: admin
server: vm1
timeout: 200
- os_server_action:
action: pause
auth:
auth_url: https://mycloud.openstack.blueboxgrid.com:5001/v2.0
username: admin
password: admin
project_name: admin
server: vm1
timeout: 200
'''
try:
@ -142,6 +142,9 @@ def main():
required_if=[('action', 'rebuild', ['image'])],
**module_kwargs)
if module._name == 'os_server_actions':
module.deprecate("The 'os_server_actions' module is being renamed 'os_server_action'", version=2.8)
if not HAS_SHADE:
module.fail_json(msg='shade is required for this module')

@ -26,7 +26,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.0',
DOCUMENTATION = '''
---
module: ovirt_affinity_groups
module: ovirt_affinity_group
short_description: Module to manage affinity groups in oVirt/RHV
version_added: "2.3"
author: "Ondra Machacek (@machacekondra)"
@ -88,7 +88,7 @@ EXAMPLES = '''
# look at ovirt_auth module to see how to reuse authentication:
# Create(if not exists) and assign affinity group to VMs vm1 and vm2 and host host1
- ovirt_affinity_groups:
- ovirt_affinity_group:
name: mygroup
cluster: mycluster
vm_enforcing: true
@ -102,7 +102,7 @@ EXAMPLES = '''
- host1
# Detach VMs from affinity group and disable VM rule:
- ovirt_affinity_groups:
- ovirt_affinity_group:
name: mygroup
cluster: mycluster
vm_enforcing: false
@ -115,7 +115,7 @@ EXAMPLES = '''
- host2
# Remove affinity group
- ovirt_affinity_groups:
- ovirt_affinity_group:
state: absent
cluster: mycluster
name: mygroup
@ -293,6 +293,10 @@ def main():
argument_spec=argument_spec,
supports_check_mode=True,
)
if module._name == 'ovirt_affinity_groups':
module.deprecate("The 'ovirt_affinity_groups' module is being renamed 'ovirt_affinity_group'", version=2.8)
check_sdk(module)
try:
auth = module.params.pop('auth')

@ -26,7 +26,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.0',
DOCUMENTATION = '''
---
module: ovirt_affinity_labels
module: ovirt_affinity_label
short_description: Module to manage affinity labels in oVirt/RHV
version_added: "2.3"
author: "Ondra Machacek (@machacekondra)"
@ -60,7 +60,7 @@ EXAMPLES = '''
# look at ovirt_auth module to see how to reuse authentication:
# Create(if not exists) and assign affinity label to vms vm1 and vm2 and host host1
- ovirt_affinity_labels:
- ovirt_affinity_label:
name: mylabel
cluster: mycluster
vms:
@ -70,13 +70,13 @@ EXAMPLES = '''
- host1
# To detach all VMs from label
- ovirt_affinity_labels:
- ovirt_affinity_label:
name: mylabel
cluster: mycluster
vms: []
# Remove affinity label
- ovirt_affinity_labels:
- ovirt_affinity_label:
state: absent
name: mylabel
'''
@ -180,6 +180,10 @@ def main():
('state', 'present', ['cluster']),
],
)
if module._name == 'ovirt_affinity_labels':
module.deprecate("The 'ovirt_affinity_labels' module is being renamed 'ovirt_affinity_label'", version=2.8)
check_sdk(module)
try:

@ -26,7 +26,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.0',
DOCUMENTATION = '''
---
module: ovirt_affinity_labels_facts
module: ovirt_affinity_label_facts
short_description: Retrieve facts about one or more oVirt/RHV affinity labels
author: "Ondra Machacek (@machacekondra)"
version_added: "2.3"
@ -53,28 +53,28 @@ EXAMPLES = '''
# look at ovirt_auth module to see how to reuse authentication:
# Gather facts about all affinity labels, which names start with C(label):
- ovirt_affinity_labels_facts:
- ovirt_affinity_label_facts:
name: label*
- debug:
var: affinity_labels
# Gather facts about all affinity labels, which are assigned to VMs
# which names start with C(postgres):
- ovirt_affinity_labels_facts:
- ovirt_affinity_label_facts:
vm: postgres*
- debug:
var: affinity_labels
# Gather facts about all affinity labels, which are assigned to hosts
# which names start with C(west):
- ovirt_affinity_labels_facts:
- ovirt_affinity_label_facts:
host: west*
- debug:
var: affinity_labels
# Gather facts about all affinity labels, which are assigned to hosts
# which names start with C(west) or VMs which names start with C(postgres):
- ovirt_affinity_labels_facts:
- ovirt_affinity_label_facts:
host: west*
vm: postgres*
- debug:
@ -108,6 +108,10 @@ def main():
vm=dict(default=None),
)
module = AnsibleModule(argument_spec)
if module._name == 'ovirt_affinity_labels_facts':
module.deprecate("The 'ovirt_affinity_labels_facts' module is being renamed 'ovirt_affinity_label_facts'", version=2.8)
check_sdk(module)
try:

@ -26,7 +26,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.0',
DOCUMENTATION = '''
---
module: ovirt_clusters
module: ovirt_cluster
short_description: Module to manage clusters in oVirt/RHV
version_added: "2.3"
author: "Ondra Machacek (@machacekondra)"
@ -216,7 +216,7 @@ EXAMPLES = '''
# look at ovirt_auth module to see how to reuse authentication:
# Create cluster
- ovirt_clusters:
- ovirt_cluster:
data_center: mydatacenter
name: mycluster
cpu_type: Intel SandyBridge Family
@ -224,7 +224,7 @@ EXAMPLES = '''
compatibility_version: 4.0
# Create virt service cluster:
- ovirt_clusters:
- ovirt_cluster:
data_center: mydatacenter
name: mycluster
cpu_type: Intel Nehalem Family
@ -245,7 +245,7 @@ EXAMPLES = '''
- random
# Remove cluster
- ovirt_clusters:
- ovirt_cluster:
state: absent
name: mycluster
'''
@ -548,6 +548,10 @@ def main():
argument_spec=argument_spec,
supports_check_mode=True,
)
if module._name == 'ovirt_clusters':
module.deprecate("The 'ovirt_clusters' module is being renamed 'ovirt_cluster'", version=2.8)
check_sdk(module)
try:

@ -26,7 +26,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.0',
DOCUMENTATION = '''
---
module: ovirt_clusters_facts
module: ovirt_cluster_facts
short_description: Retrieve facts about one or more oVirt/RHV clusters
author: "Ondra Machacek (@machacekondra)"
version_added: "2.3"
@ -49,8 +49,9 @@ EXAMPLES = '''
# look at ovirt_auth module to see how to reuse authentication:
# Gather facts about all clusters which names start with C<production>:
- ovirt_clusters_facts:
pattern: name=production*
- ovirt_cluster_facts:
pattern:
name: 'production*'
- debug:
var: ovirt_clusters
'''
@ -79,6 +80,10 @@ def main():
pattern=dict(default='', required=False),
)
module = AnsibleModule(argument_spec)
if module._name == 'ovirt_clusters_facts':
module.deprecate("The 'ovirt_clusters_facts' module is being renamed 'ovirt_cluster_facts'", version=2.8)
check_sdk(module)
try:

@ -26,7 +26,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.0',
DOCUMENTATION = '''
---
module: ovirt_datacenters
module: ovirt_datacenter
short_description: Module to manage data centers in oVirt/RHV
version_added: "2.3"
author: "Ondra Machacek (@machacekondra)"
@ -73,14 +73,14 @@ EXAMPLES = '''
# look at ovirt_auth module to see how to reuse authentication:
# Create datacenter
- ovirt_datacenters:
- ovirt_datacenter:
name: mydatacenter
local: True
compatibility_version: 4.0
quota_mode: enabled
# Remove datacenter
- ovirt_datacenters:
- ovirt_datacenter:
state: absent
name: mydatacenter
'''
@ -193,6 +193,10 @@ def main():
argument_spec=argument_spec,
supports_check_mode=True,
)
if module._name == 'ovirt_datacenters':
module.deprecate("The 'ovirt_datacenters' module is being renamed 'ovirt_datacenter'", version=2.8)
check_sdk(module)
check_params(module)

@ -26,7 +26,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.0',
DOCUMENTATION = '''
---
module: ovirt_datacenters_facts
module: ovirt_datacenter_facts
short_description: Retrieve facts about one or more oVirt/RHV datacenters
author: "Ondra Machacek (@machacekondra)"
version_added: "2.3"
@ -48,7 +48,7 @@ EXAMPLES = '''
# look at ovirt_auth module to see how to reuse authentication:
# Gather facts about all data centers which names start with C(production):
- ovirt_datacenters_facts:
- ovirt_datacenter_facts:
pattern: name=production*
- debug:
var: ovirt_datacenters
@ -78,6 +78,10 @@ def main():
pattern=dict(default='', required=False),
)
module = AnsibleModule(argument_spec)
if module._name == 'ovirt_datacenters_facts':
module.deprecate("The 'ovirt_datacenters_facts' module is being renamed 'ovirt_datacenter_facts'", version=2.8)
check_sdk(module)
try:

@ -26,7 +26,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.0',
DOCUMENTATION = '''
---
module: ovirt_disks
module: ovirt_disk
short_description: "Module to manage Virtual Machine and floating disks in oVirt/RHV"
version_added: "2.2"
author: "Ondra Machacek (@machacekondra)"
@ -147,7 +147,7 @@ EXAMPLES = '''
# look at ovirt_auth module to see how to reuse authentication:
# Create and attach new disk to VM
- ovirt_disks:
- ovirt_disk:
name: myvm_disk
vm_name: rhel7
size: 10GiB
@ -155,7 +155,7 @@ EXAMPLES = '''
interface: virtio
# Attach logical unit to VM rhel7
- ovirt_disks:
- ovirt_disk:
vm_name: rhel7
logical_unit:
target: iqn.2016-08-09.brq.str-01:omachace
@ -164,7 +164,7 @@ EXAMPLES = '''
interface: virtio
# Detach disk from VM
- ovirt_disks:
- ovirt_disk:
state: detached
name: myvm_disk
vm_name: rhel7
@ -174,7 +174,7 @@ EXAMPLES = '''
# Upload local image to disk and attach it to vm:
# Since Ansible 2.3
- ovirt_disks:
- ovirt_disk:
name: mydisk
vm_name: myvm
interface: virtio
@ -185,7 +185,7 @@ EXAMPLES = '''
# Download disk to local file system:
# Since Ansible 2.3
- ovirt_disks:
- ovirt_disk:
id: 7de90f31-222c-436c-a1ca-7e655bd5b60c
download_image_path: /home/user/mydisk.qcow2
'''
@ -541,6 +541,10 @@ def main():
argument_spec=argument_spec,
supports_check_mode=True,
)
if module._name == 'ovirt_disks':
module.deprecate("The 'ovirt_disks' module is being renamed 'ovirt_disk'", version=2.8)
check_sdk(module)
check_params(module)
@ -579,8 +583,7 @@ def main():
ret['changed'] = ret['changed'] or uploaded
# Download disk image in case it's file don't exist or force parameter is passed:
if (
module.params['download_image_path']
and (not os.path.isfile(module.params['download_image_path']) or module.params['force'])
module.params['download_image_path'] and (not os.path.isfile(module.params['download_image_path']) or module.params['force'])
):
downloaded = download_disk_image(connection, module)
ret['changed'] = ret['changed'] or downloaded
@ -623,7 +626,7 @@ def main():
if lun is None:
wait(
service=disk_attachments_service.service(ret['id']),
condition=lambda d:follow_link(connection, d.disk).status == otypes.DiskStatus.OK,
condition=lambda d: follow_link(connection, d.disk).status == otypes.DiskStatus.OK,
wait=module.params['wait'],
timeout=module.params['timeout'],
)

@ -26,7 +26,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.0',
DOCUMENTATION = '''
---
module: ovirt_external_providers
module: ovirt_external_provider
short_description: Module to manage external providers in oVirt/RHV
version_added: "2.3"
author: "Ondra Machacek (@machacekondra)"
@ -92,7 +92,7 @@ EXAMPLES = '''
# look at ovirt_auth module to see how to reuse authentication:
# Add image external provider:
- ovirt_external_providers:
- ovirt_external_provider:
name: image_provider
type: os_image
url: http://10.34.63.71:9292
@ -102,7 +102,7 @@ EXAMPLES = '''
auth_url: http://10.34.63.71:35357/v2.0/
# Add foreman provider:
- ovirt_external_providers:
- ovirt_external_provider:
name: foreman_provider
type: foreman
url: https://foreman.example.com
@ -110,14 +110,14 @@ EXAMPLES = '''
password: 123456
# Add external network provider for OVN:
- ovirt_external_providers:
- ovirt_external_provider:
name: ovn_provider
type: network
network_type: external
url: http://1.2.3.4:9696
# Remove image external provider:
- ovirt_external_providers:
- ovirt_external_provider:
state: absent
name: image_provider
type: os_image
@ -244,6 +244,10 @@ def main():
argument_spec=argument_spec,
supports_check_mode=True,
)
if module._name == 'ovirt_external_providers':
module.deprecate("The 'ovirt_external_providers' module is being renamed 'ovirt_external_provider'", version=2.8)
check_sdk(module)
check_params(module)

@ -26,7 +26,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.0',
DOCUMENTATION = '''
---
module: ovirt_external_providers_facts
module: ovirt_external_provider_facts
short_description: Retrieve facts about one or more oVirt/RHV external providers
author: "Ondra Machacek (@machacekondra)"
version_added: "2.3"
@ -52,7 +52,7 @@ EXAMPLES = '''
# look at ovirt_auth module to see how to reuse authentication:
# Gather facts about all image external providers named C<glance>:
- ovirt_external_providers_facts:
- ovirt_external_provider_facts:
type: os_image
name: glance
- debug:
@ -118,6 +118,10 @@ def main():
),
)
module = AnsibleModule(argument_spec)
if module._name == 'ovirt_external_providers_facts':
module.deprecate("The 'ovirt_external_providers_facts' module is being renamed 'ovirt_external_provider_facts'", version=2.8)
check_sdk(module)
try:

@ -26,7 +26,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.0',
DOCUMENTATION = '''
---
module: ovirt_groups
module: ovirt_group
short_description: Module to manage groups in oVirt/RHV
version_added: "2.3"
author: "Ondra Machacek (@machacekondra)"
@ -59,20 +59,20 @@ EXAMPLES = '''
# look at ovirt_auth module to see how to reuse authentication:
# Add group group1 from authorization provider example.com-authz
ovirt_groups:
ovirt_group:
name: group1
domain: example.com-authz
# Add group group1 from authorization provider example.com-authz
# In case of multi-domain Active Directory setup, you should pass
# also namespace, so it adds correct group:
ovirt_groups:
ovirt_group:
name: group1
namespace: dc=ad2,dc=example,dc=com
domain: example.com-authz
# Remove group group1 with authorization provider example.com-authz
ovirt_groups:
ovirt_group:
state: absent
name: group1
domain: example.com-authz
@ -154,6 +154,10 @@ def main():
argument_spec=argument_spec,
supports_check_mode=True,
)
if module._name == 'ovirt_groups':
module.deprecate("The 'ovirt_groups' module is being renamed 'ovirt_group'", version=2.8)
check_sdk(module)
check_params(module)

@ -26,7 +26,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.0',
DOCUMENTATION = '''
---
module: ovirt_groups_facts
module: ovirt_group_facts
short_description: Retrieve facts about one or more oVirt/RHV groups
author: "Ondra Machacek (@machacekondra)"
version_added: "2.3"
@ -48,7 +48,7 @@ EXAMPLES = '''
# look at ovirt_auth module to see how to reuse authentication:
# Gather facts about all groups which names start with C(admin):
- ovirt_groups_facts:
- ovirt_group_facts:
pattern: name=admin*
- debug:
var: ovirt_groups
@ -78,6 +78,10 @@ def main():
pattern=dict(default='', required=False),
)
module = AnsibleModule(argument_spec)
if module._name == 'ovirt_groups_facts':
module.deprecate("The 'ovirt_groups_facts' module is being renamed 'ovirt_group_facts'", version=2.8)
check_sdk(module)
try:

@ -1,3 +1,4 @@
lib/ansible/modules/cloud/ovirt/_ovirt_disks.py
lib/ansible/module_utils/ansible_tower.py
lib/ansible/module_utils/avi.py
lib/ansible/module_utils/azure_rm_common.py
@ -43,7 +44,11 @@ lib/ansible/modules/cloud/dimensiondata/dimensiondata_network.py
lib/ansible/modules/cloud/google/gc_storage.py
lib/ansible/modules/cloud/google/gcdns_record.py
lib/ansible/modules/cloud/google/gcdns_zone.py
lib/ansible/modules/cloud/misc/serverless.py
lib/ansible/modules/cloud/ovirt/ovirt_disks.py
lib/ansible/modules/cloud/openstack/os_client_config.py
lib/ansible/modules/cloud/ovirt/ovirt_disk.py
lib/ansible/modules/cloud/univention/udm_user.py
lib/ansible/modules/cloud/webfaction/webfaction_app.py
lib/ansible/modules/cloud/webfaction/webfaction_db.py
lib/ansible/modules/cloud/webfaction/webfaction_domain.py

@ -7,6 +7,9 @@ lib/ansible/modules/cloud/amazon/_ec2_elb.py
lib/ansible/modules/cloud/amazon/_ec2_elb_facts.py
lib/ansible/modules/cloud/amazon/_ec2_elb_lb.py
lib/ansible/modules/cloud/amazon/_ec2_vpc.py
lib/ansible/modules/cloud/amazon/_ec2_vpc_dhcp_options.py
lib/ansible/modules/cloud/openstack/_os_server_actions.py
lib/ansible/modules/cloud/ovirt/_ovirt_affinity_groups.py
lib/ansible/modules/cloud/amazon/aws_kms.py
lib/ansible/modules/cloud/amazon/cloudformation.py
lib/ansible/modules/cloud/amazon/cloudformation_facts.py
@ -27,7 +30,7 @@ lib/ansible/modules/cloud/amazon/ec2_snapshot_facts.py
lib/ansible/modules/cloud/amazon/ec2_tag.py
lib/ansible/modules/cloud/amazon/ec2_vol.py
lib/ansible/modules/cloud/amazon/ec2_vol_facts.py
lib/ansible/modules/cloud/amazon/ec2_vpc_dhcp_options.py
lib/ansible/modules/cloud/amazon/ec2_vpc_dhcp_option.py
lib/ansible/modules/cloud/amazon/ec2_vpc_nacl.py
lib/ansible/modules/cloud/amazon/ec2_vpc_net.py
lib/ansible/modules/cloud/amazon/ec2_vpc_net_facts.py
@ -128,7 +131,7 @@ lib/ansible/modules/cloud/openstack/os_quota.py
lib/ansible/modules/cloud/openstack/os_recordset.py
lib/ansible/modules/cloud/openstack/os_security_group_rule.py
lib/ansible/modules/cloud/openstack/os_server.py
lib/ansible/modules/cloud/openstack/os_server_actions.py
lib/ansible/modules/cloud/openstack/os_server_action.py
lib/ansible/modules/cloud/openstack/os_server_volume.py
lib/ansible/modules/cloud/openstack/os_stack.py
lib/ansible/modules/cloud/openstack/os_subnet.py
@ -138,8 +141,7 @@ lib/ansible/modules/cloud/openstack/os_user_group.py
lib/ansible/modules/cloud/openstack/os_user_role.py
lib/ansible/modules/cloud/openstack/os_zone.py
lib/ansible/modules/cloud/ovh/ovh_ip_loadbalancing_backend.py
lib/ansible/modules/cloud/ovirt/ovirt_affinity_groups.py
lib/ansible/modules/cloud/ovirt/ovirt_disks.py
lib/ansible/modules/cloud/ovirt/ovirt_affinity_group.py
lib/ansible/modules/cloud/ovirt/ovirt_nics.py
lib/ansible/modules/cloud/ovirt/ovirt_permissions.py
lib/ansible/modules/cloud/ovirt/ovirt_vms.py

Loading…
Cancel
Save