mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-02-04 16:01:55 +00:00
fix ruff case UP031 (#11223)
* fix ruff case UP031
* refactor backslashout of f-string for the sake of old Pythons
* add changelog frag
* Update plugins/modules/imc_rest.py
* scaleway_user_data: fix bug and make it an f-string
* reformat
---------
(cherry picked from commit d550baacfa)
Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
272 lines
8.3 KiB
Python
272 lines
8.3 KiB
Python
#!/usr/bin/python
|
|
#
|
|
# Copyright (c) 2016 Dimension Data
|
|
# Authors:
|
|
# - Aimon Bustardo <aimon.bustardo@dimensiondata.com>
|
|
# - Bert Diwa <Lamberto.Diwa@dimensiondata.com>
|
|
# - Adam Friedman <tintoy@tintoy.io>
|
|
#
|
|
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
DOCUMENTATION = r"""
|
|
module: dimensiondata_network
|
|
short_description: Create, update, and delete MCP 1.0 & 2.0 networks
|
|
extends_documentation_fragment:
|
|
- community.general.dimensiondata
|
|
- community.general.dimensiondata_wait
|
|
- community.general.attributes
|
|
|
|
description:
|
|
- Create, update, and delete MCP 1.0 & 2.0 networks.
|
|
deprecated:
|
|
removed_in: 13.0.0
|
|
why: Service and its endpoints are no longer available.
|
|
alternative: There is none.
|
|
author: 'Aimon Bustardo (@aimonb)'
|
|
attributes:
|
|
check_mode:
|
|
support: none
|
|
diff_mode:
|
|
support: none
|
|
options:
|
|
name:
|
|
description:
|
|
- The name of the network domain to create.
|
|
required: true
|
|
type: str
|
|
description:
|
|
description:
|
|
- Additional description of the network domain.
|
|
type: str
|
|
service_plan:
|
|
description:
|
|
- The service plan, either "ESSENTIALS" or "ADVANCED".
|
|
- MCP 2.0 Only.
|
|
choices: [ESSENTIALS, ADVANCED]
|
|
default: ESSENTIALS
|
|
type: str
|
|
state:
|
|
description:
|
|
- Should the resource be present or absent.
|
|
choices: [present, absent]
|
|
default: present
|
|
type: str
|
|
"""
|
|
|
|
EXAMPLES = r"""
|
|
- name: Create an MCP 1.0 network
|
|
community.general.dimensiondata_network:
|
|
region: na
|
|
location: NA5
|
|
name: mynet
|
|
|
|
- name: Create an MCP 2.0 network
|
|
community.general.dimensiondata_network:
|
|
region: na
|
|
mcp_user: my_user
|
|
mcp_password: my_password
|
|
location: NA9
|
|
name: mynet
|
|
service_plan: ADVANCED
|
|
|
|
- name: Delete a network
|
|
community.general.dimensiondata_network:
|
|
region: na
|
|
location: NA1
|
|
name: mynet
|
|
state: absent
|
|
"""
|
|
|
|
RETURN = r"""
|
|
network:
|
|
description: Dictionary describing the network.
|
|
returned: On success when O(state=present).
|
|
type: complex
|
|
contains:
|
|
id:
|
|
description: Network ID.
|
|
type: str
|
|
sample: "8c787000-a000-4050-a215-280893411a7d"
|
|
name:
|
|
description: Network name.
|
|
type: str
|
|
sample: "My network"
|
|
description:
|
|
description: Network description.
|
|
type: str
|
|
sample: "My network description"
|
|
location:
|
|
description: Datacenter location.
|
|
type: str
|
|
sample: NA3
|
|
status:
|
|
description: Network status. (MCP 2.0 only).
|
|
type: str
|
|
sample: NORMAL
|
|
private_net:
|
|
description: Private network subnet. (MCP 1.0 only).
|
|
type: str
|
|
sample: "10.2.3.0"
|
|
multicast:
|
|
description: Multicast enabled? (MCP 1.0 only).
|
|
type: bool
|
|
sample: false
|
|
"""
|
|
import traceback
|
|
|
|
from ansible.module_utils.basic import AnsibleModule
|
|
from ansible_collections.community.general.plugins.module_utils.dimensiondata import HAS_LIBCLOUD, DimensionDataModule
|
|
|
|
if HAS_LIBCLOUD:
|
|
from libcloud.compute.base import NodeLocation
|
|
from libcloud.common.dimensiondata import DimensionDataAPIException
|
|
|
|
|
|
class DimensionDataNetworkModule(DimensionDataModule):
|
|
"""
|
|
The dimensiondata_network module for Ansible.
|
|
"""
|
|
|
|
def __init__(self):
|
|
"""
|
|
Create a new Dimension Data network module.
|
|
"""
|
|
|
|
super().__init__(
|
|
module=AnsibleModule(
|
|
argument_spec=DimensionDataModule.argument_spec_with_wait(
|
|
name=dict(type="str", required=True),
|
|
description=dict(type="str"),
|
|
service_plan=dict(default="ESSENTIALS", choices=["ADVANCED", "ESSENTIALS"]),
|
|
state=dict(default="present", choices=["present", "absent"]),
|
|
),
|
|
required_together=DimensionDataModule.required_together(),
|
|
)
|
|
)
|
|
|
|
self.name = self.module.params["name"]
|
|
self.description = self.module.params["description"]
|
|
self.service_plan = self.module.params["service_plan"]
|
|
self.state = self.module.params["state"]
|
|
|
|
def state_present(self):
|
|
network = self._get_network()
|
|
|
|
if network:
|
|
self.module.exit_json(changed=False, msg="Network already exists", network=self._network_to_dict(network))
|
|
|
|
network = self._create_network()
|
|
|
|
self.module.exit_json(
|
|
changed=True,
|
|
msg=f'Created network "{self.name}" in datacenter "{self.location}".',
|
|
network=self._network_to_dict(network),
|
|
)
|
|
|
|
def state_absent(self):
|
|
network = self._get_network()
|
|
|
|
if not network:
|
|
self.module.exit_json(
|
|
changed=False, msg=f'Network "{self.name}" does not exist', network=self._network_to_dict(network)
|
|
)
|
|
|
|
self._delete_network(network)
|
|
|
|
def _get_network(self):
|
|
if self.mcp_version == "1.0":
|
|
networks = self.driver.list_networks(location=self.location)
|
|
else:
|
|
networks = self.driver.ex_list_network_domains(location=self.location)
|
|
|
|
matched_network = [network for network in networks if network.name == self.name]
|
|
if matched_network:
|
|
return matched_network[0]
|
|
|
|
return None
|
|
|
|
def _network_to_dict(self, network):
|
|
network_dict = dict(id=network.id, name=network.name, description=network.description)
|
|
|
|
if isinstance(network.location, NodeLocation):
|
|
network_dict["location"] = network.location.id
|
|
else:
|
|
network_dict["location"] = network.location
|
|
|
|
if self.mcp_version == "1.0":
|
|
network_dict["private_net"] = network.private_net
|
|
network_dict["multicast"] = network.multicast
|
|
network_dict["status"] = None
|
|
else:
|
|
network_dict["private_net"] = None
|
|
network_dict["multicast"] = None
|
|
network_dict["status"] = network.status
|
|
|
|
return network_dict
|
|
|
|
def _create_network(self):
|
|
# Make sure service_plan argument is defined
|
|
if self.mcp_version == "2.0" and "service_plan" not in self.module.params:
|
|
self.module.fail_json(msg="service_plan required when creating network and location is MCP 2.0")
|
|
|
|
# Create network
|
|
try:
|
|
if self.mcp_version == "1.0":
|
|
network = self.driver.ex_create_network(self.location, self.name, description=self.description)
|
|
else:
|
|
network = self.driver.ex_create_network_domain(
|
|
self.location, self.name, self.module.params["service_plan"], description=self.description
|
|
)
|
|
except DimensionDataAPIException as e:
|
|
self.module.fail_json(msg=f"Failed to create new network: {e}", exception=traceback.format_exc())
|
|
|
|
if self.module.params["wait"] is True:
|
|
network = self._wait_for_network_state(network.id, "NORMAL")
|
|
|
|
return network
|
|
|
|
def _delete_network(self, network):
|
|
try:
|
|
if self.mcp_version == "1.0":
|
|
deleted = self.driver.ex_delete_network(network)
|
|
else:
|
|
deleted = self.driver.ex_delete_network_domain(network)
|
|
|
|
if deleted:
|
|
self.module.exit_json(changed=True, msg=f"Deleted network with id {network.id}")
|
|
|
|
self.module.fail_json(f"Unexpected failure deleting network with id {network.id}")
|
|
|
|
except DimensionDataAPIException as e:
|
|
self.module.fail_json(msg=f"Failed to delete network: {e}", exception=traceback.format_exc())
|
|
|
|
def _wait_for_network_state(self, net_id, state_to_wait_for):
|
|
try:
|
|
return self.driver.connection.wait_for_state(
|
|
state_to_wait_for,
|
|
self.driver.ex_get_network_domain,
|
|
self.module.params["wait_poll_interval"],
|
|
self.module.params["wait_time"],
|
|
net_id,
|
|
)
|
|
except DimensionDataAPIException as e:
|
|
self.module.fail_json(
|
|
msg=f"Network did not reach {state_to_wait_for} state in time: {e}",
|
|
exception=traceback.format_exc(),
|
|
)
|
|
|
|
|
|
def main():
|
|
module = DimensionDataNetworkModule()
|
|
if module.state == "present":
|
|
module.state_present()
|
|
elif module.state == "absent":
|
|
module.state_absent()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|