mirror of
https://github.com/ansible-collections/hetzner.hcloud
synced 2024-12-13 22:12:32 +00:00
feat: vendor hcloud python dependency (#244)
* chore: ignore venv directories * chore: ignore integration test generated inventory * feat: vendor hcloud package * import https://github.com/hetznercloud/hcloud-python * use vendored hcloud in modules * update integration test requirements * make vendor script self contained * chore: add check-hcloud-vendor pre-commit hook * pin hcloud version to v.1.24.0 * move vendored __version__.py file to _version.py * update comment about galaxy-importer filename lint
This commit is contained in:
parent
bf9700ab23
commit
8c7cd1e8f9
84 changed files with 8433 additions and 79 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,3 +1,5 @@
|
|||
.venv
|
||||
venv
|
||||
|
||||
# Created by https://www.gitignore.io/api/git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv
|
||||
# Edit at https://www.gitignore.io/?templates=git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv
|
||||
|
@ -55,7 +57,6 @@ flycheck_*.el
|
|||
# network security
|
||||
/network-security.data
|
||||
|
||||
|
||||
### Git ###
|
||||
# Created by git for backups. To disable backups in Git:
|
||||
# $ git config --global mergetool.keepBackup false
|
||||
|
@ -387,3 +388,4 @@ $RECYCLE.BIN/
|
|||
# End of https://www.gitignore.io/api/git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv
|
||||
|
||||
cloud-config-hcloud.ini
|
||||
tests/integration/inventory
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
# See https://pre-commit.com for more information
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
exclude: ^plugins/module_utils/vendor/hcloud/.*$
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.4.0
|
||||
|
@ -52,3 +53,11 @@ repos:
|
|||
entry: antsibull-changelog lint
|
||||
pass_filenames: false
|
||||
files: ^changelogs/.*$
|
||||
|
||||
- id: check-hcloud-vendor
|
||||
name: check hcloud vendor
|
||||
description: Ensure the hcloud vendored files are in sync
|
||||
language: python
|
||||
entry: python3 scripts/vendor.py
|
||||
pass_filenames: false
|
||||
files: ^scripts/vendor.py$
|
||||
|
|
9
Makefile
Normal file
9
Makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
SHELL := bash
|
||||
.PHONY: vendor clean
|
||||
|
||||
vendor:
|
||||
python3 scripts/vendor.py
|
||||
|
||||
clean:
|
||||
git clean -xdf \
|
||||
-e tests/integration/cloud-config-hcloud.ini
|
12
changelogs/fragments/vendor-hcloud-python-dependency.yml
Normal file
12
changelogs/fragments/vendor-hcloud-python-dependency.yml
Normal file
|
@ -0,0 +1,12 @@
|
|||
release_summary: |
|
||||
This release bundles the hcloud dependency in the collection, this allows us to ship
|
||||
new features or bug fixes without having to release new major versions and require the
|
||||
users to upgrade their version of the hcloud dependency.
|
||||
minor_changes:
|
||||
- Bundle hcloud python dependency inside the collection.
|
||||
- >
|
||||
python-dateutil >= 2.7.5 is now required by the collection. If you already have the
|
||||
hcloud package installed, this dependency should also be installed.
|
||||
- >
|
||||
requests >= 2.20 is now required by the collection. If you already have the hcloud
|
||||
package installed, this dependency should also be installed.
|
|
@ -17,7 +17,8 @@ options:
|
|||
default: https://api.hetzner.cloud/v1
|
||||
type: str
|
||||
requirements:
|
||||
- hcloud-python >= 1.20.0
|
||||
- python-dateutil >= 2.7.5
|
||||
- requests >=2.20
|
||||
seealso:
|
||||
- name: Documentation for Hetzner Cloud API
|
||||
description: Complete reference for the Hetzner Cloud API.
|
||||
|
|
|
@ -121,13 +121,11 @@ from ansible.errors import AnsibleError
|
|||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable
|
||||
from ansible.release import __version__
|
||||
|
||||
try:
|
||||
from hcloud import APIException, hcloud
|
||||
|
||||
HAS_HCLOUD = True
|
||||
except ImportError:
|
||||
HAS_HCLOUD = False
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import (
|
||||
HAS_DATEUTIL,
|
||||
HAS_REQUESTS,
|
||||
)
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.vendor import hcloud
|
||||
|
||||
|
||||
class InventoryModule(BaseInventoryPlugin, Constructable):
|
||||
|
@ -159,7 +157,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
|
|||
# We test the API Token against the location API, because this is the API with the smallest result
|
||||
# and not controllable from the customer.
|
||||
self.client.locations.get_all()
|
||||
except APIException:
|
||||
except hcloud.APIException:
|
||||
raise AnsibleError("Invalid Hetzner Cloud API Token.")
|
||||
|
||||
def _get_servers(self):
|
||||
|
@ -177,7 +175,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
|
|||
self.network = self.client.networks.get_by_name(network)
|
||||
if self.network is None:
|
||||
self.network = self.client.networks.get_by_id(network)
|
||||
except APIException:
|
||||
except hcloud.APIException:
|
||||
raise AnsibleError("The given network is not found.")
|
||||
|
||||
tmp = []
|
||||
|
@ -322,8 +320,10 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
|
|||
def parse(self, inventory, loader, path, cache=True):
|
||||
super().parse(inventory, loader, path, cache)
|
||||
|
||||
if not HAS_HCLOUD:
|
||||
raise AnsibleError("The Hetzner Cloud dynamic inventory plugin requires hcloud-python.")
|
||||
if not HAS_REQUESTS:
|
||||
raise AnsibleError("The Hetzner Cloud dynamic inventory plugin requires requests.")
|
||||
if not HAS_DATEUTIL:
|
||||
raise AnsibleError("The Hetzner Cloud dynamic inventory plugin requires python-dateutil.")
|
||||
|
||||
self._read_config_data(path)
|
||||
self._configure_hcloud_client()
|
||||
|
|
|
@ -5,13 +5,20 @@
|
|||
|
||||
from ansible.module_utils.ansible_release import __version__
|
||||
from ansible.module_utils.basic import env_fallback, missing_required_lib
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.vendor import hcloud
|
||||
|
||||
HAS_REQUESTS = True
|
||||
HAS_DATEUTIL = True
|
||||
|
||||
try:
|
||||
import hcloud
|
||||
|
||||
HAS_HCLOUD = True
|
||||
import requests # pylint: disable=unused-import
|
||||
except ImportError:
|
||||
HAS_HCLOUD = False
|
||||
HAS_REQUESTS = False
|
||||
|
||||
try:
|
||||
import dateutil # pylint: disable=unused-import
|
||||
except ImportError:
|
||||
HAS_DATEUTIL = False
|
||||
|
||||
|
||||
class Hcloud:
|
||||
|
@ -19,8 +26,10 @@ class Hcloud:
|
|||
self.module = module
|
||||
self.represent = represent
|
||||
self.result = {"changed": False, self.represent: None}
|
||||
if not HAS_HCLOUD:
|
||||
module.fail_json(msg=missing_required_lib("hcloud-python"))
|
||||
if not HAS_REQUESTS:
|
||||
module.fail_json(msg=missing_required_lib("requests"))
|
||||
if not HAS_DATEUTIL:
|
||||
module.fail_json(msg=missing_required_lib("python-dateutil"))
|
||||
self._build_client()
|
||||
|
||||
def _build_client(self):
|
||||
|
|
0
plugins/module_utils/vendor/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/__init__.py
vendored
Normal file
2
plugins/module_utils/vendor/hcloud/__init__.py
vendored
Normal file
2
plugins/module_utils/vendor/hcloud/__init__.py
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
from ._exceptions import APIException, HCloudException # noqa
|
||||
from .hcloud import Client # noqa
|
14
plugins/module_utils/vendor/hcloud/_exceptions.py
vendored
Normal file
14
plugins/module_utils/vendor/hcloud/_exceptions.py
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
class HCloudException(Exception):
|
||||
"""There was an error while using the hcloud library"""
|
||||
|
||||
|
||||
class APIException(HCloudException):
|
||||
"""There was an error while performing an API Request"""
|
||||
|
||||
def __init__(self, code, message, details):
|
||||
self.code = code
|
||||
self.message = message
|
||||
self.details = details
|
||||
|
||||
def __str__(self):
|
||||
return self.message
|
1
plugins/module_utils/vendor/hcloud/_version.py
vendored
Normal file
1
plugins/module_utils/vendor/hcloud/_version.py
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
VERSION = "1.24.0" # x-release-please-version
|
0
plugins/module_utils/vendor/hcloud/actions/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/actions/__init__.py
vendored
Normal file
90
plugins/module_utils/vendor/hcloud/actions/client.py
vendored
Normal file
90
plugins/module_utils/vendor/hcloud/actions/client.py
vendored
Normal file
|
@ -0,0 +1,90 @@
|
|||
import time
|
||||
|
||||
from ..core.client import BoundModelBase, ClientEntityBase
|
||||
from .domain import Action, ActionFailedException, ActionTimeoutException
|
||||
|
||||
|
||||
class BoundAction(BoundModelBase):
|
||||
model = Action
|
||||
|
||||
def wait_until_finished(self, max_retries=100):
|
||||
"""Wait until the specific action has status="finished" (set Client.poll_interval to specify a delay between checks)
|
||||
|
||||
:param max_retries: int
|
||||
Specify how many retries will be performed before an ActionTimeoutException will be raised
|
||||
:raises: ActionFailedException when action is finished with status=="error"
|
||||
:raises: ActionTimeoutException when Action is still in "running" state after max_retries reloads.
|
||||
"""
|
||||
while self.status == Action.STATUS_RUNNING:
|
||||
if max_retries > 0:
|
||||
self.reload()
|
||||
time.sleep(self._client._client.poll_interval)
|
||||
max_retries = max_retries - 1
|
||||
else:
|
||||
raise ActionTimeoutException(action=self)
|
||||
|
||||
if self.status == Action.STATUS_ERROR:
|
||||
raise ActionFailedException(action=self)
|
||||
|
||||
|
||||
class ActionsClient(ClientEntityBase):
|
||||
results_list_attribute_name = "actions"
|
||||
|
||||
def get_by_id(self, id):
|
||||
# type: (int) -> BoundAction
|
||||
"""Get a specific action by its ID.
|
||||
|
||||
:param id: int
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
|
||||
response = self._client.request(url=f"/actions/{id}", method="GET")
|
||||
return BoundAction(self, response["action"])
|
||||
|
||||
def get_list(
|
||||
self,
|
||||
status=None, # type: Optional[List[str]]
|
||||
sort=None, # type: Optional[List[str]]
|
||||
page=None, # type: Optional[int]
|
||||
per_page=None, # type: Optional[int]
|
||||
):
|
||||
# type: (...) -> PageResults[List[BoundAction]]
|
||||
"""Get a list of actions from this account
|
||||
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `command` `status` `progress` `started` `finished` . You can add one of ":asc", ":desc" to modify sort order. ( ":asc" is default)
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
if status is not None:
|
||||
params["status"] = status
|
||||
if sort is not None:
|
||||
params["sort"] = sort
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
|
||||
response = self._client.request(url="/actions", method="GET", params=params)
|
||||
actions = [
|
||||
BoundAction(self, action_data) for action_data in response["actions"]
|
||||
]
|
||||
return self._add_meta_to_result(actions, response)
|
||||
|
||||
def get_all(self, status=None, sort=None):
|
||||
# type: (Optional[List[str]], Optional[List[str]]) -> List[BoundAction]
|
||||
"""Get all actions of the account
|
||||
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `command` `status` `progress` `started` `finished` . You can add one of ":asc", ":desc" to modify sort order. ( ":asc" is default)
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
return super().get_all(status=status, sort=sort)
|
75
plugins/module_utils/vendor/hcloud/actions/domain.py
vendored
Normal file
75
plugins/module_utils/vendor/hcloud/actions/domain.py
vendored
Normal file
|
@ -0,0 +1,75 @@
|
|||
try:
|
||||
from dateutil.parser import isoparse
|
||||
except ImportError:
|
||||
isoparse = None
|
||||
|
||||
from .._exceptions import HCloudException
|
||||
from ..core.domain import BaseDomain
|
||||
|
||||
|
||||
class Action(BaseDomain):
|
||||
"""Action Domain
|
||||
|
||||
:param id: int ID of an action
|
||||
:param command: Command executed in the action
|
||||
:param status: Status of the action
|
||||
:param progress: Progress of action in percent
|
||||
:param started: Point in time when the action was started
|
||||
:param datetime,None finished: Point in time when the action was finished. Only set if the action is finished otherwise None
|
||||
:param resources: Resources the action relates to
|
||||
:param error: Error message for the action if error occurred, otherwise None.
|
||||
"""
|
||||
|
||||
STATUS_RUNNING = "running"
|
||||
"""Action Status running"""
|
||||
STATUS_SUCCESS = "success"
|
||||
"""Action Status success"""
|
||||
STATUS_ERROR = "error"
|
||||
"""Action Status error"""
|
||||
|
||||
__slots__ = (
|
||||
"id",
|
||||
"command",
|
||||
"status",
|
||||
"progress",
|
||||
"resources",
|
||||
"error",
|
||||
"started",
|
||||
"finished",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id,
|
||||
command=None,
|
||||
status=None,
|
||||
progress=None,
|
||||
started=None,
|
||||
finished=None,
|
||||
resources=None,
|
||||
error=None,
|
||||
):
|
||||
self.id = id
|
||||
self.command = command
|
||||
|
||||
self.status = status
|
||||
self.progress = progress
|
||||
self.started = isoparse(started) if started else None
|
||||
self.finished = isoparse(finished) if finished else None
|
||||
self.resources = resources
|
||||
self.error = error
|
||||
|
||||
|
||||
class ActionException(HCloudException):
|
||||
"""A generic action exception"""
|
||||
|
||||
def __init__(self, action):
|
||||
self.action = action
|
||||
|
||||
|
||||
class ActionFailedException(ActionException):
|
||||
"""The Action you were waiting for failed"""
|
||||
|
||||
|
||||
class ActionTimeoutException(ActionException):
|
||||
"""The Action you were waiting for timed out"""
|
0
plugins/module_utils/vendor/hcloud/certificates/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/certificates/__init__.py
vendored
Normal file
316
plugins/module_utils/vendor/hcloud/certificates/client.py
vendored
Normal file
316
plugins/module_utils/vendor/hcloud/certificates/client.py
vendored
Normal file
|
@ -0,0 +1,316 @@
|
|||
from ..actions.client import BoundAction
|
||||
from ..core.client import BoundModelBase, ClientEntityBase, GetEntityByNameMixin
|
||||
from ..core.domain import add_meta_to_result
|
||||
from .domain import (
|
||||
Certificate,
|
||||
CreateManagedCertificateResponse,
|
||||
ManagedCertificateError,
|
||||
ManagedCertificateStatus,
|
||||
)
|
||||
|
||||
|
||||
class BoundCertificate(BoundModelBase):
|
||||
model = Certificate
|
||||
|
||||
def __init__(self, client, data, complete=True):
|
||||
status = data.get("status")
|
||||
if status is not None:
|
||||
error_data = status.get("error")
|
||||
error = None
|
||||
if error_data:
|
||||
error = ManagedCertificateError(
|
||||
code=error_data["code"], message=error_data["message"]
|
||||
)
|
||||
data["status"] = ManagedCertificateStatus(
|
||||
issuance=status["issuance"], renewal=status["renewal"], error=error
|
||||
)
|
||||
super().__init__(client, data, complete)
|
||||
|
||||
def get_actions_list(self, status=None, sort=None, page=None, per_page=None):
|
||||
# type: (Optional[List[str]], Optional[List[str]], Optional[int], Optional[int]) -> PageResults[List[BoundAction, Meta]]
|
||||
"""Returns all action objects for a Certificate.
|
||||
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
return self._client.get_actions_list(self, status, sort, page, per_page)
|
||||
|
||||
def get_actions(self, status=None, sort=None):
|
||||
# type: (Optional[List[str]], Optional[List[str]]) -> List[BoundAction]
|
||||
"""Returns all action objects for a Certificate.
|
||||
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
return self._client.get_actions(self, status, sort)
|
||||
|
||||
def update(self, name=None, labels=None):
|
||||
# type: (Optional[str], Optional[Dict[str, str]]) -> BoundCertificate
|
||||
"""Updates an certificate. You can update an certificate name and the certificate labels.
|
||||
|
||||
:param name: str (optional)
|
||||
New name to set
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:return: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>
|
||||
"""
|
||||
return self._client.update(self, name, labels)
|
||||
|
||||
def delete(self):
|
||||
# type: () -> bool
|
||||
"""Deletes a certificate.
|
||||
:return: boolean
|
||||
"""
|
||||
return self._client.delete(self)
|
||||
|
||||
def retry_issuance(self):
|
||||
# type: () -> BoundAction
|
||||
"""Retry a failed Certificate issuance or renewal.
|
||||
:return: BoundAction
|
||||
"""
|
||||
return self._client.retry_issuance(self)
|
||||
|
||||
|
||||
class CertificatesClient(ClientEntityBase, GetEntityByNameMixin):
|
||||
results_list_attribute_name = "certificates"
|
||||
|
||||
def get_by_id(self, id):
|
||||
# type: (int) -> BoundCertificate
|
||||
"""Get a specific certificate by its ID.
|
||||
|
||||
:param id: int
|
||||
:return: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>`
|
||||
"""
|
||||
response = self._client.request(url=f"/certificates/{id}", method="GET")
|
||||
return BoundCertificate(self, response["certificate"])
|
||||
|
||||
def get_list(
|
||||
self,
|
||||
name=None, # type: Optional[str]
|
||||
label_selector=None, # type: Optional[str]
|
||||
page=None, # type: Optional[int]
|
||||
per_page=None, # type: Optional[int]
|
||||
):
|
||||
# type: (...) -> PageResults[List[BoundCertificate], Meta]
|
||||
"""Get a list of certificates
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter certificates by their name.
|
||||
:param label_selector: str (optional)
|
||||
Can be used to filter certificates by labels. The response will only contain certificates matching the label selector.
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
if name is not None:
|
||||
params["name"] = name
|
||||
|
||||
if label_selector is not None:
|
||||
params["label_selector"] = label_selector
|
||||
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
|
||||
response = self._client.request(
|
||||
url="/certificates", method="GET", params=params
|
||||
)
|
||||
|
||||
certificates = [
|
||||
BoundCertificate(self, certificate_data)
|
||||
for certificate_data in response["certificates"]
|
||||
]
|
||||
|
||||
return self._add_meta_to_result(certificates, response)
|
||||
|
||||
def get_all(self, name=None, label_selector=None):
|
||||
# type: (Optional[str], Optional[str]) -> List[BoundCertificate]
|
||||
"""Get all certificates
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter certificates by their name.
|
||||
:param label_selector: str (optional)
|
||||
Can be used to filter certificates by labels. The response will only contain certificates matching the label selector.
|
||||
:return: List[:class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>`]
|
||||
"""
|
||||
return super().get_all(name=name, label_selector=label_selector)
|
||||
|
||||
def get_by_name(self, name):
|
||||
# type: (str) -> BoundCertificate
|
||||
"""Get certificate by name
|
||||
|
||||
:param name: str
|
||||
Used to get certificate by name.
|
||||
:return: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>`
|
||||
"""
|
||||
return super().get_by_name(name)
|
||||
|
||||
def create(self, name, certificate, private_key, labels=None):
|
||||
# type: (str, str, str, Optional[Dict[str, str]]) -> BoundCertificate
|
||||
"""Creates a new Certificate with the given name, certificate and private_key. This methods allows only creating
|
||||
custom uploaded certificates. If you want to create a managed certificate use :func:`~hcloud.certificates.client.CertificatesClient.create_managed`
|
||||
|
||||
:param name: str
|
||||
:param certificate: str
|
||||
Certificate and chain in PEM format, in order so that each record directly certifies the one preceding
|
||||
:param private_key: str
|
||||
Certificate key in PEM format
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:return: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>`
|
||||
"""
|
||||
data = {
|
||||
"name": name,
|
||||
"certificate": certificate,
|
||||
"private_key": private_key,
|
||||
"type": Certificate.TYPE_UPLOADED,
|
||||
}
|
||||
if labels is not None:
|
||||
data["labels"] = labels
|
||||
response = self._client.request(url="/certificates", method="POST", json=data)
|
||||
return BoundCertificate(self, response["certificate"])
|
||||
|
||||
def create_managed(self, name, domain_names, labels=None):
|
||||
# type: (str, List[str], Optional[Dict[str, str]]) -> CreateManagedCertificateResponse
|
||||
"""Creates a new managed Certificate with the given name and domain names. This methods allows only creating
|
||||
managed certificates for domains that are using the Hetzner DNS service. If you want to create a custom uploaded certificate use :func:`~hcloud.certificates.client.CertificatesClient.create`
|
||||
|
||||
:param name: str
|
||||
:param domain_names: List[str]
|
||||
Domains and subdomains that should be contained in the Certificate
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:return: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>`
|
||||
"""
|
||||
data = {
|
||||
"name": name,
|
||||
"type": Certificate.TYPE_MANAGED,
|
||||
"domain_names": domain_names,
|
||||
}
|
||||
if labels is not None:
|
||||
data["labels"] = labels
|
||||
response = self._client.request(url="/certificates", method="POST", json=data)
|
||||
return CreateManagedCertificateResponse(
|
||||
certificate=BoundCertificate(self, response["certificate"]),
|
||||
action=BoundAction(self._client.actions, response["action"]),
|
||||
)
|
||||
|
||||
def update(self, certificate, name=None, labels=None):
|
||||
# type: (Certificate, Optional[str], Optional[Dict[str, str]]) -> BoundCertificate
|
||||
"""Updates a Certificate. You can update a certificate name and labels.
|
||||
|
||||
:param certificate: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>` or :class:`Certificate <hcloud.certificates.domain.Certificate>`
|
||||
:param name: str (optional)
|
||||
New name to set
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:return: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>`
|
||||
"""
|
||||
data = {}
|
||||
if name is not None:
|
||||
data["name"] = name
|
||||
if labels is not None:
|
||||
data["labels"] = labels
|
||||
response = self._client.request(
|
||||
url=f"/certificates/{certificate.id}",
|
||||
method="PUT",
|
||||
json=data,
|
||||
)
|
||||
return BoundCertificate(self, response["certificate"])
|
||||
|
||||
def delete(self, certificate):
|
||||
# type: (Certificate) -> bool
|
||||
self._client.request(
|
||||
url=f"/certificates/{certificate.id}",
|
||||
method="DELETE",
|
||||
)
|
||||
"""Deletes a certificate.
|
||||
|
||||
:param certificate: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>` or :class:`Certificate <hcloud.certificates.domain.Certificate>`
|
||||
:return: True
|
||||
"""
|
||||
# Return always true, because the API does not return an action for it. When an error occurs a HcloudAPIException will be raised
|
||||
return True
|
||||
|
||||
def get_actions_list(
|
||||
self, certificate, status=None, sort=None, page=None, per_page=None
|
||||
):
|
||||
# type: (Certificate, Optional[List[str]], Optional[List[str]], Optional[int], Optional[int]) -> PageResults[List[BoundAction], Meta]
|
||||
"""Returns all action objects for a Certificate.
|
||||
|
||||
:param certificate: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>` or :class:`Certificate <hcloud.certificates.domain.Certificate>`
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
if status is not None:
|
||||
params["status"] = status
|
||||
if sort is not None:
|
||||
params["sort"] = sort
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
|
||||
response = self._client.request(
|
||||
url="/certificates/{certificate_id}/actions".format(
|
||||
certificate_id=certificate.id
|
||||
),
|
||||
method="GET",
|
||||
params=params,
|
||||
)
|
||||
actions = [
|
||||
BoundAction(self._client.actions, action_data)
|
||||
for action_data in response["actions"]
|
||||
]
|
||||
return add_meta_to_result(actions, response, "actions")
|
||||
|
||||
def get_actions(self, certificate, status=None, sort=None):
|
||||
# type: (Certificate, Optional[List[str]], Optional[List[str]]) -> List[BoundAction]
|
||||
"""Returns all action objects for a Certificate.
|
||||
|
||||
:param certificate: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>` or :class:`Certificate <hcloud.certificates.domain.Certificate>`
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
return super().get_actions(certificate, status=status, sort=sort)
|
||||
|
||||
def retry_issuance(self, certificate):
|
||||
# type: (Certificate) -> BoundAction
|
||||
"""Returns all action objects for a Certificate.
|
||||
|
||||
:param certificate: :class:`BoundCertificate <hcloud.certificates.client.BoundCertificate>` or :class:`Certificate <hcloud.certificates.domain.Certificate>`
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
response = self._client.request(
|
||||
url="/certificates/{certificate_id}/actions/retry".format(
|
||||
certificate_id=certificate.id
|
||||
),
|
||||
method="POST",
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
120
plugins/module_utils/vendor/hcloud/certificates/domain.py
vendored
Normal file
120
plugins/module_utils/vendor/hcloud/certificates/domain.py
vendored
Normal file
|
@ -0,0 +1,120 @@
|
|||
try:
|
||||
from dateutil.parser import isoparse
|
||||
except ImportError:
|
||||
isoparse = None
|
||||
|
||||
from ..core.domain import BaseDomain, DomainIdentityMixin
|
||||
|
||||
|
||||
class Certificate(BaseDomain, DomainIdentityMixin):
|
||||
"""Certificate Domain
|
||||
|
||||
:param id: int ID of Certificate
|
||||
:param name: str Name of Certificate
|
||||
:param certificate: str Certificate and chain in PEM format, in order so that each record directly certifies the one preceding
|
||||
:param not_valid_before: datetime
|
||||
Point in time when the Certificate becomes valid
|
||||
:param not_valid_after: datetime
|
||||
Point in time when the Certificate becomes invalid
|
||||
:param domain_names: List[str] List of domains and subdomains covered by this certificate
|
||||
:param fingerprint: str Fingerprint of the Certificate
|
||||
:param labels: dict
|
||||
User-defined labels (key-value pairs)
|
||||
:param created: datetime
|
||||
Point in time when the certificate was created
|
||||
:param type: str Type of Certificate
|
||||
:param status: ManagedCertificateStatus Current status of a type managed Certificate, always none for type uploaded Certificates
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"id",
|
||||
"name",
|
||||
"certificate",
|
||||
"not_valid_before",
|
||||
"not_valid_after",
|
||||
"domain_names",
|
||||
"fingerprint",
|
||||
"created",
|
||||
"labels",
|
||||
"type",
|
||||
"status",
|
||||
)
|
||||
TYPE_UPLOADED = "uploaded"
|
||||
TYPE_MANAGED = "managed"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id=None,
|
||||
name=None,
|
||||
certificate=None,
|
||||
not_valid_before=None,
|
||||
not_valid_after=None,
|
||||
domain_names=None,
|
||||
fingerprint=None,
|
||||
created=None,
|
||||
labels=None,
|
||||
type=None,
|
||||
status=None,
|
||||
):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.type = type
|
||||
self.certificate = certificate
|
||||
self.domain_names = domain_names
|
||||
self.fingerprint = fingerprint
|
||||
self.not_valid_before = isoparse(not_valid_before) if not_valid_before else None
|
||||
self.not_valid_after = isoparse(not_valid_after) if not_valid_after else None
|
||||
self.created = isoparse(created) if created else None
|
||||
self.labels = labels
|
||||
self.status = status
|
||||
|
||||
|
||||
class ManagedCertificateStatus(BaseDomain):
|
||||
"""ManagedCertificateStatus Domain
|
||||
|
||||
:param issuance: str
|
||||
Status of the issuance process of the Certificate
|
||||
:param renewal: str
|
||||
Status of the renewal process of the Certificate
|
||||
:param error: ManagedCertificateError
|
||||
If issuance or renewal reports failure, this property contains information about what happened
|
||||
"""
|
||||
|
||||
def __init__(self, issuance=None, renewal=None, error=None):
|
||||
self.issuance = issuance
|
||||
self.renewal = renewal
|
||||
self.error = error
|
||||
|
||||
|
||||
class ManagedCertificateError(BaseDomain):
|
||||
"""ManagedCertificateError Domain
|
||||
|
||||
:param code: str
|
||||
Error code identifying the error
|
||||
:param message:
|
||||
Message detailing the error
|
||||
"""
|
||||
|
||||
def __init__(self, code=None, message=None):
|
||||
self.code = code
|
||||
self.message = message
|
||||
|
||||
|
||||
class CreateManagedCertificateResponse(BaseDomain):
|
||||
"""Create Managed Certificate Response Domain
|
||||
|
||||
:param certificate: :class:`BoundCertificate <hcloud.certificate.client.BoundCertificate>`
|
||||
The created server
|
||||
:param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
Shows the progress of the certificate creation
|
||||
"""
|
||||
|
||||
__slots__ = ("certificate", "action")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
certificate, # type: BoundCertificate
|
||||
action, # type: BoundAction
|
||||
):
|
||||
self.certificate = certificate
|
||||
self.action = action
|
0
plugins/module_utils/vendor/hcloud/core/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/core/__init__.py
vendored
Normal file
127
plugins/module_utils/vendor/hcloud/core/client.py
vendored
Normal file
127
plugins/module_utils/vendor/hcloud/core/client.py
vendored
Normal file
|
@ -0,0 +1,127 @@
|
|||
from .domain import add_meta_to_result
|
||||
|
||||
|
||||
class ClientEntityBase:
|
||||
max_per_page = 50
|
||||
results_list_attribute_name = None
|
||||
|
||||
def __init__(self, client):
|
||||
"""
|
||||
:param client: Client
|
||||
:return self
|
||||
"""
|
||||
self._client = client
|
||||
|
||||
def _is_list_attribute_implemented(self):
|
||||
if self.results_list_attribute_name is None:
|
||||
raise NotImplementedError(
|
||||
"in order to get results list, 'results_list_attribute_name' attribute of {} has to be specified".format(
|
||||
self.__class__.__name__
|
||||
)
|
||||
)
|
||||
|
||||
def _add_meta_to_result(
|
||||
self,
|
||||
results, # type: List[BoundModelBase]
|
||||
response, # type: json
|
||||
):
|
||||
# type: (...) -> PageResult
|
||||
self._is_list_attribute_implemented()
|
||||
return add_meta_to_result(results, response, self.results_list_attribute_name)
|
||||
|
||||
def _get_all(
|
||||
self,
|
||||
list_function, # type: function
|
||||
results_list_attribute_name, # type: str
|
||||
*args,
|
||||
**kwargs
|
||||
):
|
||||
# type (...) -> List[BoundModelBase]
|
||||
|
||||
page = 1
|
||||
|
||||
results = []
|
||||
|
||||
while page:
|
||||
page_result = list_function(
|
||||
page=page, per_page=self.max_per_page, *args, **kwargs
|
||||
)
|
||||
result = getattr(page_result, results_list_attribute_name)
|
||||
if result:
|
||||
results.extend(result)
|
||||
meta = page_result.meta
|
||||
if (
|
||||
meta
|
||||
and meta.pagination
|
||||
and meta.pagination.next_page
|
||||
and meta.pagination.next_page
|
||||
):
|
||||
page = meta.pagination.next_page
|
||||
else:
|
||||
page = None
|
||||
|
||||
return results
|
||||
|
||||
def get_all(self, *args, **kwargs):
|
||||
# type: (...) -> List[BoundModelBase]
|
||||
self._is_list_attribute_implemented()
|
||||
return self._get_all(
|
||||
self.get_list, self.results_list_attribute_name, *args, **kwargs
|
||||
)
|
||||
|
||||
def get_actions(self, *args, **kwargs):
|
||||
# type: (...) -> List[BoundModelBase]
|
||||
if not hasattr(self, "get_actions_list"):
|
||||
raise ValueError("this endpoint does not support get_actions method")
|
||||
|
||||
return self._get_all(self.get_actions_list, "actions", *args, **kwargs)
|
||||
|
||||
|
||||
class GetEntityByNameMixin:
|
||||
"""
|
||||
Use as a mixin for ClientEntityBase classes
|
||||
"""
|
||||
|
||||
def get_by_name(self, name):
|
||||
# type: (str) -> BoundModelBase
|
||||
self._is_list_attribute_implemented()
|
||||
response = self.get_list(name=name)
|
||||
entities = getattr(response, self.results_list_attribute_name)
|
||||
entity = entities[0] if entities else None
|
||||
return entity
|
||||
|
||||
|
||||
class BoundModelBase:
|
||||
"""Bound Model Base"""
|
||||
|
||||
model = None
|
||||
|
||||
def __init__(self, client, data={}, complete=True):
|
||||
"""
|
||||
:param client:
|
||||
The client for the specific model to use
|
||||
:param data:
|
||||
The data of the model
|
||||
:param complete: bool
|
||||
False if not all attributes of the model fetched
|
||||
"""
|
||||
self._client = client
|
||||
self.complete = complete
|
||||
self.data_model = self.model.from_dict(data)
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""Allow magical access to the properties of the model
|
||||
:param name: str
|
||||
:return:
|
||||
"""
|
||||
value = getattr(self.data_model, name)
|
||||
if not value and not self.complete:
|
||||
self.reload()
|
||||
value = getattr(self.data_model, name)
|
||||
return value
|
||||
|
||||
def reload(self):
|
||||
"""Reloads the model and tries to get all data from the APIx"""
|
||||
bound_model = self._client.get_by_id(self.data_model.id)
|
||||
self.data_model = bound_model.data_model
|
||||
self.complete = True
|
75
plugins/module_utils/vendor/hcloud/core/domain.py
vendored
Normal file
75
plugins/module_utils/vendor/hcloud/core/domain.py
vendored
Normal file
|
@ -0,0 +1,75 @@
|
|||
from collections import namedtuple
|
||||
|
||||
|
||||
class BaseDomain:
|
||||
__slots__ = ()
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data):
|
||||
supported_data = {k: v for k, v in data.items() if k in cls.__slots__}
|
||||
return cls(**supported_data)
|
||||
|
||||
|
||||
class DomainIdentityMixin:
|
||||
__slots__ = ()
|
||||
|
||||
@property
|
||||
def id_or_name(self):
|
||||
if self.id is not None:
|
||||
return self.id
|
||||
elif self.name is not None:
|
||||
return self.name
|
||||
else:
|
||||
raise ValueError("id or name must be set")
|
||||
|
||||
|
||||
class Pagination(BaseDomain):
|
||||
__slots__ = (
|
||||
"page",
|
||||
"per_page",
|
||||
"previous_page",
|
||||
"next_page",
|
||||
"last_page",
|
||||
"total_entries",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
page,
|
||||
per_page,
|
||||
previous_page=None,
|
||||
next_page=None,
|
||||
last_page=None,
|
||||
total_entries=None,
|
||||
):
|
||||
self.page = page
|
||||
self.per_page = per_page
|
||||
self.previous_page = previous_page
|
||||
self.next_page = next_page
|
||||
self.last_page = last_page
|
||||
self.total_entries = total_entries
|
||||
|
||||
|
||||
class Meta(BaseDomain):
|
||||
__slots__ = ("pagination",)
|
||||
|
||||
def __init__(self, pagination=None):
|
||||
self.pagination = pagination
|
||||
|
||||
@classmethod
|
||||
def parse_meta(cls, json_content):
|
||||
meta = None
|
||||
if json_content and "meta" in json_content:
|
||||
meta = cls()
|
||||
pagination_json = json_content["meta"].get("pagination")
|
||||
if pagination_json:
|
||||
pagination = Pagination(**pagination_json)
|
||||
meta.pagination = pagination
|
||||
return meta
|
||||
|
||||
|
||||
def add_meta_to_result(result, json_content, attr_name):
|
||||
# type: (List[BoundModelBase], json, string) -> PageResult
|
||||
class_name = f"PageResults{attr_name.capitalize()}"
|
||||
PageResults = namedtuple(class_name, [attr_name, "meta"])
|
||||
return PageResults(**{attr_name: result, "meta": Meta.parse_meta(json_content)})
|
0
plugins/module_utils/vendor/hcloud/datacenters/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/datacenters/__init__.py
vendored
Normal file
111
plugins/module_utils/vendor/hcloud/datacenters/client.py
vendored
Normal file
111
plugins/module_utils/vendor/hcloud/datacenters/client.py
vendored
Normal file
|
@ -0,0 +1,111 @@
|
|||
from ..core.client import BoundModelBase, ClientEntityBase, GetEntityByNameMixin
|
||||
from ..locations.client import BoundLocation
|
||||
from ..server_types.client import BoundServerType
|
||||
from .domain import Datacenter, DatacenterServerTypes
|
||||
|
||||
|
||||
class BoundDatacenter(BoundModelBase):
|
||||
model = Datacenter
|
||||
|
||||
def __init__(self, client, data):
|
||||
location = data.get("location")
|
||||
if location is not None:
|
||||
data["location"] = BoundLocation(client._client.locations, location)
|
||||
|
||||
server_types = data.get("server_types")
|
||||
if server_types is not None:
|
||||
available = [
|
||||
BoundServerType(
|
||||
client._client.server_types, {"id": server_type}, complete=False
|
||||
)
|
||||
for server_type in server_types["available"]
|
||||
]
|
||||
supported = [
|
||||
BoundServerType(
|
||||
client._client.server_types, {"id": server_type}, complete=False
|
||||
)
|
||||
for server_type in server_types["supported"]
|
||||
]
|
||||
available_for_migration = [
|
||||
BoundServerType(
|
||||
client._client.server_types, {"id": server_type}, complete=False
|
||||
)
|
||||
for server_type in server_types["available_for_migration"]
|
||||
]
|
||||
data["server_types"] = DatacenterServerTypes(
|
||||
available=available,
|
||||
supported=supported,
|
||||
available_for_migration=available_for_migration,
|
||||
)
|
||||
|
||||
super().__init__(client, data)
|
||||
|
||||
|
||||
class DatacentersClient(ClientEntityBase, GetEntityByNameMixin):
|
||||
results_list_attribute_name = "datacenters"
|
||||
|
||||
def get_by_id(self, id):
|
||||
# type: (int) -> BoundDatacenter
|
||||
"""Get a specific datacenter by its ID.
|
||||
|
||||
:param id: int
|
||||
:return: :class:`BoundDatacenter <hcloud.datacenters.client.BoundDatacenter>`
|
||||
"""
|
||||
response = self._client.request(url=f"/datacenters/{id}", method="GET")
|
||||
return BoundDatacenter(self, response["datacenter"])
|
||||
|
||||
def get_list(
|
||||
self,
|
||||
name=None, # type: Optional[str]
|
||||
page=None, # type: Optional[int]
|
||||
per_page=None, # type: Optional[int]
|
||||
):
|
||||
# type: (...) -> PageResults[List[BoundDatacenter], Meta]
|
||||
"""Get a list of datacenters
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter datacenters by their name.
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundDatacenter <hcloud.datacenters.client.BoundDatacenter>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
if name is not None:
|
||||
params["name"] = name
|
||||
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
|
||||
response = self._client.request(url="/datacenters", method="GET", params=params)
|
||||
|
||||
datacenters = [
|
||||
BoundDatacenter(self, datacenter_data)
|
||||
for datacenter_data in response["datacenters"]
|
||||
]
|
||||
|
||||
return self._add_meta_to_result(datacenters, response)
|
||||
|
||||
def get_all(self, name=None):
|
||||
# type: (Optional[str]) -> List[BoundDatacenter]
|
||||
"""Get all datacenters
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter datacenters by their name.
|
||||
:return: List[:class:`BoundDatacenter <hcloud.datacenters.client.BoundDatacenter>`]
|
||||
"""
|
||||
return super().get_all(name=name)
|
||||
|
||||
def get_by_name(self, name):
|
||||
# type: (str) -> BoundDatacenter
|
||||
"""Get datacenter by name
|
||||
|
||||
:param name: str
|
||||
Used to get datacenter by name.
|
||||
:return: :class:`BoundDatacenter <hcloud.datacenters.client.BoundDatacenter>`
|
||||
"""
|
||||
return super().get_by_name(name)
|
42
plugins/module_utils/vendor/hcloud/datacenters/domain.py
vendored
Normal file
42
plugins/module_utils/vendor/hcloud/datacenters/domain.py
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
from ..core.domain import BaseDomain, DomainIdentityMixin
|
||||
|
||||
|
||||
class Datacenter(BaseDomain, DomainIdentityMixin):
|
||||
"""Datacenter Domain
|
||||
|
||||
:param id: int ID of Datacenter
|
||||
:param name: str Name of Datacenter
|
||||
:param description: str Description of Datacenter
|
||||
:param location: :class:`BoundLocation <hcloud.locations.client.BoundLocation>`
|
||||
:param server_types: :class:`DatacenterServerTypes <hcloud.datacenters.domain.DatacenterServerTypes>`
|
||||
"""
|
||||
|
||||
__slots__ = ("id", "name", "description", "location", "server_types")
|
||||
|
||||
def __init__(
|
||||
self, id=None, name=None, description=None, location=None, server_types=None
|
||||
):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.location = location
|
||||
self.server_types = server_types
|
||||
|
||||
|
||||
class DatacenterServerTypes:
|
||||
"""DatacenterServerTypes Domain
|
||||
|
||||
:param available: List[:class:`BoundServerTypes <hcloud.server_types.client.BoundServerTypes>`]
|
||||
All available server types for this datacenter
|
||||
:param supported: List[:class:`BoundServerTypes <hcloud.server_types.client.BoundServerTypes>`]
|
||||
All supported server types for this datacenter
|
||||
:param available_for_migration: List[:class:`BoundServerTypes <hcloud.server_types.client.BoundServerTypes>`]
|
||||
All available for migration (change type) server types for this datacenter
|
||||
"""
|
||||
|
||||
__slots__ = ("available", "supported", "available_for_migration")
|
||||
|
||||
def __init__(self, available, supported, available_for_migration):
|
||||
self.available = available
|
||||
self.supported = supported
|
||||
self.available_for_migration = available_for_migration
|
0
plugins/module_utils/vendor/hcloud/deprecation/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/deprecation/__init__.py
vendored
Normal file
34
plugins/module_utils/vendor/hcloud/deprecation/domain.py
vendored
Normal file
34
plugins/module_utils/vendor/hcloud/deprecation/domain.py
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
try:
|
||||
from dateutil.parser import isoparse
|
||||
except ImportError:
|
||||
isoparse = None
|
||||
|
||||
from ..core.domain import BaseDomain
|
||||
|
||||
|
||||
class DeprecationInfo(BaseDomain):
|
||||
"""Describes if, when & how the resources was deprecated. If this field is set to ``None`` the resource is not
|
||||
deprecated. If it has a value, it is considered deprecated.
|
||||
|
||||
:param announced: datetime
|
||||
Date of when the deprecation was announced.
|
||||
:param unavailable_after: datetime
|
||||
After the time in this field, the resource will not be available from the general listing endpoint of the
|
||||
resource type, and it can not be used in new resources. For example, if this is an image, you can not create
|
||||
new servers with this image after the mentioned date.
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"announced",
|
||||
"unavailable_after",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
announced=None,
|
||||
unavailable_after=None,
|
||||
):
|
||||
self.announced = isoparse(announced) if announced else None
|
||||
self.unavailable_after = (
|
||||
isoparse(unavailable_after) if unavailable_after else None
|
||||
)
|
0
plugins/module_utils/vendor/hcloud/firewalls/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/firewalls/__init__.py
vendored
Normal file
416
plugins/module_utils/vendor/hcloud/firewalls/client.py
vendored
Normal file
416
plugins/module_utils/vendor/hcloud/firewalls/client.py
vendored
Normal file
|
@ -0,0 +1,416 @@
|
|||
from ..actions.client import BoundAction
|
||||
from ..core.client import BoundModelBase, ClientEntityBase, GetEntityByNameMixin
|
||||
from ..core.domain import add_meta_to_result
|
||||
from .domain import (
|
||||
CreateFirewallResponse,
|
||||
Firewall,
|
||||
FirewallResource,
|
||||
FirewallResourceLabelSelector,
|
||||
FirewallRule,
|
||||
)
|
||||
|
||||
|
||||
class BoundFirewall(BoundModelBase):
|
||||
model = Firewall
|
||||
|
||||
def __init__(self, client, data, complete=True):
|
||||
rules = data.get("rules", [])
|
||||
if rules:
|
||||
rules = [
|
||||
FirewallRule(
|
||||
direction=rule["direction"],
|
||||
source_ips=rule["source_ips"],
|
||||
destination_ips=rule["destination_ips"],
|
||||
protocol=rule["protocol"],
|
||||
port=rule["port"],
|
||||
description=rule["description"],
|
||||
)
|
||||
for rule in rules
|
||||
]
|
||||
data["rules"] = rules
|
||||
|
||||
applied_to = data.get("applied_to", [])
|
||||
if applied_to:
|
||||
from ..servers.client import BoundServer
|
||||
|
||||
ats = []
|
||||
for a in applied_to:
|
||||
if a["type"] == FirewallResource.TYPE_SERVER:
|
||||
ats.append(
|
||||
FirewallResource(
|
||||
type=a["type"],
|
||||
server=BoundServer(
|
||||
client._client.servers, a["server"], complete=False
|
||||
),
|
||||
)
|
||||
)
|
||||
elif a["type"] == FirewallResource.TYPE_LABEL_SELECTOR:
|
||||
ats.append(
|
||||
FirewallResource(
|
||||
type=a["type"],
|
||||
label_selector=FirewallResourceLabelSelector(
|
||||
selector=a["label_selector"]["selector"]
|
||||
),
|
||||
)
|
||||
)
|
||||
data["applied_to"] = ats
|
||||
|
||||
super().__init__(client, data, complete)
|
||||
|
||||
def get_actions_list(self, status=None, sort=None, page=None, per_page=None):
|
||||
# type: (Optional[List[str]], Optional[List[str]], Optional[int], Optional[int]) -> PageResult[BoundAction, Meta]
|
||||
"""Returns all action objects for a Firewall.
|
||||
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
return self._client.get_actions_list(self, status, sort, page, per_page)
|
||||
|
||||
def get_actions(self, status=None, sort=None):
|
||||
# type: (Optional[List[str]], Optional[List[str]]) -> List[BoundAction]
|
||||
"""Returns all action objects for a Firewall.
|
||||
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
return self._client.get_actions(self, status, sort)
|
||||
|
||||
def update(self, name=None, labels=None):
|
||||
# type: (Optional[str], Optional[Dict[str, str]], Optional[str]) -> BoundFirewall
|
||||
"""Updates the name or labels of a Firewall.
|
||||
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:param name: str (optional)
|
||||
New Name to set
|
||||
:return: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>`
|
||||
"""
|
||||
return self._client.update(self, labels, name)
|
||||
|
||||
def delete(self):
|
||||
# type: () -> bool
|
||||
"""Deletes a Firewall.
|
||||
|
||||
:return: boolean
|
||||
"""
|
||||
return self._client.delete(self)
|
||||
|
||||
def set_rules(self, rules):
|
||||
# type: (List[FirewallRule]) -> List[BoundAction]
|
||||
"""Sets the rules of a Firewall. All existing rules will be overwritten. Pass an empty rules array to remove all rules.
|
||||
:param rules: List[:class:`FirewallRule <hcloud.firewalls.domain.FirewallRule>`]
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
|
||||
return self._client.set_rules(self, rules)
|
||||
|
||||
def apply_to_resources(self, resources):
|
||||
# type: (List[FirewallResource]) -> List[BoundAction]
|
||||
"""Applies one Firewall to multiple resources.
|
||||
:param resources: List[:class:`FirewallResource <hcloud.firewalls.domain.FirewallResource>`]
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
return self._client.apply_to_resources(self, resources)
|
||||
|
||||
def remove_from_resources(self, resources):
|
||||
# type: (List[FirewallResource]) -> List[BoundAction]
|
||||
"""Removes one Firewall from multiple resources.
|
||||
:param resources: List[:class:`FirewallResource <hcloud.firewalls.domain.FirewallResource>`]
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
return self._client.remove_from_resources(self, resources)
|
||||
|
||||
|
||||
class FirewallsClient(ClientEntityBase, GetEntityByNameMixin):
|
||||
results_list_attribute_name = "firewalls"
|
||||
|
||||
def get_actions_list(
|
||||
self,
|
||||
firewall, # type: Firewall
|
||||
status=None, # type: Optional[List[str]]
|
||||
sort=None, # type: Optional[List[str]]
|
||||
page=None, # type: Optional[int]
|
||||
per_page=None, # type: Optional[int]
|
||||
):
|
||||
# type: (...) -> PageResults[List[BoundAction], Meta]
|
||||
"""Returns all action objects for a Firewall.
|
||||
|
||||
:param firewall: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>` or :class:`Firewall <hcloud.firewalls.domain.Firewall>`
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
if status is not None:
|
||||
params["status"] = status
|
||||
if sort is not None:
|
||||
params["sort"] = sort
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
response = self._client.request(
|
||||
url=f"/firewalls/{firewall.id}/actions",
|
||||
method="GET",
|
||||
params=params,
|
||||
)
|
||||
actions = [
|
||||
BoundAction(self._client.actions, action_data)
|
||||
for action_data in response["actions"]
|
||||
]
|
||||
return add_meta_to_result(actions, response, "actions")
|
||||
|
||||
def get_actions(
|
||||
self,
|
||||
firewall, # type: Firewall
|
||||
status=None, # type: Optional[List[str]]
|
||||
sort=None, # type: Optional[List[str]]
|
||||
):
|
||||
# type: (...) -> List[BoundAction]
|
||||
"""Returns all action objects for a Firewall.
|
||||
|
||||
:param firewall: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>` or :class:`Firewall <hcloud.firewalls.domain.Firewall>`
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
return super().get_actions(firewall, status=status, sort=sort)
|
||||
|
||||
def get_by_id(self, id):
|
||||
# type: (int) -> BoundFirewall
|
||||
"""Returns a specific Firewall object.
|
||||
|
||||
:param id: int
|
||||
:return: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>`
|
||||
"""
|
||||
response = self._client.request(url=f"/firewalls/{id}", method="GET")
|
||||
return BoundFirewall(self, response["firewall"])
|
||||
|
||||
def get_list(
|
||||
self,
|
||||
label_selector=None, # type: Optional[str]
|
||||
page=None, # type: Optional[int]
|
||||
per_page=None, # type: Optional[int]
|
||||
name=None, # type: Optional[str]
|
||||
sort=None, # type: Optional[List[str]]
|
||||
):
|
||||
# type: (...) -> PageResults[List[BoundFirewall]]
|
||||
"""Get a list of floating ips from this account
|
||||
|
||||
:param label_selector: str (optional)
|
||||
Can be used to filter Firewalls by labels. The response will only contain Firewalls matching the label selector values.
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:param name: str (optional)
|
||||
Can be used to filter networks by their name.
|
||||
:param sort: List[str] (optional)
|
||||
Choices: id name created (You can add one of ":asc", ":desc" to modify sort order. ( ":asc" is default))
|
||||
:return: (List[:class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
|
||||
if label_selector is not None:
|
||||
params["label_selector"] = label_selector
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
if name is not None:
|
||||
params["name"] = name
|
||||
if sort is not None:
|
||||
params["sort"] = sort
|
||||
response = self._client.request(url="/firewalls", method="GET", params=params)
|
||||
firewalls = [
|
||||
BoundFirewall(self, firewall_data)
|
||||
for firewall_data in response["firewalls"]
|
||||
]
|
||||
|
||||
return self._add_meta_to_result(firewalls, response)
|
||||
|
||||
def get_all(self, label_selector=None, name=None, sort=None):
|
||||
# type: (Optional[str], Optional[str], Optional[List[str]]) -> List[BoundFirewall]
|
||||
"""Get all floating ips from this account
|
||||
|
||||
:param label_selector: str (optional)
|
||||
Can be used to filter Firewalls by labels. The response will only contain Firewalls matching the label selector values.
|
||||
:param name: str (optional)
|
||||
Can be used to filter networks by their name.
|
||||
:param sort: List[str] (optional)
|
||||
Choices: id name created (You can add one of ":asc", ":desc" to modify sort order. ( ":asc" is default))
|
||||
:return: List[:class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>`]
|
||||
"""
|
||||
return super().get_all(label_selector=label_selector, name=name, sort=sort)
|
||||
|
||||
def get_by_name(self, name):
|
||||
# type: (str) -> BoundFirewall
|
||||
"""Get Firewall by name
|
||||
|
||||
:param name: str
|
||||
Used to get Firewall by name.
|
||||
:return: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>`
|
||||
"""
|
||||
return super().get_by_name(name)
|
||||
|
||||
def create(
|
||||
self,
|
||||
name, # type: str
|
||||
rules=None, # type: Optional[List[FirewallRule]]
|
||||
labels=None, # type: Optional[str]
|
||||
resources=None, # type: Optional[List[FirewallResource]]
|
||||
):
|
||||
# type: (...) -> CreateFirewallResponse
|
||||
"""Creates a new Firewall.
|
||||
|
||||
:param name: str
|
||||
Firewall Name
|
||||
:param rules: List[:class:`FirewallRule <hcloud.firewalls.domain.FirewallRule>`] (optional)
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:param resources: List[:class:`FirewallResource <hcloud.firewalls.domain.FirewallResource>`] (optional)
|
||||
:return: :class:`CreateFirewallResponse <hcloud.firewalls.domain.CreateFirewallResponse>`
|
||||
"""
|
||||
|
||||
data = {"name": name}
|
||||
if labels is not None:
|
||||
data["labels"] = labels
|
||||
|
||||
if rules is not None:
|
||||
data.update({"rules": []})
|
||||
for rule in rules:
|
||||
data["rules"].append(rule.to_payload())
|
||||
if resources is not None:
|
||||
data.update({"apply_to": []})
|
||||
for resource in resources:
|
||||
data["apply_to"].append(resource.to_payload())
|
||||
response = self._client.request(url="/firewalls", json=data, method="POST")
|
||||
|
||||
actions = []
|
||||
if response.get("actions") is not None:
|
||||
actions = [
|
||||
BoundAction(self._client.actions, _) for _ in response["actions"]
|
||||
]
|
||||
|
||||
result = CreateFirewallResponse(
|
||||
firewall=BoundFirewall(self, response["firewall"]), actions=actions
|
||||
)
|
||||
return result
|
||||
|
||||
def update(self, firewall, labels=None, name=None):
|
||||
# type: (Firewall, Optional[Dict[str, str]], Optional[str]) -> BoundFirewall
|
||||
"""Updates the description or labels of a Firewall.
|
||||
|
||||
:param firewall: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>` or :class:`Firewall <hcloud.firewalls.domain.Firewall>`
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:param name: str (optional)
|
||||
New name to set
|
||||
:return: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>`
|
||||
"""
|
||||
data = {}
|
||||
if labels is not None:
|
||||
data["labels"] = labels
|
||||
if name is not None:
|
||||
data["name"] = name
|
||||
|
||||
response = self._client.request(
|
||||
url=f"/firewalls/{firewall.id}",
|
||||
method="PUT",
|
||||
json=data,
|
||||
)
|
||||
return BoundFirewall(self, response["firewall"])
|
||||
|
||||
def delete(self, firewall):
|
||||
# type: (Firewall) -> bool
|
||||
"""Deletes a Firewall.
|
||||
|
||||
:param firewall: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>` or :class:`Firewall <hcloud.firewalls.domain.Firewall>`
|
||||
:return: boolean
|
||||
"""
|
||||
self._client.request(
|
||||
url=f"/firewalls/{firewall.id}",
|
||||
method="DELETE",
|
||||
)
|
||||
# Return always true, because the API does not return an action for it. When an error occurs a HcloudAPIException will be raised
|
||||
return True
|
||||
|
||||
def set_rules(self, firewall, rules):
|
||||
# type: (Firewall, List[FirewallRule]) -> List[BoundAction]
|
||||
"""Sets the rules of a Firewall. All existing rules will be overwritten. Pass an empty rules array to remove all rules.
|
||||
|
||||
:param firewall: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>` or :class:`Firewall <hcloud.firewalls.domain.Firewall>`
|
||||
:param rules: List[:class:`FirewallRule <hcloud.firewalls.domain.FirewallRule>`]
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
data = {"rules": []}
|
||||
for rule in rules:
|
||||
data["rules"].append(rule.to_payload())
|
||||
response = self._client.request(
|
||||
url="/firewalls/{firewall_id}/actions/set_rules".format(
|
||||
firewall_id=firewall.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return [BoundAction(self._client.actions, _) for _ in response["actions"]]
|
||||
|
||||
def apply_to_resources(self, firewall, resources):
|
||||
# type: (Firewall, List[FirewallResource]) -> List[BoundAction]
|
||||
"""Applies one Firewall to multiple resources.
|
||||
|
||||
:param firewall: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>` or :class:`Firewall <hcloud.firewalls.domain.Firewall>`
|
||||
:param resources: List[:class:`FirewallResource <hcloud.firewalls.domain.FirewallResource>`]
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
data = {"apply_to": []}
|
||||
for resource in resources:
|
||||
data["apply_to"].append(resource.to_payload())
|
||||
response = self._client.request(
|
||||
url="/firewalls/{firewall_id}/actions/apply_to_resources".format(
|
||||
firewall_id=firewall.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return [BoundAction(self._client.actions, _) for _ in response["actions"]]
|
||||
|
||||
def remove_from_resources(self, firewall, resources):
|
||||
# type: (Firewall, List[FirewallResource]) -> List[BoundAction]
|
||||
"""Removes one Firewall from multiple resources.
|
||||
|
||||
:param firewall: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>` or :class:`Firewall <hcloud.firewalls.domain.Firewall>`
|
||||
:param resources: List[:class:`FirewallResource <hcloud.firewalls.domain.FirewallResource>`]
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
data = {"remove_from": []}
|
||||
for resource in resources:
|
||||
data["remove_from"].append(resource.to_payload())
|
||||
response = self._client.request(
|
||||
url="/firewalls/{firewall_id}/actions/remove_from_resources".format(
|
||||
firewall_id=firewall.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return [BoundAction(self._client.actions, _) for _ in response["actions"]]
|
180
plugins/module_utils/vendor/hcloud/firewalls/domain.py
vendored
Normal file
180
plugins/module_utils/vendor/hcloud/firewalls/domain.py
vendored
Normal file
|
@ -0,0 +1,180 @@
|
|||
try:
|
||||
from dateutil.parser import isoparse
|
||||
except ImportError:
|
||||
isoparse = None
|
||||
|
||||
from ..core.domain import BaseDomain
|
||||
|
||||
|
||||
class Firewall(BaseDomain):
|
||||
"""Firewall Domain
|
||||
|
||||
:param id: int
|
||||
ID of the Firewall
|
||||
:param name: str
|
||||
Name of the Firewall
|
||||
:param labels: dict
|
||||
User-defined labels (key-value pairs)
|
||||
:param rules: List[:class:`FirewallRule <hcloud.firewalls.domain.FirewallRule>`]
|
||||
Rules of the Firewall
|
||||
:param applied_to: List[:class:`FirewallResource <hcloud.firewalls.domain.FirewallResource>`]
|
||||
Resources currently using the Firewall
|
||||
:param created: datetime
|
||||
Point in time when the image was created
|
||||
"""
|
||||
|
||||
__slots__ = ("id", "name", "labels", "rules", "applied_to", "created")
|
||||
|
||||
def __init__(
|
||||
self, id=None, name=None, labels=None, rules=None, applied_to=None, created=None
|
||||
):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.rules = rules
|
||||
self.applied_to = applied_to
|
||||
self.labels = labels
|
||||
self.created = isoparse(created) if created else None
|
||||
|
||||
|
||||
class FirewallRule:
|
||||
"""Firewall Rule Domain
|
||||
|
||||
:param direction: str
|
||||
The Firewall which was created
|
||||
:param port: str
|
||||
Port to which traffic will be allowed, only applicable for protocols TCP and UDP, specify port ranges by using
|
||||
- as a indicator, Sample: 80-85 means all ports between 80 & 85 (80, 82, 83, 84, 85)
|
||||
:param protocol: str
|
||||
Select traffic direction on which rule should be applied. Use source_ips for direction in and destination_ips for direction out.
|
||||
:param source_ips: List[str]
|
||||
List of permitted IPv4/IPv6 addresses in CIDR notation. Use 0.0.0.0/0 to allow all IPv4 addresses and ::/0 to allow all IPv6 addresses. You can specify 100 CIDRs at most.
|
||||
:param destination_ips: List[str]
|
||||
List of permitted IPv4/IPv6 addresses in CIDR notation. Use 0.0.0.0/0 to allow all IPv4 addresses and ::/0 to allow all IPv6 addresses. You can specify 100 CIDRs at most.
|
||||
:param description: str
|
||||
Short description of the firewall rule
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"direction",
|
||||
"port",
|
||||
"protocol",
|
||||
"source_ips",
|
||||
"destination_ips",
|
||||
"description",
|
||||
)
|
||||
|
||||
DIRECTION_IN = "in"
|
||||
"""Firewall Rule Direction In"""
|
||||
DIRECTION_OUT = "out"
|
||||
"""Firewall Rule Direction Out"""
|
||||
|
||||
PROTOCOL_UDP = "udp"
|
||||
"""Firewall Rule Protocol UDP"""
|
||||
PROTOCOL_ICMP = "icmp"
|
||||
"""Firewall Rule Protocol ICMP"""
|
||||
PROTOCOL_TCP = "tcp"
|
||||
"""Firewall Rule Protocol TCP"""
|
||||
PROTOCOL_ESP = "esp"
|
||||
"""Firewall Rule Protocol ESP"""
|
||||
PROTOCOL_GRE = "gre"
|
||||
"""Firewall Rule Protocol GRE"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
direction, # type: str
|
||||
protocol, # type: str
|
||||
source_ips, # type: List[str]
|
||||
port=None, # type: Optional[str]
|
||||
destination_ips=None, # type: Optional[List[str]]
|
||||
description=None, # type: Optional[str]
|
||||
):
|
||||
self.direction = direction
|
||||
self.port = port
|
||||
self.protocol = protocol
|
||||
self.source_ips = source_ips
|
||||
self.destination_ips = destination_ips or []
|
||||
self.description = description
|
||||
|
||||
def to_payload(self):
|
||||
payload = {
|
||||
"direction": self.direction,
|
||||
"protocol": self.protocol,
|
||||
"source_ips": self.source_ips,
|
||||
}
|
||||
if len(self.destination_ips) > 0:
|
||||
payload.update({"destination_ips": self.destination_ips})
|
||||
if self.port is not None:
|
||||
payload.update({"port": self.port})
|
||||
if self.description is not None:
|
||||
payload.update({"description": self.description})
|
||||
return payload
|
||||
|
||||
|
||||
class FirewallResource:
|
||||
"""Firewall Used By Domain
|
||||
|
||||
:param type: str
|
||||
Type of resource referenced
|
||||
:param server: Optional[Server]
|
||||
Server the Firewall is applied to
|
||||
:param label_selector: Optional[FirewallResourceLabelSelector]
|
||||
Label Selector for Servers the Firewall should be applied to
|
||||
"""
|
||||
|
||||
__slots__ = ("type", "server", "label_selector")
|
||||
|
||||
TYPE_SERVER = "server"
|
||||
"""Firewall Used By Type Server"""
|
||||
TYPE_LABEL_SELECTOR = "label_selector"
|
||||
"""Firewall Used By Type label_selector"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
type, # type: str
|
||||
server=None, # type: Optional[Server]
|
||||
label_selector=None, # type: Optional[FirewallResourceLabelSelector]
|
||||
):
|
||||
self.type = type
|
||||
self.server = server
|
||||
self.label_selector = label_selector
|
||||
|
||||
def to_payload(self):
|
||||
payload = {"type": self.type}
|
||||
if self.server is not None:
|
||||
payload.update({"server": {"id": self.server.id}})
|
||||
|
||||
if self.label_selector is not None:
|
||||
payload.update(
|
||||
{"label_selector": {"selector": self.label_selector.selector}}
|
||||
)
|
||||
return payload
|
||||
|
||||
|
||||
class FirewallResourceLabelSelector(BaseDomain):
|
||||
"""FirewallResourceLabelSelector Domain
|
||||
|
||||
:param selector: str Target label selector
|
||||
"""
|
||||
|
||||
def __init__(self, selector=None):
|
||||
self.selector = selector
|
||||
|
||||
|
||||
class CreateFirewallResponse(BaseDomain):
|
||||
"""Create Firewall Response Domain
|
||||
|
||||
:param firewall: :class:`BoundFirewall <hcloud.firewalls.client.BoundFirewall>`
|
||||
The Firewall which was created
|
||||
:param actions: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
The Action which shows the progress of the Firewall Creation
|
||||
"""
|
||||
|
||||
__slots__ = ("firewall", "actions")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
firewall, # type: BoundFirewall
|
||||
actions, # type: BoundAction
|
||||
):
|
||||
self.firewall = firewall
|
||||
self.actions = actions
|
0
plugins/module_utils/vendor/hcloud/floating_ips/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/floating_ips/__init__.py
vendored
Normal file
422
plugins/module_utils/vendor/hcloud/floating_ips/client.py
vendored
Normal file
422
plugins/module_utils/vendor/hcloud/floating_ips/client.py
vendored
Normal file
|
@ -0,0 +1,422 @@
|
|||
from ..actions.client import BoundAction
|
||||
from ..core.client import BoundModelBase, ClientEntityBase, GetEntityByNameMixin
|
||||
from ..core.domain import add_meta_to_result
|
||||
from ..locations.client import BoundLocation
|
||||
from .domain import CreateFloatingIPResponse, FloatingIP
|
||||
|
||||
|
||||
class BoundFloatingIP(BoundModelBase):
|
||||
model = FloatingIP
|
||||
|
||||
def __init__(self, client, data, complete=True):
|
||||
from ..servers.client import BoundServer
|
||||
|
||||
server = data.get("server")
|
||||
if server is not None:
|
||||
data["server"] = BoundServer(
|
||||
client._client.servers, {"id": server}, complete=False
|
||||
)
|
||||
|
||||
home_location = data.get("home_location")
|
||||
if home_location is not None:
|
||||
data["home_location"] = BoundLocation(
|
||||
client._client.locations, home_location
|
||||
)
|
||||
|
||||
super().__init__(client, data, complete)
|
||||
|
||||
def get_actions_list(self, status=None, sort=None, page=None, per_page=None):
|
||||
# type: (Optional[List[str]], Optional[List[str]], Optional[int], Optional[int]) -> PageResult[BoundAction, Meta]
|
||||
"""Returns all action objects for a Floating IP.
|
||||
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
return self._client.get_actions_list(self, status, sort, page, per_page)
|
||||
|
||||
def get_actions(self, status=None, sort=None):
|
||||
# type: (Optional[List[str]], Optional[List[str]]) -> List[BoundAction]
|
||||
"""Returns all action objects for a Floating IP.
|
||||
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
return self._client.get_actions(self, status, sort)
|
||||
|
||||
def update(self, description=None, labels=None, name=None):
|
||||
# type: (Optional[str], Optional[Dict[str, str]], Optional[str]) -> BoundFloatingIP
|
||||
"""Updates the description or labels of a Floating IP.
|
||||
|
||||
:param description: str (optional)
|
||||
New Description to set
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:param name: str (optional)
|
||||
New Name to set
|
||||
:return: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>`
|
||||
"""
|
||||
return self._client.update(self, description, labels, name)
|
||||
|
||||
def delete(self):
|
||||
# type: () -> bool
|
||||
"""Deletes a Floating IP. If it is currently assigned to a server it will automatically get unassigned.
|
||||
|
||||
:return: boolean
|
||||
"""
|
||||
return self._client.delete(self)
|
||||
|
||||
def change_protection(self, delete=None):
|
||||
# type: (Optional[bool]) -> BoundAction
|
||||
"""Changes the protection configuration of the Floating IP.
|
||||
|
||||
:param delete: boolean
|
||||
If true, prevents the Floating IP from being deleted
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.change_protection(self, delete)
|
||||
|
||||
def assign(self, server):
|
||||
# type: (Server) -> BoundAction
|
||||
"""Assigns a Floating IP to a server.
|
||||
|
||||
:param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
|
||||
Server the Floating IP shall be assigned to
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.assign(self, server)
|
||||
|
||||
def unassign(self):
|
||||
# type: () -> BoundAction
|
||||
"""Unassigns a Floating IP, resulting in it being unreachable. You may assign it to a server again at a later time.
|
||||
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.unassign(self)
|
||||
|
||||
def change_dns_ptr(self, ip, dns_ptr):
|
||||
# type: (str, str) -> BoundAction
|
||||
"""Changes the hostname that will appear when getting the hostname belonging to this Floating IP.
|
||||
|
||||
:param ip: str
|
||||
The IP address for which to set the reverse DNS entry
|
||||
:param dns_ptr: str
|
||||
Hostname to set as a reverse DNS PTR entry, will reset to original default value if `None`
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.change_dns_ptr(self, ip, dns_ptr)
|
||||
|
||||
|
||||
class FloatingIPsClient(ClientEntityBase, GetEntityByNameMixin):
|
||||
results_list_attribute_name = "floating_ips"
|
||||
|
||||
def get_actions_list(
|
||||
self,
|
||||
floating_ip, # type: FloatingIP
|
||||
status=None, # type: Optional[List[str]]
|
||||
sort=None, # type: Optional[List[str]]
|
||||
page=None, # type: Optional[int]
|
||||
per_page=None, # type: Optional[int]
|
||||
):
|
||||
# type: (...) -> PageResults[List[BoundAction], Meta]
|
||||
"""Returns all action objects for a Floating IP.
|
||||
|
||||
:param floating_ip: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>` or :class:`FloatingIP <hcloud.floating_ips.domain.FloatingIP>`
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
if status is not None:
|
||||
params["status"] = status
|
||||
if sort is not None:
|
||||
params["sort"] = sort
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
response = self._client.request(
|
||||
url="/floating_ips/{floating_ip_id}/actions".format(
|
||||
floating_ip_id=floating_ip.id
|
||||
),
|
||||
method="GET",
|
||||
params=params,
|
||||
)
|
||||
actions = [
|
||||
BoundAction(self._client.actions, action_data)
|
||||
for action_data in response["actions"]
|
||||
]
|
||||
return add_meta_to_result(actions, response, "actions")
|
||||
|
||||
def get_actions(
|
||||
self,
|
||||
floating_ip, # type: FloatingIP
|
||||
status=None, # type: Optional[List[str]]
|
||||
sort=None, # type: Optional[List[str]]
|
||||
):
|
||||
# type: (...) -> List[BoundAction]
|
||||
"""Returns all action objects for a Floating IP.
|
||||
|
||||
:param floating_ip: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>` or :class:`FloatingIP <hcloud.floating_ips.domain.FloatingIP>`
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
return super().get_actions(floating_ip, status=status, sort=sort)
|
||||
|
||||
def get_by_id(self, id):
|
||||
# type: (int) -> BoundFloatingIP
|
||||
"""Returns a specific Floating IP object.
|
||||
|
||||
:param id: int
|
||||
:return: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>`
|
||||
"""
|
||||
response = self._client.request(url=f"/floating_ips/{id}", method="GET")
|
||||
return BoundFloatingIP(self, response["floating_ip"])
|
||||
|
||||
def get_list(
|
||||
self,
|
||||
label_selector=None, # type: Optional[str]
|
||||
page=None, # type: Optional[int]
|
||||
per_page=None, # type: Optional[int]
|
||||
name=None, # type: Optional[str]
|
||||
):
|
||||
# type: (...) -> PageResults[List[BoundFloatingIP]]
|
||||
"""Get a list of floating ips from this account
|
||||
|
||||
:param label_selector: str (optional)
|
||||
Can be used to filter Floating IPs by labels. The response will only contain Floating IPs matching the label selector.able values.
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:param name: str (optional)
|
||||
Can be used to filter networks by their name.
|
||||
:return: (List[:class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
|
||||
if label_selector is not None:
|
||||
params["label_selector"] = label_selector
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
if name is not None:
|
||||
params["name"] = name
|
||||
|
||||
response = self._client.request(
|
||||
url="/floating_ips", method="GET", params=params
|
||||
)
|
||||
floating_ips = [
|
||||
BoundFloatingIP(self, floating_ip_data)
|
||||
for floating_ip_data in response["floating_ips"]
|
||||
]
|
||||
|
||||
return self._add_meta_to_result(floating_ips, response)
|
||||
|
||||
def get_all(self, label_selector=None, name=None):
|
||||
# type: (Optional[str], Optional[str]) -> List[BoundFloatingIP]
|
||||
"""Get all floating ips from this account
|
||||
|
||||
:param label_selector: str (optional)
|
||||
Can be used to filter Floating IPs by labels. The response will only contain Floating IPs matching the label selector.able values.
|
||||
:param name: str (optional)
|
||||
Can be used to filter networks by their name.
|
||||
:return: List[:class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>`]
|
||||
"""
|
||||
return super().get_all(label_selector=label_selector, name=name)
|
||||
|
||||
def get_by_name(self, name):
|
||||
# type: (str) -> BoundFloatingIP
|
||||
"""Get Floating IP by name
|
||||
|
||||
:param name: str
|
||||
Used to get Floating IP by name.
|
||||
:return: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>`
|
||||
"""
|
||||
return super().get_by_name(name)
|
||||
|
||||
def create(
|
||||
self,
|
||||
type, # type: str
|
||||
description=None, # type: Optional[str]
|
||||
labels=None, # type: Optional[str]
|
||||
home_location=None, # type: Optional[Location]
|
||||
server=None, # type: Optional[Server]
|
||||
name=None, # type: Optional[str]
|
||||
):
|
||||
# type: (...) -> CreateFloatingIPResponse
|
||||
"""Creates a new Floating IP assigned to a server.
|
||||
|
||||
:param type: str
|
||||
Floating IP type Choices: ipv4, ipv6
|
||||
:param description: str (optional)
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:param home_location: :class:`BoundLocation <hcloud.locations.client.BoundLocation>` or :class:`Location <hcloud.locations.domain.Location>` (
|
||||
Home location (routing is optimized for that location). Only optional if server argument is passed.
|
||||
:param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
|
||||
Server to assign the Floating IP to
|
||||
:param name: str (optional)
|
||||
:return: :class:`CreateFloatingIPResponse <hcloud.floating_ips.domain.CreateFloatingIPResponse>`
|
||||
"""
|
||||
|
||||
data = {"type": type}
|
||||
if description is not None:
|
||||
data["description"] = description
|
||||
if labels is not None:
|
||||
data["labels"] = labels
|
||||
if home_location is not None:
|
||||
data["home_location"] = home_location.id_or_name
|
||||
if server is not None:
|
||||
data["server"] = server.id
|
||||
if name is not None:
|
||||
data["name"] = name
|
||||
|
||||
response = self._client.request(url="/floating_ips", json=data, method="POST")
|
||||
|
||||
action = None
|
||||
if response.get("action") is not None:
|
||||
action = BoundAction(self._client.actions, response["action"])
|
||||
|
||||
result = CreateFloatingIPResponse(
|
||||
floating_ip=BoundFloatingIP(self, response["floating_ip"]), action=action
|
||||
)
|
||||
return result
|
||||
|
||||
def update(self, floating_ip, description=None, labels=None, name=None):
|
||||
# type: (FloatingIP, Optional[str], Optional[Dict[str, str]], Optional[str]) -> BoundFloatingIP
|
||||
"""Updates the description or labels of a Floating IP.
|
||||
|
||||
:param floating_ip: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>` or :class:`FloatingIP <hcloud.floating_ips.domain.FloatingIP>`
|
||||
:param description: str (optional)
|
||||
New Description to set
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:param name: str (optional)
|
||||
New name to set
|
||||
:return: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>`
|
||||
"""
|
||||
data = {}
|
||||
if description is not None:
|
||||
data["description"] = description
|
||||
if labels is not None:
|
||||
data["labels"] = labels
|
||||
if name is not None:
|
||||
data["name"] = name
|
||||
|
||||
response = self._client.request(
|
||||
url=f"/floating_ips/{floating_ip.id}",
|
||||
method="PUT",
|
||||
json=data,
|
||||
)
|
||||
return BoundFloatingIP(self, response["floating_ip"])
|
||||
|
||||
def delete(self, floating_ip):
|
||||
# type: (FloatingIP) -> bool
|
||||
"""Deletes a Floating IP. If it is currently assigned to a server it will automatically get unassigned.
|
||||
|
||||
:param floating_ip: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>` or :class:`FloatingIP <hcloud.floating_ips.domain.FloatingIP>`
|
||||
:return: boolean
|
||||
"""
|
||||
self._client.request(
|
||||
url=f"/floating_ips/{floating_ip.id}",
|
||||
method="DELETE",
|
||||
)
|
||||
# Return always true, because the API does not return an action for it. When an error occurs a HcloudAPIException will be raised
|
||||
return True
|
||||
|
||||
def change_protection(self, floating_ip, delete=None):
|
||||
# type: (FloatingIP, Optional[bool]) -> BoundAction
|
||||
"""Changes the protection configuration of the Floating IP.
|
||||
|
||||
:param floating_ip: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>` or :class:`FloatingIP <hcloud.floating_ips.domain.FloatingIP>`
|
||||
:param delete: boolean
|
||||
If true, prevents the Floating IP from being deleted
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {}
|
||||
if delete is not None:
|
||||
data.update({"delete": delete})
|
||||
|
||||
response = self._client.request(
|
||||
url="/floating_ips/{floating_ip_id}/actions/change_protection".format(
|
||||
floating_ip_id=floating_ip.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def assign(self, floating_ip, server):
|
||||
# type: (FloatingIP, Server) -> BoundAction
|
||||
"""Assigns a Floating IP to a server.
|
||||
|
||||
:param floating_ip: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>` or :class:`FloatingIP <hcloud.floating_ips.domain.FloatingIP>`
|
||||
:param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
|
||||
Server the Floating IP shall be assigned to
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
response = self._client.request(
|
||||
url="/floating_ips/{floating_ip_id}/actions/assign".format(
|
||||
floating_ip_id=floating_ip.id
|
||||
),
|
||||
method="POST",
|
||||
json={"server": server.id},
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def unassign(self, floating_ip):
|
||||
# type: (FloatingIP) -> BoundAction
|
||||
"""Unassigns a Floating IP, resulting in it being unreachable. You may assign it to a server again at a later time.
|
||||
|
||||
:param floating_ip: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>` or :class:`FloatingIP <hcloud.floating_ips.domain.FloatingIP>`
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
response = self._client.request(
|
||||
url="/floating_ips/{floating_ip_id}/actions/unassign".format(
|
||||
floating_ip_id=floating_ip.id
|
||||
),
|
||||
method="POST",
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def change_dns_ptr(self, floating_ip, ip, dns_ptr):
|
||||
# type: (FloatingIP, str, str) -> BoundAction
|
||||
"""Changes the hostname that will appear when getting the hostname belonging to this Floating IP.
|
||||
|
||||
:param floating_ip: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>` or :class:`FloatingIP <hcloud.floating_ips.domain.FloatingIP>`
|
||||
:param ip: str
|
||||
The IP address for which to set the reverse DNS entry
|
||||
:param dns_ptr: str
|
||||
Hostname to set as a reverse DNS PTR entry, will reset to original default value if `None`
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
response = self._client.request(
|
||||
url="/floating_ips/{floating_ip_id}/actions/change_dns_ptr".format(
|
||||
floating_ip_id=floating_ip.id
|
||||
),
|
||||
method="POST",
|
||||
json={"ip": ip, "dns_ptr": dns_ptr},
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
99
plugins/module_utils/vendor/hcloud/floating_ips/domain.py
vendored
Normal file
99
plugins/module_utils/vendor/hcloud/floating_ips/domain.py
vendored
Normal file
|
@ -0,0 +1,99 @@
|
|||
try:
|
||||
from dateutil.parser import isoparse
|
||||
except ImportError:
|
||||
isoparse = None
|
||||
|
||||
from ..core.domain import BaseDomain
|
||||
|
||||
|
||||
class FloatingIP(BaseDomain):
|
||||
"""Floating IP Domain
|
||||
|
||||
:param id: int
|
||||
ID of the Floating IP
|
||||
:param description: str, None
|
||||
Description of the Floating IP
|
||||
:param ip: str
|
||||
IP address of the Floating IP
|
||||
:param type: str
|
||||
Type of Floating IP. Choices: `ipv4`, `ipv6`
|
||||
:param server: :class:`BoundServer <hcloud.servers.client.BoundServer>`, None
|
||||
Server the Floating IP is assigned to, None if it is not assigned at all
|
||||
:param dns_ptr: List[Dict]
|
||||
Array of reverse DNS entries
|
||||
:param home_location: :class:`BoundLocation <hcloud.locations.client.BoundLocation>`
|
||||
Location the Floating IP was created in. Routing is optimized for this location.
|
||||
:param blocked: boolean
|
||||
Whether the IP is blocked
|
||||
:param protection: dict
|
||||
Protection configuration for the Floating IP
|
||||
:param labels: dict
|
||||
User-defined labels (key-value pairs)
|
||||
:param created: datetime
|
||||
Point in time when the Floating IP was created
|
||||
:param name: str
|
||||
Name of the Floating IP
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"id",
|
||||
"type",
|
||||
"description",
|
||||
"ip",
|
||||
"server",
|
||||
"dns_ptr",
|
||||
"home_location",
|
||||
"blocked",
|
||||
"protection",
|
||||
"labels",
|
||||
"name",
|
||||
"created",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id=None,
|
||||
type=None,
|
||||
description=None,
|
||||
ip=None,
|
||||
server=None,
|
||||
dns_ptr=None,
|
||||
home_location=None,
|
||||
blocked=None,
|
||||
protection=None,
|
||||
labels=None,
|
||||
created=None,
|
||||
name=None,
|
||||
):
|
||||
self.id = id
|
||||
self.type = type
|
||||
self.description = description
|
||||
self.ip = ip
|
||||
self.server = server
|
||||
self.dns_ptr = dns_ptr
|
||||
self.home_location = home_location
|
||||
self.blocked = blocked
|
||||
self.protection = protection
|
||||
self.labels = labels
|
||||
self.created = isoparse(created) if created else None
|
||||
self.name = name
|
||||
|
||||
|
||||
class CreateFloatingIPResponse(BaseDomain):
|
||||
"""Create Floating IP Response Domain
|
||||
|
||||
:param floating_ip: :class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>`
|
||||
The Floating IP which was created
|
||||
:param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
The Action which shows the progress of the Floating IP Creation
|
||||
"""
|
||||
|
||||
__slots__ = ("floating_ip", "action")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
floating_ip, # type: BoundFloatingIP
|
||||
action, # type: BoundAction
|
||||
):
|
||||
self.floating_ip = floating_ip
|
||||
self.action = action
|
225
plugins/module_utils/vendor/hcloud/hcloud.py
vendored
Normal file
225
plugins/module_utils/vendor/hcloud/hcloud.py
vendored
Normal file
|
@ -0,0 +1,225 @@
|
|||
import time
|
||||
from typing import Optional, Union
|
||||
|
||||
try:
|
||||
import requests
|
||||
except ImportError:
|
||||
requests = None
|
||||
|
||||
from ._version import VERSION
|
||||
from ._exceptions import APIException
|
||||
from .actions.client import ActionsClient
|
||||
from .certificates.client import CertificatesClient
|
||||
from .datacenters.client import DatacentersClient
|
||||
from .firewalls.client import FirewallsClient
|
||||
from .floating_ips.client import FloatingIPsClient
|
||||
from .images.client import ImagesClient
|
||||
from .isos.client import IsosClient
|
||||
from .load_balancer_types.client import LoadBalancerTypesClient
|
||||
from .load_balancers.client import LoadBalancersClient
|
||||
from .locations.client import LocationsClient
|
||||
from .networks.client import NetworksClient
|
||||
from .placement_groups.client import PlacementGroupsClient
|
||||
from .primary_ips.client import PrimaryIPsClient
|
||||
from .server_types.client import ServerTypesClient
|
||||
from .servers.client import ServersClient
|
||||
from .ssh_keys.client import SSHKeysClient
|
||||
from .volumes.client import VolumesClient
|
||||
|
||||
|
||||
class Client:
|
||||
"""Base Client for accessing the Hetzner Cloud API"""
|
||||
|
||||
_version = VERSION
|
||||
_retry_wait_time = 0.5
|
||||
__user_agent_prefix = "hcloud-python"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
token: str,
|
||||
api_endpoint: str = "https://api.hetzner.cloud/v1",
|
||||
application_name: Optional[str] = None,
|
||||
application_version: Optional[str] = None,
|
||||
poll_interval: int = 1,
|
||||
):
|
||||
"""Create an new Client instance
|
||||
|
||||
:param token: Hetzner Cloud API token
|
||||
:param api_endpoint: Hetzner Cloud API endpoint
|
||||
:param application_name: Your application name
|
||||
:param application_version: Your application _version
|
||||
:param poll_interval: Interval for polling information from Hetzner Cloud API in seconds
|
||||
"""
|
||||
self.token = token
|
||||
self._api_endpoint = api_endpoint
|
||||
self._application_name = application_name
|
||||
self._application_version = application_version
|
||||
self._requests_session = requests.Session()
|
||||
self.poll_interval = poll_interval
|
||||
|
||||
self.datacenters = DatacentersClient(self)
|
||||
"""DatacentersClient Instance
|
||||
|
||||
:type: :class:`DatacentersClient <hcloud.datacenters.client.DatacentersClient>`
|
||||
"""
|
||||
self.locations = LocationsClient(self)
|
||||
"""LocationsClient Instance
|
||||
|
||||
:type: :class:`LocationsClient <hcloud.locations.client.LocationsClient>`
|
||||
"""
|
||||
self.servers = ServersClient(self)
|
||||
"""ServersClient Instance
|
||||
|
||||
:type: :class:`ServersClient <hcloud.servers.client.ServersClient>`
|
||||
"""
|
||||
self.server_types = ServerTypesClient(self)
|
||||
"""ServerTypesClient Instance
|
||||
|
||||
:type: :class:`ServerTypesClient <hcloud.server_types.client.ServerTypesClient>`
|
||||
"""
|
||||
self.volumes = VolumesClient(self)
|
||||
"""VolumesClient Instance
|
||||
|
||||
:type: :class:`VolumesClient <hcloud.volumes.client.VolumesClient>`
|
||||
"""
|
||||
self.actions = ActionsClient(self)
|
||||
"""ActionsClient Instance
|
||||
|
||||
:type: :class:`ActionsClient <hcloud.actions.client.ActionsClient>`
|
||||
"""
|
||||
self.images = ImagesClient(self)
|
||||
"""ImagesClient Instance
|
||||
|
||||
:type: :class:`ImagesClient <hcloud.images.client.ImagesClient>`
|
||||
"""
|
||||
self.isos = IsosClient(self)
|
||||
"""ImagesClient Instance
|
||||
|
||||
:type: :class:`IsosClient <hcloud.isos.client.IsosClient>`
|
||||
"""
|
||||
self.ssh_keys = SSHKeysClient(self)
|
||||
"""SSHKeysClient Instance
|
||||
|
||||
:type: :class:`SSHKeysClient <hcloud.ssh_keys.client.SSHKeysClient>`
|
||||
"""
|
||||
self.floating_ips = FloatingIPsClient(self)
|
||||
"""FloatingIPsClient Instance
|
||||
|
||||
:type: :class:`FloatingIPsClient <hcloud.floating_ips.client.FloatingIPsClient>`
|
||||
"""
|
||||
self.primary_ips = PrimaryIPsClient(self)
|
||||
"""PrimaryIPsClient Instance
|
||||
|
||||
:type: :class:`PrimaryIPsClient <hcloud.primary_ips.client.PrimaryIPsClient>`
|
||||
"""
|
||||
self.networks = NetworksClient(self)
|
||||
"""NetworksClient Instance
|
||||
|
||||
:type: :class:`NetworksClient <hcloud.networks.client.NetworksClient>`
|
||||
"""
|
||||
self.certificates = CertificatesClient(self)
|
||||
"""CertificatesClient Instance
|
||||
|
||||
:type: :class:`CertificatesClient <hcloud.certificates.client.CertificatesClient>`
|
||||
"""
|
||||
|
||||
self.load_balancers = LoadBalancersClient(self)
|
||||
"""LoadBalancersClient Instance
|
||||
|
||||
:type: :class:`LoadBalancersClient <hcloud.load_balancers.client.LoadBalancersClient>`
|
||||
"""
|
||||
|
||||
self.load_balancer_types = LoadBalancerTypesClient(self)
|
||||
"""LoadBalancerTypesClient Instance
|
||||
|
||||
:type: :class:`LoadBalancerTypesClient <hcloud.load_balancer_types.client.LoadBalancerTypesClient>`
|
||||
"""
|
||||
|
||||
self.firewalls = FirewallsClient(self)
|
||||
"""FirewallsClient Instance
|
||||
|
||||
:type: :class:`FirewallsClient <hcloud.firewalls.client.FirewallsClient>`
|
||||
"""
|
||||
|
||||
self.placement_groups = PlacementGroupsClient(self)
|
||||
"""PlacementGroupsClient Instance
|
||||
|
||||
:type: :class:`PlacementGroupsClient <hcloud.placement_groups.client.PlacementGroupsClient>`
|
||||
"""
|
||||
|
||||
def _get_user_agent(self) -> str:
|
||||
"""Get the user agent of the hcloud-python instance with the user application name (if specified)
|
||||
|
||||
:return: The user agent of this hcloud-python instance
|
||||
"""
|
||||
user_agents = []
|
||||
for name, version in [
|
||||
(self._application_name, self._application_version),
|
||||
(self.__user_agent_prefix, self._version),
|
||||
]:
|
||||
if name is not None:
|
||||
user_agents.append(name if version is None else f"{name}/{version}")
|
||||
|
||||
return " ".join(user_agents)
|
||||
|
||||
def _get_headers(self) -> dict:
|
||||
headers = {
|
||||
"User-Agent": self._get_user_agent(),
|
||||
"Authorization": f"Bearer {self.token}",
|
||||
}
|
||||
return headers
|
||||
|
||||
def _raise_exception_from_response(self, response):
|
||||
raise APIException(
|
||||
code=response.status_code,
|
||||
message=response.reason,
|
||||
details={"content": response.content},
|
||||
)
|
||||
|
||||
def _raise_exception_from_content(self, content: dict):
|
||||
raise APIException(
|
||||
code=content["error"]["code"],
|
||||
message=content["error"]["message"],
|
||||
details=content["error"]["details"],
|
||||
)
|
||||
|
||||
def request(
|
||||
self,
|
||||
method: str,
|
||||
url: str,
|
||||
tries: int = 1,
|
||||
**kwargs,
|
||||
) -> Union[bytes, dict]:
|
||||
"""Perform a request to the Hetzner Cloud API, wrapper around requests.request
|
||||
|
||||
:param method: HTTP Method to perform the Request
|
||||
:param url: URL of the Endpoint
|
||||
:param tries: Tries of the request (used internally, should not be set by the user)
|
||||
:return: Response
|
||||
"""
|
||||
response = self._requests_session.request(
|
||||
method=method,
|
||||
url=self._api_endpoint + url,
|
||||
headers=self._get_headers(),
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
content = response.content
|
||||
try:
|
||||
if len(content) > 0:
|
||||
content = response.json()
|
||||
except (TypeError, ValueError):
|
||||
self._raise_exception_from_response(response)
|
||||
|
||||
if not response.ok:
|
||||
if content:
|
||||
if content["error"]["code"] == "rate_limit_exceeded" and tries < 5:
|
||||
time.sleep(tries * self._retry_wait_time)
|
||||
tries = tries + 1
|
||||
return self.request(method, url, tries, **kwargs)
|
||||
else:
|
||||
self._raise_exception_from_content(content)
|
||||
else:
|
||||
self._raise_exception_from_response(response)
|
||||
|
||||
return content
|
0
plugins/module_utils/vendor/hcloud/helpers/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/helpers/__init__.py
vendored
Normal file
39
plugins/module_utils/vendor/hcloud/helpers/labels.py
vendored
Normal file
39
plugins/module_utils/vendor/hcloud/helpers/labels.py
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
import re
|
||||
from typing import Dict
|
||||
|
||||
|
||||
class LabelValidator:
|
||||
KEY_REGEX = re.compile(
|
||||
r"^([a-z0-9A-Z]((?:[\-_.]|[a-z0-9A-Z]){0,253}[a-z0-9A-Z])?/)?[a-z0-9A-Z]((?:[\-_.]|[a-z0-9A-Z]|){0,61}[a-z0-9A-Z])?$"
|
||||
)
|
||||
VALUE_REGEX = re.compile(
|
||||
r"^(([a-z0-9A-Z](?:[\-_.]|[a-z0-9A-Z]){0,61})?[a-z0-9A-Z]$|$)"
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def validate(labels: Dict[str, str]) -> bool:
|
||||
"""Validates Labels. If you want to know which key/value pair of the dict is not correctly formatted
|
||||
use :func:`~hcloud.helpers.labels.validate_verbose`.
|
||||
|
||||
:return: bool
|
||||
"""
|
||||
for k, v in labels.items():
|
||||
if LabelValidator.KEY_REGEX.match(k) is None:
|
||||
return False
|
||||
if LabelValidator.VALUE_REGEX.match(v) is None:
|
||||
return False
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def validate_verbose(labels: Dict[str, str]) -> (bool, str):
|
||||
"""Validates Labels and returns the corresponding error message if something is wrong. Returns True, <empty string>
|
||||
if everything is fine.
|
||||
|
||||
:return: bool, str
|
||||
"""
|
||||
for k, v in labels.items():
|
||||
if LabelValidator.KEY_REGEX.match(k) is None:
|
||||
return False, f"label key {k} is not correctly formatted"
|
||||
if LabelValidator.VALUE_REGEX.match(v) is None:
|
||||
return False, f"label value {v} (key: {k}) is not correctly formatted"
|
||||
return True, ""
|
0
plugins/module_utils/vendor/hcloud/images/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/images/__init__.py
vendored
Normal file
354
plugins/module_utils/vendor/hcloud/images/client.py
vendored
Normal file
354
plugins/module_utils/vendor/hcloud/images/client.py
vendored
Normal file
|
@ -0,0 +1,354 @@
|
|||
from ..actions.client import BoundAction
|
||||
from ..core.client import BoundModelBase, ClientEntityBase, GetEntityByNameMixin
|
||||
from ..core.domain import add_meta_to_result
|
||||
from .domain import Image
|
||||
|
||||
|
||||
class BoundImage(BoundModelBase):
|
||||
model = Image
|
||||
|
||||
def __init__(self, client, data):
|
||||
from ..servers.client import BoundServer
|
||||
|
||||
created_from = data.get("created_from")
|
||||
if created_from is not None:
|
||||
data["created_from"] = BoundServer(
|
||||
client._client.servers, created_from, complete=False
|
||||
)
|
||||
bound_to = data.get("bound_to")
|
||||
if bound_to is not None:
|
||||
data["bound_to"] = BoundServer(
|
||||
client._client.servers, {"id": bound_to}, complete=False
|
||||
)
|
||||
|
||||
super().__init__(client, data)
|
||||
|
||||
def get_actions_list(self, sort=None, page=None, per_page=None, status=None):
|
||||
# type: (Optional[List[str]], Optional[int], Optional[int], Optional[List[str]]) -> PageResult[BoundAction, Meta]
|
||||
"""Returns a list of action objects for the image.
|
||||
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
return self._client.get_actions_list(
|
||||
self, sort=sort, page=page, per_page=per_page, status=status
|
||||
)
|
||||
|
||||
def get_actions(self, sort=None, status=None):
|
||||
# type: (Optional[List[str]], Optional[List[str]]) -> List[BoundAction]
|
||||
"""Returns all action objects for the image.
|
||||
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
return self._client.get_actions(self, status=status, sort=sort)
|
||||
|
||||
def update(self, description=None, type=None, labels=None):
|
||||
# type: (Optional[str], Optional[str], Optional[Dict[str, str]]) -> BoundImage
|
||||
"""Updates the Image. You may change the description, convert a Backup image to a Snapshot Image or change the image labels.
|
||||
|
||||
:param description: str (optional)
|
||||
New description of Image
|
||||
:param type: str (optional)
|
||||
Destination image type to convert to
|
||||
Choices: snapshot
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:return: :class:`BoundImage <hcloud.images.client.BoundImage>`
|
||||
"""
|
||||
return self._client.update(self, description, type, labels)
|
||||
|
||||
def delete(self):
|
||||
# type: () -> bool
|
||||
"""Deletes an Image. Only images of type snapshot and backup can be deleted.
|
||||
|
||||
:return: bool
|
||||
"""
|
||||
return self._client.delete(self)
|
||||
|
||||
def change_protection(self, delete=None):
|
||||
# type: (Optional[bool]) -> BoundAction
|
||||
"""Changes the protection configuration of the image. Can only be used on snapshots.
|
||||
|
||||
:param delete: bool
|
||||
If true, prevents the snapshot from being deleted
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.change_protection(self, delete)
|
||||
|
||||
|
||||
class ImagesClient(ClientEntityBase, GetEntityByNameMixin):
|
||||
results_list_attribute_name = "images"
|
||||
|
||||
def get_actions_list(
|
||||
self,
|
||||
image, # type: Image
|
||||
sort=None, # type: Optional[List[str]]
|
||||
page=None, # type: Optional[int]
|
||||
per_page=None, # type: Optional[int]
|
||||
status=None, # type: Optional[List[str]]
|
||||
):
|
||||
# type: (...) -> PageResults[List[BoundAction], Meta]
|
||||
"""Returns a list of action objects for an image.
|
||||
|
||||
:param image: :class:`BoundImage <hcloud.images.client.BoundImage>` or :class:`Image <hcloud.images.domain.Image>`
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
if sort is not None:
|
||||
params["sort"] = sort
|
||||
if status is not None:
|
||||
params["status"] = status
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
response = self._client.request(
|
||||
url=f"/images/{image.id}/actions",
|
||||
method="GET",
|
||||
params=params,
|
||||
)
|
||||
actions = [
|
||||
BoundAction(self._client.actions, action_data)
|
||||
for action_data in response["actions"]
|
||||
]
|
||||
return add_meta_to_result(actions, response, "actions")
|
||||
|
||||
def get_actions(
|
||||
self,
|
||||
image, # type: Image
|
||||
sort=None, # type: Optional[List[str]]
|
||||
status=None, # type: Optional[List[str]]
|
||||
):
|
||||
# type: (...) -> List[BoundAction]
|
||||
"""Returns all action objects for an image.
|
||||
|
||||
:param image: :class:`BoundImage <hcloud.images.client.BoundImage>` or :class:`Image <hcloud.images.domain.Image>`
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `command` `status` `progress` `started` `finished` . You can add one of ":asc", ":desc" to modify sort order. ( ":asc" is default)
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
return super().get_actions(image, sort=sort, status=status)
|
||||
|
||||
def get_by_id(self, id):
|
||||
# type: (int) -> BoundImage
|
||||
"""Get a specific Image
|
||||
|
||||
:param id: int
|
||||
:return: :class:`BoundImage <hcloud.images.client.BoundImage
|
||||
"""
|
||||
response = self._client.request(url=f"/images/{id}", method="GET")
|
||||
return BoundImage(self, response["image"])
|
||||
|
||||
def get_list(
|
||||
self,
|
||||
name=None, # type: Optional[str]
|
||||
label_selector=None, # type: Optional[str]
|
||||
bound_to=None, # type: Optional[List[str]]
|
||||
type=None, # type: Optional[List[str]]
|
||||
architecture=None, # type: Optional[List[str]]
|
||||
sort=None, # type: Optional[List[str]]
|
||||
page=None, # type: Optional[int]
|
||||
per_page=None, # type: Optional[int]
|
||||
status=None, # type: Optional[List[str]]
|
||||
include_deprecated=None, # type: Optional[bool]
|
||||
):
|
||||
# type: (...) -> PageResults[List[BoundImage]]
|
||||
"""Get all images
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter images by their name.
|
||||
:param label_selector: str (optional)
|
||||
Can be used to filter servers by labels. The response will only contain servers matching the label selector.
|
||||
:param bound_to: List[str] (optional)
|
||||
Server Id linked to the image. Only available for images of type backup
|
||||
:param type: List[str] (optional)
|
||||
Choices: system snapshot backup
|
||||
:param architecture: List[str] (optional)
|
||||
Choices: x86 arm
|
||||
:param status: List[str] (optional)
|
||||
Can be used to filter images by their status. The response will only contain images matching the status.
|
||||
:param sort: List[str] (optional)
|
||||
Choices: id id:asc id:desc name name:asc name:desc created created:asc created:desc
|
||||
:param include_deprecated: bool (optional)
|
||||
Include deprecated images in the response. Default: False
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundImage <hcloud.images.client.BoundImage>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
if name is not None:
|
||||
params["name"] = name
|
||||
if label_selector is not None:
|
||||
params["label_selector"] = label_selector
|
||||
if bound_to is not None:
|
||||
params["bound_to"] = bound_to
|
||||
if type is not None:
|
||||
params["type"] = type
|
||||
if architecture is not None:
|
||||
params["architecture"] = architecture
|
||||
if sort is not None:
|
||||
params["sort"] = sort
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
if status is not None:
|
||||
params["status"] = per_page
|
||||
if include_deprecated is not None:
|
||||
params["include_deprecated"] = include_deprecated
|
||||
response = self._client.request(url="/images", method="GET", params=params)
|
||||
images = [BoundImage(self, image_data) for image_data in response["images"]]
|
||||
|
||||
return self._add_meta_to_result(images, response)
|
||||
|
||||
def get_all(
|
||||
self,
|
||||
name=None, # type: Optional[str]
|
||||
label_selector=None, # type: Optional[str]
|
||||
bound_to=None, # type: Optional[List[str]]
|
||||
type=None, # type: Optional[List[str]]
|
||||
architecture=None, # type: Optional[List[str]]
|
||||
sort=None, # type: Optional[List[str]]
|
||||
status=None, # type: Optional[List[str]]
|
||||
include_deprecated=None, # type: Optional[bool]
|
||||
):
|
||||
# type: (...) -> List[BoundImage]
|
||||
"""Get all images
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter images by their name.
|
||||
:param label_selector: str (optional)
|
||||
Can be used to filter servers by labels. The response will only contain servers matching the label selector.
|
||||
:param bound_to: List[str] (optional)
|
||||
Server Id linked to the image. Only available for images of type backup
|
||||
:param type: List[str] (optional)
|
||||
Choices: system snapshot backup
|
||||
:param architecture: List[str] (optional)
|
||||
Choices: x86 arm
|
||||
:param status: List[str] (optional)
|
||||
Can be used to filter images by their status. The response will only contain images matching the status.
|
||||
:param sort: List[str] (optional)
|
||||
Choices: id name created (You can add one of ":asc", ":desc" to modify sort order. ( ":asc" is default))
|
||||
:param include_deprecated: bool (optional)
|
||||
Include deprecated images in the response. Default: False
|
||||
:return: List[:class:`BoundImage <hcloud.images.client.BoundImage>`]
|
||||
"""
|
||||
return super().get_all(
|
||||
name=name,
|
||||
label_selector=label_selector,
|
||||
bound_to=bound_to,
|
||||
type=type,
|
||||
architecture=architecture,
|
||||
sort=sort,
|
||||
status=status,
|
||||
include_deprecated=include_deprecated,
|
||||
)
|
||||
|
||||
def get_by_name(self, name):
|
||||
# type: (str) -> BoundImage
|
||||
"""Get image by name
|
||||
|
||||
Deprecated: Use get_by_name_and_architecture instead.
|
||||
|
||||
:param name: str
|
||||
Used to get image by name.
|
||||
:return: :class:`BoundImage <hcloud.images.client.BoundImage>`
|
||||
"""
|
||||
return super().get_by_name(name)
|
||||
|
||||
def get_by_name_and_architecture(self, name, architecture):
|
||||
# type: (str, str) -> BoundImage
|
||||
"""Get image by name
|
||||
|
||||
:param name: str
|
||||
Used to identify the image.
|
||||
:param architecture: str
|
||||
Used to identify the image.
|
||||
:return: :class:`BoundImage <hcloud.images.client.BoundImage>`
|
||||
"""
|
||||
response = self.get_list(name=name, architecture=[architecture])
|
||||
entities = getattr(response, self.results_list_attribute_name)
|
||||
entity = entities[0] if entities else None
|
||||
return entity
|
||||
|
||||
def update(self, image, description=None, type=None, labels=None):
|
||||
# type:(Image, Optional[str], Optional[str], Optional[Dict[str, str]]) -> BoundImage
|
||||
"""Updates the Image. You may change the description, convert a Backup image to a Snapshot Image or change the image labels.
|
||||
|
||||
:param image: :class:`BoundImage <hcloud.images.client.BoundImage>` or :class:`Image <hcloud.images.domain.Image>`
|
||||
:param description: str (optional)
|
||||
New description of Image
|
||||
:param type: str (optional)
|
||||
Destination image type to convert to
|
||||
Choices: snapshot
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:return: :class:`BoundImage <hcloud.images.client.BoundImage>`
|
||||
"""
|
||||
data = {}
|
||||
if description is not None:
|
||||
data.update({"description": description})
|
||||
if type is not None:
|
||||
data.update({"type": type})
|
||||
if labels is not None:
|
||||
data.update({"labels": labels})
|
||||
response = self._client.request(
|
||||
url=f"/images/{image.id}", method="PUT", json=data
|
||||
)
|
||||
return BoundImage(self, response["image"])
|
||||
|
||||
def delete(self, image):
|
||||
# type: (Image) -> bool
|
||||
"""Deletes an Image. Only images of type snapshot and backup can be deleted.
|
||||
|
||||
:param :class:`BoundImage <hcloud.images.client.BoundImage>` or :class:`Image <hcloud.images.domain.Image>`
|
||||
:return: bool
|
||||
"""
|
||||
self._client.request(url=f"/images/{image.id}", method="DELETE")
|
||||
# Return allays true, because the API does not return an action for it. When an error occurs a APIException will be raised
|
||||
return True
|
||||
|
||||
def change_protection(self, image, delete=None):
|
||||
# type: (Image, Optional[bool]) -> BoundAction
|
||||
"""Changes the protection configuration of the image. Can only be used on snapshots.
|
||||
|
||||
:param image: :class:`BoundImage <hcloud.images.client.BoundImage>` or :class:`Image <hcloud.images.domain.Image>`
|
||||
:param delete: bool
|
||||
If true, prevents the snapshot from being deleted
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {}
|
||||
if delete is not None:
|
||||
data.update({"delete": delete})
|
||||
|
||||
response = self._client.request(
|
||||
url="/images/{image_id}/actions/change_protection".format(
|
||||
image_id=image.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
124
plugins/module_utils/vendor/hcloud/images/domain.py
vendored
Normal file
124
plugins/module_utils/vendor/hcloud/images/domain.py
vendored
Normal file
|
@ -0,0 +1,124 @@
|
|||
try:
|
||||
from dateutil.parser import isoparse
|
||||
except ImportError:
|
||||
isoparse = None
|
||||
|
||||
from ..core.domain import BaseDomain, DomainIdentityMixin
|
||||
|
||||
|
||||
class Image(BaseDomain, DomainIdentityMixin):
|
||||
"""Image Domain
|
||||
|
||||
:param id: int
|
||||
ID of the image
|
||||
:param type: str
|
||||
Type of the image Choices: `system`, `snapshot`, `backup`, `app`
|
||||
:param status: str
|
||||
Whether the image can be used or if it’s still being created Choices: `available`, `creating`
|
||||
:param name: str, None
|
||||
Unique identifier of the image. This value is only set for system images.
|
||||
:param description: str
|
||||
Description of the image
|
||||
:param image_size: number, None
|
||||
Size of the image file in our storage in GB. For snapshot images this is the value relevant for calculating costs for the image.
|
||||
:param disk_size: number
|
||||
Size of the disk contained in the image in GB.
|
||||
:param created: datetime
|
||||
Point in time when the image was created
|
||||
:param created_from: :class:`BoundServer <hcloud.servers.client.BoundServer>`, None
|
||||
Information about the server the image was created from
|
||||
:param bound_to: :class:`BoundServer <hcloud.servers.client.BoundServer>`, None
|
||||
ID of server the image is bound to. Only set for images of type `backup`.
|
||||
:param os_flavor: str
|
||||
Flavor of operating system contained in the image Choices: `ubuntu`, `centos`, `debian`, `fedora`, `unknown`
|
||||
:param os_version: str, None
|
||||
Operating system version
|
||||
:param architecture: str
|
||||
CPU Architecture that the image is compatible with. Choices: `x86`, `arm`
|
||||
:param rapid_deploy: bool
|
||||
Indicates that rapid deploy of the image is available
|
||||
:param protection: dict
|
||||
Protection configuration for the image
|
||||
:param deprecated: datetime, None
|
||||
Point in time when the image is considered to be deprecated (in ISO-8601 format)
|
||||
:param labels: Dict
|
||||
User-defined labels (key-value pairs)
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"id",
|
||||
"name",
|
||||
"type",
|
||||
"description",
|
||||
"image_size",
|
||||
"disk_size",
|
||||
"bound_to",
|
||||
"os_flavor",
|
||||
"os_version",
|
||||
"architecture",
|
||||
"rapid_deploy",
|
||||
"created_from",
|
||||
"status",
|
||||
"protection",
|
||||
"labels",
|
||||
"created",
|
||||
"deprecated",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id=None,
|
||||
name=None,
|
||||
type=None,
|
||||
created=None,
|
||||
description=None,
|
||||
image_size=None,
|
||||
disk_size=None,
|
||||
deprecated=None,
|
||||
bound_to=None,
|
||||
os_flavor=None,
|
||||
os_version=None,
|
||||
architecture=None,
|
||||
rapid_deploy=None,
|
||||
created_from=None,
|
||||
protection=None,
|
||||
labels=None,
|
||||
status=None,
|
||||
):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.type = type
|
||||
self.created = isoparse(created) if created else None
|
||||
self.description = description
|
||||
self.image_size = image_size
|
||||
self.disk_size = disk_size
|
||||
self.deprecated = isoparse(deprecated) if deprecated else None
|
||||
self.bound_to = bound_to
|
||||
self.os_flavor = os_flavor
|
||||
self.os_version = os_version
|
||||
self.architecture = architecture
|
||||
self.rapid_deploy = rapid_deploy
|
||||
self.created_from = created_from
|
||||
self.protection = protection
|
||||
self.labels = labels
|
||||
self.status = status
|
||||
|
||||
|
||||
class CreateImageResponse(BaseDomain):
|
||||
"""Create Image Response Domain
|
||||
|
||||
:param image: :class:`BoundImage <hcloud.images.client.BoundImage>`
|
||||
The Image which was created
|
||||
:param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
The Action which shows the progress of the Floating IP Creation
|
||||
"""
|
||||
|
||||
__slots__ = ("action", "image")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
action, # type: BoundAction
|
||||
image, # type: BoundImage
|
||||
):
|
||||
self.action = action
|
||||
self.image = image
|
0
plugins/module_utils/vendor/hcloud/isos/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/isos/__init__.py
vendored
Normal file
118
plugins/module_utils/vendor/hcloud/isos/client.py
vendored
Normal file
118
plugins/module_utils/vendor/hcloud/isos/client.py
vendored
Normal file
|
@ -0,0 +1,118 @@
|
|||
from warnings import warn
|
||||
|
||||
from ..core.client import BoundModelBase, ClientEntityBase, GetEntityByNameMixin
|
||||
from .domain import Iso
|
||||
|
||||
|
||||
class BoundIso(BoundModelBase):
|
||||
model = Iso
|
||||
|
||||
|
||||
class IsosClient(ClientEntityBase, GetEntityByNameMixin):
|
||||
results_list_attribute_name = "isos"
|
||||
|
||||
def get_by_id(self, id):
|
||||
# type: (int) -> BoundIso
|
||||
"""Get a specific ISO by its id
|
||||
|
||||
:param id: int
|
||||
:return: :class:`BoundIso <hcloud.isos.client.BoundIso>`
|
||||
"""
|
||||
response = self._client.request(url=f"/isos/{id}", method="GET")
|
||||
return BoundIso(self, response["iso"])
|
||||
|
||||
def get_list(
|
||||
self,
|
||||
name=None, # type: Optional[str]
|
||||
architecture=None, # type: Optional[List[str]]
|
||||
include_wildcard_architecture=None, # type: Optional[bool]
|
||||
include_architecture_wildcard=None, # type: Optional[bool]
|
||||
page=None, # type: Optional[int]
|
||||
per_page=None, # type: Optional[int]
|
||||
):
|
||||
# type: (...) -> PageResults[List[BoundIso], Meta]
|
||||
"""Get a list of ISOs
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter ISOs by their name.
|
||||
:param architecture: List[str] (optional)
|
||||
Can be used to filter ISOs by their architecture. Choices: x86 arm
|
||||
:param include_wildcard_architecture: bool (optional)
|
||||
Deprecated, please use `include_architecture_wildcard` instead.
|
||||
:param include_architecture_wildcard: bool (optional)
|
||||
Custom ISOs do not have an architecture set. You must also set this flag to True if you are filtering by
|
||||
architecture and also want custom ISOs.
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundIso <hcloud.isos.client.BoundIso>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
|
||||
if include_wildcard_architecture is not None:
|
||||
warn(
|
||||
"The `include_wildcard_architecture` argument is deprecated, please use the `include_architecture_wildcard` argument instead.",
|
||||
DeprecationWarning,
|
||||
)
|
||||
include_architecture_wildcard = include_wildcard_architecture
|
||||
|
||||
params = {}
|
||||
if name is not None:
|
||||
params["name"] = name
|
||||
if architecture is not None:
|
||||
params["architecture"] = architecture
|
||||
if include_architecture_wildcard is not None:
|
||||
params["include_architecture_wildcard"] = include_architecture_wildcard
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
|
||||
response = self._client.request(url="/isos", method="GET", params=params)
|
||||
isos = [BoundIso(self, iso_data) for iso_data in response["isos"]]
|
||||
return self._add_meta_to_result(isos, response)
|
||||
|
||||
def get_all(
|
||||
self,
|
||||
name=None, # type: Optional[str]
|
||||
architecture=None, # type: Optional[List[str]]
|
||||
include_wildcard_architecture=None, # type: Optional[bool]
|
||||
include_architecture_wildcard=None, # type: Optional[bool]
|
||||
):
|
||||
# type: (...) -> List[BoundIso]
|
||||
"""Get all ISOs
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter ISOs by their name.
|
||||
:param architecture: List[str] (optional)
|
||||
Can be used to filter ISOs by their architecture. Choices: x86 arm
|
||||
:param include_wildcard_architecture: bool (optional)
|
||||
Deprecated, please use `include_architecture_wildcard` instead.
|
||||
:param include_architecture_wildcard: bool (optional)
|
||||
Custom ISOs do not have an architecture set. You must also set this flag to True if you are filtering by
|
||||
architecture and also want custom ISOs.
|
||||
:return: List[:class:`BoundIso <hcloud.isos.client.BoundIso>`]
|
||||
"""
|
||||
|
||||
if include_wildcard_architecture is not None:
|
||||
warn(
|
||||
"The `include_wildcard_architecture` argument is deprecated, please use the `include_architecture_wildcard` argument instead.",
|
||||
DeprecationWarning,
|
||||
)
|
||||
include_architecture_wildcard = include_wildcard_architecture
|
||||
|
||||
return super().get_all(
|
||||
name=name,
|
||||
architecture=architecture,
|
||||
include_architecture_wildcard=include_architecture_wildcard,
|
||||
)
|
||||
|
||||
def get_by_name(self, name):
|
||||
# type: (str) -> BoundIso
|
||||
"""Get iso by name
|
||||
|
||||
:param name: str
|
||||
Used to get iso by name.
|
||||
:return: :class:`BoundIso <hcloud.isos.client.BoundIso>`
|
||||
"""
|
||||
return super().get_by_name(name)
|
42
plugins/module_utils/vendor/hcloud/isos/domain.py
vendored
Normal file
42
plugins/module_utils/vendor/hcloud/isos/domain.py
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
try:
|
||||
from dateutil.parser import isoparse
|
||||
except ImportError:
|
||||
isoparse = None
|
||||
|
||||
from ..core.domain import BaseDomain, DomainIdentityMixin
|
||||
|
||||
|
||||
class Iso(BaseDomain, DomainIdentityMixin):
|
||||
"""Iso Domain
|
||||
|
||||
:param id: int
|
||||
ID of the ISO
|
||||
:param name: str, None
|
||||
Unique identifier of the ISO. Only set for public ISOs
|
||||
:param description: str
|
||||
Description of the ISO
|
||||
:param type: str
|
||||
Type of the ISO. Choices: `public`, `private`
|
||||
:param architecture: str, None
|
||||
CPU Architecture that the ISO is compatible with. None means that the compatibility is unknown. Choices: `x86`, `arm`
|
||||
:param deprecated: datetime, None
|
||||
ISO 8601 timestamp of deprecation, None if ISO is still available. After the deprecation time it will no longer be possible to attach the ISO to servers.
|
||||
"""
|
||||
|
||||
__slots__ = ("id", "name", "type", "architecture", "description", "deprecated")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id=None,
|
||||
name=None,
|
||||
type=None,
|
||||
architecture=None,
|
||||
description=None,
|
||||
deprecated=None,
|
||||
):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.type = type
|
||||
self.architecture = architecture
|
||||
self.description = description
|
||||
self.deprecated = isoparse(deprecated) if deprecated else None
|
0
plugins/module_utils/vendor/hcloud/load_balancer_types/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/load_balancer_types/__init__.py
vendored
Normal file
74
plugins/module_utils/vendor/hcloud/load_balancer_types/client.py
vendored
Normal file
74
plugins/module_utils/vendor/hcloud/load_balancer_types/client.py
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
from ..core.client import BoundModelBase, ClientEntityBase, GetEntityByNameMixin
|
||||
from .domain import LoadBalancerType
|
||||
|
||||
|
||||
class BoundLoadBalancerType(BoundModelBase):
|
||||
model = LoadBalancerType
|
||||
|
||||
|
||||
class LoadBalancerTypesClient(ClientEntityBase, GetEntityByNameMixin):
|
||||
results_list_attribute_name = "load_balancer_types"
|
||||
|
||||
def get_by_id(self, id):
|
||||
# type: (int) -> load_balancer_types.client.BoundLoadBalancerType
|
||||
"""Returns a specific Load Balancer Type.
|
||||
|
||||
:param id: int
|
||||
:return: :class:`BoundLoadBalancerType <hcloud.load_balancer_type.client.BoundLoadBalancerType>`
|
||||
"""
|
||||
response = self._client.request(
|
||||
url="/load_balancer_types/{load_balancer_type_id}".format(
|
||||
load_balancer_type_id=id
|
||||
),
|
||||
method="GET",
|
||||
)
|
||||
return BoundLoadBalancerType(self, response["load_balancer_type"])
|
||||
|
||||
def get_list(self, name=None, page=None, per_page=None):
|
||||
# type: (Optional[str], Optional[int], Optional[int]) -> PageResults[List[BoundLoadBalancerType], Meta]
|
||||
"""Get a list of Load Balancer types
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter Load Balancer type by their name.
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundLoadBalancerType <hcloud.load_balancer_types.client.BoundLoadBalancerType>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
if name is not None:
|
||||
params["name"] = name
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
|
||||
response = self._client.request(
|
||||
url="/load_balancer_types", method="GET", params=params
|
||||
)
|
||||
load_balancer_types = [
|
||||
BoundLoadBalancerType(self, load_balancer_type_data)
|
||||
for load_balancer_type_data in response["load_balancer_types"]
|
||||
]
|
||||
return self._add_meta_to_result(load_balancer_types, response)
|
||||
|
||||
def get_all(self, name=None):
|
||||
# type: (Optional[str]) -> List[BoundLoadBalancerType]
|
||||
"""Get all Load Balancer types
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter Load Balancer type by their name.
|
||||
:return: List[:class:`BoundLoadBalancerType <hcloud.load_balancer_types.client.BoundLoadBalancerType>`]
|
||||
"""
|
||||
return super().get_all(name=name)
|
||||
|
||||
def get_by_name(self, name):
|
||||
# type: (str) -> BoundLoadBalancerType
|
||||
"""Get Load Balancer type by name
|
||||
|
||||
:param name: str
|
||||
Used to get Load Balancer type by name.
|
||||
:return: :class:`BoundLoadBalancerType <hcloud.load_balancer_types.client.BoundLoadBalancerType>`
|
||||
"""
|
||||
return super().get_by_name(name)
|
55
plugins/module_utils/vendor/hcloud/load_balancer_types/domain.py
vendored
Normal file
55
plugins/module_utils/vendor/hcloud/load_balancer_types/domain.py
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
from ..core.domain import BaseDomain, DomainIdentityMixin
|
||||
|
||||
|
||||
class LoadBalancerType(BaseDomain, DomainIdentityMixin):
|
||||
"""LoadBalancerType Domain
|
||||
|
||||
:param id: int
|
||||
ID of the Load Balancer type
|
||||
:param name: str
|
||||
Name of the Load Balancer type
|
||||
:param description: str
|
||||
Description of the Load Balancer type
|
||||
:param max_connections: int
|
||||
Max amount of connections the Load Balancer can handle
|
||||
:param max_services: int
|
||||
Max amount of services the Load Balancer can handle
|
||||
:param max_targets: int
|
||||
Max amount of targets the Load Balancer can handle
|
||||
:param max_assigned_certificates: int
|
||||
Max amount of certificates the Load Balancer can serve
|
||||
:param prices: Dict
|
||||
Prices in different locations
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"id",
|
||||
"name",
|
||||
"description",
|
||||
"max_connections",
|
||||
"max_services",
|
||||
"max_targets",
|
||||
"max_assigned_certificates",
|
||||
"prices",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id=None,
|
||||
name=None,
|
||||
description=None,
|
||||
max_connections=None,
|
||||
max_services=None,
|
||||
max_targets=None,
|
||||
max_assigned_certificates=None,
|
||||
prices=None,
|
||||
):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.max_connections = max_connections
|
||||
self.max_services = max_services
|
||||
self.max_targets = max_targets
|
||||
self.max_assigned_certificates = max_assigned_certificates
|
||||
self.prices = prices
|
0
plugins/module_utils/vendor/hcloud/load_balancers/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/load_balancers/__init__.py
vendored
Normal file
900
plugins/module_utils/vendor/hcloud/load_balancers/client.py
vendored
Normal file
900
plugins/module_utils/vendor/hcloud/load_balancers/client.py
vendored
Normal file
|
@ -0,0 +1,900 @@
|
|||
from ..actions.client import BoundAction
|
||||
from ..certificates.client import BoundCertificate
|
||||
from ..core.client import BoundModelBase, ClientEntityBase, GetEntityByNameMixin
|
||||
from ..core.domain import add_meta_to_result
|
||||
from ..load_balancer_types.client import BoundLoadBalancerType
|
||||
from ..locations.client import BoundLocation
|
||||
from ..networks.client import BoundNetwork
|
||||
from ..servers.client import BoundServer
|
||||
from .domain import (
|
||||
CreateLoadBalancerResponse,
|
||||
IPv4Address,
|
||||
IPv6Network,
|
||||
LoadBalancer,
|
||||
LoadBalancerAlgorithm,
|
||||
LoadBalancerHealtCheckHttp,
|
||||
LoadBalancerHealthCheck,
|
||||
LoadBalancerService,
|
||||
LoadBalancerServiceHttp,
|
||||
LoadBalancerTarget,
|
||||
LoadBalancerTargetIP,
|
||||
LoadBalancerTargetLabelSelector,
|
||||
PrivateNet,
|
||||
PublicNetwork,
|
||||
)
|
||||
|
||||
|
||||
class BoundLoadBalancer(BoundModelBase):
|
||||
model = LoadBalancer
|
||||
|
||||
def __init__(self, client, data, complete=True):
|
||||
algorithm = data.get("algorithm")
|
||||
if algorithm:
|
||||
data["algorithm"] = LoadBalancerAlgorithm(type=algorithm["type"])
|
||||
|
||||
public_net = data.get("public_net")
|
||||
if public_net:
|
||||
ipv4_address = IPv4Address.from_dict(public_net["ipv4"])
|
||||
ipv6_network = IPv6Network.from_dict(public_net["ipv6"])
|
||||
data["public_net"] = PublicNetwork(
|
||||
ipv4=ipv4_address, ipv6=ipv6_network, enabled=public_net["enabled"]
|
||||
)
|
||||
|
||||
private_nets = data.get("private_net")
|
||||
if private_nets:
|
||||
private_nets = [
|
||||
PrivateNet(
|
||||
network=BoundNetwork(
|
||||
client._client.networks,
|
||||
{"id": private_net["network"]},
|
||||
complete=False,
|
||||
),
|
||||
ip=private_net["ip"],
|
||||
)
|
||||
for private_net in private_nets
|
||||
]
|
||||
data["private_net"] = private_nets
|
||||
|
||||
targets = data.get("targets")
|
||||
if targets:
|
||||
tmp_targets = []
|
||||
for target in targets:
|
||||
tmp_target = LoadBalancerTarget(type=target["type"])
|
||||
if target["type"] == "server":
|
||||
tmp_target.server = BoundServer(
|
||||
client._client.servers, data=target["server"], complete=False
|
||||
)
|
||||
tmp_target.use_private_ip = target["use_private_ip"]
|
||||
elif target["type"] == "label_selector":
|
||||
tmp_target.label_selector = LoadBalancerTargetLabelSelector(
|
||||
selector=target["label_selector"]["selector"]
|
||||
)
|
||||
tmp_target.use_private_ip = target["use_private_ip"]
|
||||
elif target["type"] == "ip":
|
||||
tmp_target.ip = LoadBalancerTargetIP(ip=target["ip"]["ip"])
|
||||
tmp_targets.append(tmp_target)
|
||||
data["targets"] = tmp_targets
|
||||
|
||||
services = data.get("services")
|
||||
if services:
|
||||
tmp_services = []
|
||||
for service in services:
|
||||
tmp_service = LoadBalancerService(
|
||||
protocol=service["protocol"],
|
||||
listen_port=service["listen_port"],
|
||||
destination_port=service["destination_port"],
|
||||
proxyprotocol=service["proxyprotocol"],
|
||||
)
|
||||
if service["protocol"] != "tcp":
|
||||
tmp_service.http = LoadBalancerServiceHttp(
|
||||
sticky_sessions=service["http"]["sticky_sessions"],
|
||||
redirect_http=service["http"]["redirect_http"],
|
||||
cookie_name=service["http"]["cookie_name"],
|
||||
cookie_lifetime=service["http"]["cookie_lifetime"],
|
||||
)
|
||||
tmp_service.http.certificates = [
|
||||
BoundCertificate(
|
||||
client._client.certificates,
|
||||
{"id": certificate},
|
||||
complete=False,
|
||||
)
|
||||
for certificate in service["http"]["certificates"]
|
||||
]
|
||||
|
||||
tmp_service.health_check = LoadBalancerHealthCheck(
|
||||
protocol=service["health_check"]["protocol"],
|
||||
port=service["health_check"]["port"],
|
||||
interval=service["health_check"]["interval"],
|
||||
retries=service["health_check"]["retries"],
|
||||
timeout=service["health_check"]["timeout"],
|
||||
)
|
||||
if tmp_service.health_check.protocol != "tcp":
|
||||
tmp_service.health_check.http = LoadBalancerHealtCheckHttp(
|
||||
domain=service["health_check"]["http"]["domain"],
|
||||
path=service["health_check"]["http"]["path"],
|
||||
response=service["health_check"]["http"]["response"],
|
||||
tls=service["health_check"]["http"]["tls"],
|
||||
status_codes=service["health_check"]["http"]["status_codes"],
|
||||
)
|
||||
tmp_services.append(tmp_service)
|
||||
data["services"] = tmp_services
|
||||
|
||||
load_balancer_type = data.get("load_balancer_type")
|
||||
if load_balancer_type is not None:
|
||||
data["load_balancer_type"] = BoundLoadBalancerType(
|
||||
client._client.load_balancer_types, load_balancer_type
|
||||
)
|
||||
|
||||
location = data.get("location")
|
||||
if location is not None:
|
||||
data["location"] = BoundLocation(client._client.locations, location)
|
||||
|
||||
super().__init__(client, data, complete)
|
||||
|
||||
def update(self, name=None, labels=None):
|
||||
# type: (Optional[str], Optional[Dict[str, str]]) -> BoundLoadBalancer
|
||||
"""Updates a Load Balancer. You can update a Load Balancers name and a Load Balancers labels.
|
||||
|
||||
:param name: str (optional)
|
||||
New name to set
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:return: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>`
|
||||
"""
|
||||
return self._client.update(self, name, labels)
|
||||
|
||||
def delete(self):
|
||||
# type: () -> BoundAction
|
||||
"""Deletes a Load Balancer.
|
||||
|
||||
:return: boolean
|
||||
"""
|
||||
return self._client.delete(self)
|
||||
|
||||
def get_actions_list(self, status=None, sort=None, page=None, per_page=None):
|
||||
# type: (Optional[List[str]], Optional[List[str]], Optional[int], Optional[int]) -> PageResults[List[BoundAction, Meta]]
|
||||
"""Returns all action objects for a Load Balancer.
|
||||
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
return self._client.get_actions_list(self, status, sort, page, per_page)
|
||||
|
||||
def get_actions(self, status=None, sort=None):
|
||||
# type: (Optional[List[str]], Optional[List[str]]) -> List[BoundAction]
|
||||
"""Returns all action objects for a Load Balancer.
|
||||
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
return self._client.get_actions(self, status, sort)
|
||||
|
||||
def add_service(self, service):
|
||||
# type: (LoadBalancerService) -> List[BoundAction]
|
||||
"""Adds a service to a Load Balancer.
|
||||
|
||||
:param service: :class:`LoadBalancerService <hcloud.load_balancers.domain.LoadBalancerService>`
|
||||
The LoadBalancerService you want to add to the Load Balancer
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.add_service(self, service=service)
|
||||
|
||||
def update_service(self, service):
|
||||
# type: (LoadBalancerService) -> List[BoundAction]
|
||||
"""Updates a service of an Load Balancer.
|
||||
|
||||
:param service: :class:`LoadBalancerService <hcloud.load_balancers.domain.LoadBalancerService>`
|
||||
The LoadBalancerService you want to update
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.update_service(self, service=service)
|
||||
|
||||
def delete_service(self, service):
|
||||
# type: (LoadBalancerService) -> List[BoundAction]
|
||||
"""Deletes a service from a Load Balancer.
|
||||
|
||||
:param service: :class:`LoadBalancerService <hcloud.load_balancers.domain.LoadBalancerService>`
|
||||
The LoadBalancerService you want to delete from the Load Balancer
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.delete_service(self, service)
|
||||
|
||||
def add_target(self, target):
|
||||
# type: (LoadBalancerTarget) -> List[BoundAction]
|
||||
"""Adds a target to a Load Balancer.
|
||||
|
||||
:param target: :class:`LoadBalancerTarget <hcloud.load_balancers.domain.LoadBalancerTarget>`
|
||||
The LoadBalancerTarget you want to add to the Load Balancer
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.add_target(self, target)
|
||||
|
||||
def remove_target(self, target):
|
||||
# type: (LoadBalancerTarget) -> List[BoundAction]
|
||||
"""Removes a target from a Load Balancer.
|
||||
|
||||
:param target: :class:`LoadBalancerTarget <hcloud.load_balancers.domain.LoadBalancerTarget>`
|
||||
The LoadBalancerTarget you want to remove from the Load Balancer
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.remove_target(self, target)
|
||||
|
||||
def change_algorithm(self, algorithm):
|
||||
# type: (LoadBalancerAlgorithm) -> List[BoundAction]
|
||||
"""Changes the algorithm used by the Load Balancer
|
||||
|
||||
:param algorithm: :class:`LoadBalancerAlgorithm <hcloud.load_balancers.domain.LoadBalancerAlgorithm>`
|
||||
The LoadBalancerAlgorithm you want to use
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.change_algorithm(self, algorithm)
|
||||
|
||||
def change_dns_ptr(self, ip, dns_ptr):
|
||||
# type: (str, str) -> BoundAction
|
||||
"""Changes the hostname that will appear when getting the hostname belonging to the public IPs (IPv4 and IPv6) of this Load Balancer.
|
||||
|
||||
:param ip: str
|
||||
The IP address for which to set the reverse DNS entry
|
||||
:param dns_ptr: str
|
||||
Hostname to set as a reverse DNS PTR entry, will reset to original default value if `None`
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.change_dns_ptr(self, ip, dns_ptr)
|
||||
|
||||
def change_protection(self, delete):
|
||||
# type: (LoadBalancerService) -> List[BoundAction]
|
||||
"""Changes the protection configuration of a Load Balancer.
|
||||
|
||||
:param delete: boolean
|
||||
If True, prevents the Load Balancer from being deleted
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.change_protection(self, delete)
|
||||
|
||||
def attach_to_network(self, network, ip=None):
|
||||
# type: (Union[Network,BoundNetwork],Optional[str]) -> BoundAction
|
||||
"""Attaches a Load Balancer to a Network
|
||||
|
||||
:param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
|
||||
:param ip: str
|
||||
IP to request to be assigned to this Load Balancer
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.attach_to_network(self, network, ip)
|
||||
|
||||
def detach_from_network(self, network):
|
||||
# type: ( Union[Network,BoundNetwork]) -> BoundAction
|
||||
"""Detaches a Load Balancer from a Network.
|
||||
|
||||
:param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.detach_from_network(self, network)
|
||||
|
||||
def enable_public_interface(self):
|
||||
# type: () -> BoundAction
|
||||
"""Enables the public interface of a Load Balancer.
|
||||
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.enable_public_interface(self)
|
||||
|
||||
def disable_public_interface(self):
|
||||
# type: () -> BoundAction
|
||||
"""Disables the public interface of a Load Balancer.
|
||||
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.disable_public_interface(self)
|
||||
|
||||
def change_type(self, load_balancer_type):
|
||||
# type: (Union[LoadBalancerType,BoundLoadBalancerType]) -> BoundAction
|
||||
"""Changes the type of a Load Balancer.
|
||||
|
||||
:param load_balancer_type: :class:`BoundLoadBalancerType <hcloud.load_balancer_types.client.BoundLoadBalancerType>` or :class:`LoadBalancerType <hcloud.load_balancer_types.domain.LoadBalancerType>`
|
||||
Load Balancer type the Load Balancer should migrate to
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.change_type(self, load_balancer_type)
|
||||
|
||||
|
||||
class LoadBalancersClient(ClientEntityBase, GetEntityByNameMixin):
|
||||
results_list_attribute_name = "load_balancers"
|
||||
|
||||
def get_by_id(self, id):
|
||||
# type: (int) -> BoundLoadBalancer
|
||||
"""Get a specific Load Balancer
|
||||
|
||||
:param id: int
|
||||
:return: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>`
|
||||
"""
|
||||
response = self._client.request(
|
||||
url=f"/load_balancers/{id}",
|
||||
method="GET",
|
||||
)
|
||||
return BoundLoadBalancer(self, response["load_balancer"])
|
||||
|
||||
def get_list(
|
||||
self,
|
||||
name=None, # type: Optional[str]
|
||||
label_selector=None, # type: Optional[str]
|
||||
page=None, # type: Optional[int]
|
||||
per_page=None, # type: Optional[int]
|
||||
):
|
||||
# type: (...) -> PageResults[List[BoundLoadBalancer], Meta]
|
||||
"""Get a list of Load Balancers from this account
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter Load Balancers by their name.
|
||||
:param label_selector: str (optional)
|
||||
Can be used to filter Load Balancers by labels. The response will only contain Load Balancers matching the label selector.
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
if name is not None:
|
||||
params["name"] = name
|
||||
if label_selector is not None:
|
||||
params["label_selector"] = label_selector
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
|
||||
response = self._client.request(
|
||||
url="/load_balancers", method="GET", params=params
|
||||
)
|
||||
|
||||
ass_load_balancers = [
|
||||
BoundLoadBalancer(self, load_balancer_data)
|
||||
for load_balancer_data in response["load_balancers"]
|
||||
]
|
||||
return self._add_meta_to_result(ass_load_balancers, response)
|
||||
|
||||
def get_all(self, name=None, label_selector=None):
|
||||
# type: (Optional[str], Optional[str]) -> List[BoundLoadBalancer]
|
||||
"""Get all Load Balancers from this account
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter Load Balancers by their name.
|
||||
:param label_selector: str (optional)
|
||||
Can be used to filter Load Balancers by labels. The response will only contain Load Balancers matching the label selector.
|
||||
:return: List[:class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>`]
|
||||
"""
|
||||
return super().get_all(name=name, label_selector=label_selector)
|
||||
|
||||
def get_by_name(self, name):
|
||||
# type: (str) -> BoundLoadBalancer
|
||||
"""Get Load Balancer by name
|
||||
|
||||
:param name: str
|
||||
Used to get Load Balancer by name.
|
||||
:return: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>`
|
||||
"""
|
||||
return super().get_by_name(name)
|
||||
|
||||
def create(
|
||||
self,
|
||||
name, # type: str
|
||||
load_balancer_type, # type: LoadBalancerType
|
||||
algorithm=None, # type: Optional[LoadBalancerAlgorithm]
|
||||
services=None, # type: Optional[List[LoadBalancerService]]
|
||||
targets=None, # type: Optional[List[LoadBalancerTarget]]
|
||||
labels=None, # type: Optional[Dict[str, str]]
|
||||
location=None, # type: Optional[Location]
|
||||
network_zone=None, # type: Optional[str]
|
||||
public_interface=None, # type: Optional[bool]
|
||||
network=None, # type: Optional[Union[Network,BoundNetwork]]
|
||||
):
|
||||
# type: (...) -> CreateLoadBalancerResponse
|
||||
"""Creates a Load Balancer .
|
||||
|
||||
:param name: str
|
||||
Name of the Load Balancer
|
||||
:param load_balancer_type: LoadBalancerType
|
||||
Type of the Load Balancer
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:param location: Location
|
||||
Location of the Load Balancer
|
||||
:param network_zone: str
|
||||
Network Zone of the Load Balancer
|
||||
:param algorithm: LoadBalancerAlgorithm (optional)
|
||||
The algorithm the Load Balancer is currently using
|
||||
:param services: LoadBalancerService
|
||||
The services the Load Balancer is currently serving
|
||||
:param targets: LoadBalancerTarget
|
||||
The targets the Load Balancer is currently serving
|
||||
:param public_interface: bool
|
||||
Enable or disable the public interface of the Load Balancer
|
||||
:param network: Network
|
||||
Adds the Load Balancer to a Network
|
||||
:return: :class:`CreateLoadBalancerResponse <hcloud.load_balancers.domain.CreateLoadBalancerResponse>`
|
||||
"""
|
||||
data = {"name": name, "load_balancer_type": load_balancer_type.id_or_name}
|
||||
if network is not None:
|
||||
data["network"] = network.id
|
||||
if public_interface is not None:
|
||||
data["public_interface"] = public_interface
|
||||
if labels is not None:
|
||||
data["labels"] = labels
|
||||
if algorithm is not None:
|
||||
data["algorithm"] = {"type": algorithm.type}
|
||||
if services is not None:
|
||||
service_list = []
|
||||
for service in services:
|
||||
service_list.append(self.get_service_parameters(service))
|
||||
data["services"] = service_list
|
||||
|
||||
if targets is not None:
|
||||
target_list = []
|
||||
for target in targets:
|
||||
target_data = {
|
||||
"type": target.type,
|
||||
"use_private_ip": target.use_private_ip,
|
||||
}
|
||||
if target.type == "server":
|
||||
target_data["server"] = {"id": target.server.id}
|
||||
elif target.type == "label_selector":
|
||||
target_data["label_selector"] = {
|
||||
"selector": target.label_selector.selector
|
||||
}
|
||||
elif target.type == "ip":
|
||||
target_data["ip"] = {"ip": target.ip.ip}
|
||||
target_list.append(target_data)
|
||||
|
||||
data["targets"] = target_list
|
||||
|
||||
if network_zone is not None:
|
||||
data["network_zone"] = network_zone
|
||||
if location is not None:
|
||||
data["location"] = location.id_or_name
|
||||
|
||||
response = self._client.request(url="/load_balancers", method="POST", json=data)
|
||||
|
||||
return CreateLoadBalancerResponse(
|
||||
load_balancer=BoundLoadBalancer(self, response["load_balancer"]),
|
||||
action=BoundAction(self._client.actions, response["action"]),
|
||||
)
|
||||
|
||||
def update(self, load_balancer, name=None, labels=None):
|
||||
# type:(LoadBalancer, Optional[str], Optional[Dict[str, str]]) -> BoundLoadBalancer
|
||||
"""Updates a LoadBalancer. You can update a LoadBalancer’s name and a LoadBalancer’s labels.
|
||||
|
||||
:param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
|
||||
:param name: str (optional)
|
||||
New name to set
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:return: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>`
|
||||
"""
|
||||
data = {}
|
||||
if name is not None:
|
||||
data.update({"name": name})
|
||||
if labels is not None:
|
||||
data.update({"labels": labels})
|
||||
response = self._client.request(
|
||||
url="/load_balancers/{load_balancer_id}".format(
|
||||
load_balancer_id=load_balancer.id
|
||||
),
|
||||
method="PUT",
|
||||
json=data,
|
||||
)
|
||||
return BoundLoadBalancer(self, response["load_balancer"])
|
||||
|
||||
def delete(self, load_balancer):
|
||||
# type: (LoadBalancer) -> BoundAction
|
||||
"""Deletes a Load Balancer.
|
||||
|
||||
:param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
|
||||
:return: boolean
|
||||
"""
|
||||
self._client.request(
|
||||
url="/load_balancers/{load_balancer_id}".format(
|
||||
load_balancer_id=load_balancer.id
|
||||
),
|
||||
method="DELETE",
|
||||
)
|
||||
return True
|
||||
|
||||
def get_actions_list(
|
||||
self, load_balancer, status=None, sort=None, page=None, per_page=None
|
||||
):
|
||||
# type: (LoadBalancer, Optional[List[str]], Optional[List[str]], Optional[int], Optional[int]) -> PageResults[List[BoundAction], Meta]
|
||||
"""Returns all action objects for a Load Balancer.
|
||||
|
||||
:param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
if status is not None:
|
||||
params["status"] = status
|
||||
if sort is not None:
|
||||
params["sort"] = sort
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
|
||||
response = self._client.request(
|
||||
url="/load_balancers/{load_balancer_id}/actions".format(
|
||||
load_balancer_id=load_balancer.id
|
||||
),
|
||||
method="GET",
|
||||
params=params,
|
||||
)
|
||||
actions = [
|
||||
BoundAction(self._client.actions, action_data)
|
||||
for action_data in response["actions"]
|
||||
]
|
||||
return add_meta_to_result(actions, response, "actions")
|
||||
|
||||
def get_actions(self, load_balancer, status=None, sort=None):
|
||||
# type: (LoadBalancer, Optional[List[str]], Optional[List[str]]) -> List[BoundAction]
|
||||
"""Returns all action objects for a Load Balancer.
|
||||
|
||||
:param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
return super().get_actions(load_balancer, status=status, sort=sort)
|
||||
|
||||
def add_service(self, load_balancer, service):
|
||||
# type: (Union[LoadBalancer, BoundLoadBalancer], LoadBalancerService) -> List[BoundAction]
|
||||
"""Adds a service to a Load Balancer.
|
||||
|
||||
:param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
|
||||
:param service: :class:`LoadBalancerService <hcloud.load_balancers.domain.LoadBalancerService>`
|
||||
The LoadBalancerService you want to add to the Load Balancer
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = self.get_service_parameters(service)
|
||||
|
||||
response = self._client.request(
|
||||
url="/load_balancers/{load_balancer_id}/actions/add_service".format(
|
||||
load_balancer_id=load_balancer.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def get_service_parameters(self, service):
|
||||
data = {}
|
||||
if service.protocol is not None:
|
||||
data["protocol"] = service.protocol
|
||||
if service.listen_port is not None:
|
||||
data["listen_port"] = service.listen_port
|
||||
if service.destination_port is not None:
|
||||
data["destination_port"] = service.destination_port
|
||||
if service.proxyprotocol is not None:
|
||||
data["proxyprotocol"] = service.proxyprotocol
|
||||
if service.http is not None:
|
||||
data["http"] = {}
|
||||
if service.http.cookie_name is not None:
|
||||
data["http"]["cookie_name"] = service.http.cookie_name
|
||||
if service.http.cookie_lifetime is not None:
|
||||
data["http"]["cookie_lifetime"] = service.http.cookie_lifetime
|
||||
if service.http.redirect_http is not None:
|
||||
data["http"]["redirect_http"] = service.http.redirect_http
|
||||
if service.http.sticky_sessions is not None:
|
||||
data["http"]["sticky_sessions"] = service.http.sticky_sessions
|
||||
certificate_ids = []
|
||||
for certificate in service.http.certificates:
|
||||
certificate_ids.append(certificate.id)
|
||||
data["http"]["certificates"] = certificate_ids
|
||||
if service.health_check is not None:
|
||||
data["health_check"] = {
|
||||
"protocol": service.health_check.protocol,
|
||||
"port": service.health_check.port,
|
||||
"interval": service.health_check.interval,
|
||||
"timeout": service.health_check.timeout,
|
||||
"retries": service.health_check.retries,
|
||||
}
|
||||
data["health_check"] = {}
|
||||
if service.health_check.protocol is not None:
|
||||
data["health_check"]["protocol"] = service.health_check.protocol
|
||||
if service.health_check.port is not None:
|
||||
data["health_check"]["port"] = service.health_check.port
|
||||
if service.health_check.interval is not None:
|
||||
data["health_check"]["interval"] = service.health_check.interval
|
||||
if service.health_check.timeout is not None:
|
||||
data["health_check"]["timeout"] = service.health_check.timeout
|
||||
if service.health_check.retries is not None:
|
||||
data["health_check"]["retries"] = service.health_check.retries
|
||||
if service.health_check.http is not None:
|
||||
data["health_check"]["http"] = {}
|
||||
if service.health_check.http.domain is not None:
|
||||
data["health_check"]["http"][
|
||||
"domain"
|
||||
] = service.health_check.http.domain
|
||||
if service.health_check.http.path is not None:
|
||||
data["health_check"]["http"][
|
||||
"path"
|
||||
] = service.health_check.http.path
|
||||
if service.health_check.http.response is not None:
|
||||
data["health_check"]["http"][
|
||||
"response"
|
||||
] = service.health_check.http.response
|
||||
if service.health_check.http.status_codes is not None:
|
||||
data["health_check"]["http"][
|
||||
"status_codes"
|
||||
] = service.health_check.http.status_codes
|
||||
if service.health_check.http.tls is not None:
|
||||
data["health_check"]["http"]["tls"] = service.health_check.http.tls
|
||||
return data
|
||||
|
||||
def update_service(self, load_balancer, service):
|
||||
# type: (Union[LoadBalancer, BoundLoadBalancer], LoadBalancerService) -> List[BoundAction]
|
||||
"""Updates a service of an Load Balancer.
|
||||
|
||||
:param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
|
||||
:param service: :class:`LoadBalancerService <hcloud.load_balancers.domain.LoadBalancerService>`
|
||||
The LoadBalancerService with updated values within for the Load Balancer
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = self.get_service_parameters(service)
|
||||
response = self._client.request(
|
||||
url="/load_balancers/{load_balancer_id}/actions/update_service".format(
|
||||
load_balancer_id=load_balancer.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def delete_service(self, load_balancer, service):
|
||||
# type: (Union[LoadBalancer, BoundLoadBalancer], LoadBalancerService) -> List[BoundAction]
|
||||
"""Deletes a service from a Load Balancer.
|
||||
|
||||
:param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
|
||||
:param service: :class:`LoadBalancerService <hcloud.load_balancers.domain.LoadBalancerService>`
|
||||
The LoadBalancerService you want to delete from the Load Balancer
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {"listen_port": service.listen_port}
|
||||
|
||||
response = self._client.request(
|
||||
url="/load_balancers/{load_balancer_id}/actions/delete_service".format(
|
||||
load_balancer_id=load_balancer.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def add_target(self, load_balancer, target):
|
||||
# type: (Union[LoadBalancer, BoundLoadBalancer], LoadBalancerTarget) -> List[BoundAction]
|
||||
"""Adds a target to a Load Balancer.
|
||||
|
||||
:param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
|
||||
:param target: :class:`LoadBalancerTarget <hcloud.load_balancers.domain.LoadBalancerTarget>`
|
||||
The LoadBalancerTarget you want to add to the Load Balancer
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {"type": target.type, "use_private_ip": target.use_private_ip}
|
||||
if target.type == "server":
|
||||
data["server"] = {"id": target.server.id}
|
||||
elif target.type == "label_selector":
|
||||
data["label_selector"] = {"selector": target.label_selector.selector}
|
||||
elif target.type == "ip":
|
||||
data["ip"] = {"ip": target.ip.ip}
|
||||
|
||||
response = self._client.request(
|
||||
url="/load_balancers/{load_balancer_id}/actions/add_target".format(
|
||||
load_balancer_id=load_balancer.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def remove_target(self, load_balancer, target):
|
||||
# type: (Union[LoadBalancer, BoundLoadBalancer], LoadBalancerTarget) -> List[BoundAction]
|
||||
"""Removes a target from a Load Balancer.
|
||||
|
||||
:param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
|
||||
:param target: :class:`LoadBalancerTarget <hcloud.load_balancers.domain.LoadBalancerTarget>`
|
||||
The LoadBalancerTarget you want to remove from the Load Balancer
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {"type": target.type}
|
||||
if target.type == "server":
|
||||
data["server"] = {"id": target.server.id}
|
||||
elif target.type == "label_selector":
|
||||
data["label_selector"] = {"selector": target.label_selector.selector}
|
||||
elif target.type == "ip":
|
||||
data["ip"] = {"ip": target.ip.ip}
|
||||
|
||||
response = self._client.request(
|
||||
url="/load_balancers/{load_balancer_id}/actions/remove_target".format(
|
||||
load_balancer_id=load_balancer.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def change_algorithm(self, load_balancer, algorithm):
|
||||
# type: (Union[LoadBalancer, BoundLoadBalancer], Optional[bool]) -> BoundAction
|
||||
"""Changes the algorithm used by the Load Balancer
|
||||
|
||||
:param load_balancer: :class:` <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
|
||||
:param algorithm: :class:`LoadBalancerAlgorithm <hcloud.load_balancers.domain.LoadBalancerAlgorithm>`
|
||||
The LoadBalancerSubnet you want to add to the Load Balancer
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {"type": algorithm.type}
|
||||
|
||||
response = self._client.request(
|
||||
url="/load_balancers/{load_balancer_id}/actions/change_algorithm".format(
|
||||
load_balancer_id=load_balancer.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def change_dns_ptr(self, load_balancer, ip, dns_ptr):
|
||||
# type: (Union[LoadBalancer, BoundLoadBalancer], str, str) -> BoundAction
|
||||
"""Changes the hostname that will appear when getting the hostname belonging to the public IPs (IPv4 and IPv6) of this Load Balancer.
|
||||
|
||||
:param ip: str
|
||||
The IP address for which to set the reverse DNS entry
|
||||
:param dns_ptr: str
|
||||
Hostname to set as a reverse DNS PTR entry, will reset to original default value if `None`
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
|
||||
response = self._client.request(
|
||||
url="/load_balancers/{load_balancer_id}/actions/change_dns_ptr".format(
|
||||
load_balancer_id=load_balancer.id
|
||||
),
|
||||
method="POST",
|
||||
json={"ip": ip, "dns_ptr": dns_ptr},
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def change_protection(self, load_balancer, delete=None):
|
||||
# type: (Union[LoadBalancer, BoundLoadBalancer], Optional[bool]) -> BoundAction
|
||||
"""Changes the protection configuration of a Load Balancer.
|
||||
|
||||
:param load_balancer: :class:` <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
|
||||
:param delete: boolean
|
||||
If True, prevents the Load Balancer from being deleted
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {}
|
||||
if delete is not None:
|
||||
data.update({"delete": delete})
|
||||
|
||||
response = self._client.request(
|
||||
url="/load_balancers/{load_balancer_id}/actions/change_protection".format(
|
||||
load_balancer_id=load_balancer.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def attach_to_network(
|
||||
self,
|
||||
load_balancer, # type: Union[LoadBalancer, BoundLoadBalancer]
|
||||
network, # type: Union[Network, BoundNetwork]
|
||||
ip=None, # type: Optional[str]
|
||||
):
|
||||
"""Attach a Load Balancer to a Network.
|
||||
|
||||
:param load_balancer: :class:` <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
|
||||
:param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
|
||||
:param ip: str
|
||||
IP to request to be assigned to this Load Balancer
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {"network": network.id}
|
||||
if ip is not None:
|
||||
data.update({"ip": ip})
|
||||
|
||||
response = self._client.request(
|
||||
url="/load_balancers/{load_balancer_id}/actions/attach_to_network".format(
|
||||
load_balancer_id=load_balancer.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def detach_from_network(self, load_balancer, network):
|
||||
# type: (Union[LoadBalancer, BoundLoadBalancer], Union[Network,BoundNetwork]) -> BoundAction
|
||||
"""Detaches a Load Balancer from a Network.
|
||||
|
||||
:param load_balancer: :class:` <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
|
||||
:param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {"network": network.id}
|
||||
response = self._client.request(
|
||||
url="/load_balancers/{load_balancer_id}/actions/detach_from_network".format(
|
||||
load_balancer_id=load_balancer.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def enable_public_interface(self, load_balancer):
|
||||
# type: (Union[LoadBalancer, BoundLoadBalancer]) -> BoundAction
|
||||
"""Enables the public interface of a Load Balancer.
|
||||
|
||||
:param load_balancer: :class:` <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
|
||||
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
|
||||
response = self._client.request(
|
||||
url="/load_balancers/{load_balancer_id}/actions/enable_public_interface".format(
|
||||
load_balancer_id=load_balancer.id
|
||||
),
|
||||
method="POST",
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def disable_public_interface(self, load_balancer):
|
||||
# type: (Union[LoadBalancer, BoundLoadBalancer]) -> BoundAction
|
||||
"""Disables the public interface of a Load Balancer.
|
||||
|
||||
:param load_balancer: :class:` <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
|
||||
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
|
||||
response = self._client.request(
|
||||
url="/load_balancers/{load_balancer_id}/actions/disable_public_interface".format(
|
||||
load_balancer_id=load_balancer.id
|
||||
),
|
||||
method="POST",
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def change_type(self, load_balancer, load_balancer_type):
|
||||
# type: ([LoadBalancer, BoundLoadBalancer], [LoadBalancerType, BoundLoadBalancerType]) ->BoundAction
|
||||
"""Changes the type of a Load Balancer.
|
||||
|
||||
:param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>` or :class:`LoadBalancer <hcloud.load_balancers.domain.LoadBalancer>`
|
||||
:param load_balancer_type: :class:`BoundLoadBalancerType <hcloud.load_balancer_types.client.BoundLoadBalancerType>` or :class:`LoadBalancerType <hcloud.load_balancer_types.domain.LoadBalancerType>`
|
||||
Load Balancer type the Load Balancer should migrate to
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {"load_balancer_type": load_balancer_type.id_or_name}
|
||||
response = self._client.request(
|
||||
url="/load_balancers/{load_balancer_id}/actions/change_type".format(
|
||||
load_balancer_id=load_balancer.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
370
plugins/module_utils/vendor/hcloud/load_balancers/domain.py
vendored
Normal file
370
plugins/module_utils/vendor/hcloud/load_balancers/domain.py
vendored
Normal file
|
@ -0,0 +1,370 @@
|
|||
try:
|
||||
from dateutil.parser import isoparse
|
||||
except ImportError:
|
||||
isoparse = None
|
||||
|
||||
from ..core.domain import BaseDomain
|
||||
|
||||
|
||||
class LoadBalancer(BaseDomain):
|
||||
"""LoadBalancer Domain
|
||||
|
||||
:param id: int
|
||||
ID of the Load Balancer
|
||||
:param name: str
|
||||
Name of the Load Balancer (must be unique per project)
|
||||
:param created: datetime
|
||||
Point in time when the Load Balancer was created
|
||||
:param protection: dict
|
||||
Protection configuration for the Load Balancer
|
||||
:param labels: dict
|
||||
User-defined labels (key-value pairs)
|
||||
:param location: Location
|
||||
Location of the Load Balancer
|
||||
:param public_net: :class:`PublicNetwork <hcloud.load_balancers.domain.PublicNetwork>`
|
||||
Public network information.
|
||||
:param private_net: List[:class:`PrivateNet <hcloud.load_balancers.domain.PrivateNet`]
|
||||
Private networks information.
|
||||
:param algorithm: LoadBalancerAlgorithm
|
||||
The algorithm the Load Balancer is currently using
|
||||
:param services: List[LoadBalancerService]
|
||||
The services the LoadBalancer is currently serving
|
||||
:param targets: LoadBalancerTarget
|
||||
The targets the LoadBalancer is currently serving
|
||||
:param load_balancer_type: LoadBalancerType
|
||||
The type of the Load Balancer
|
||||
:param outgoing_traffic: int, None
|
||||
Outbound Traffic for the current billing period in bytes
|
||||
:param ingoing_traffic: int, None
|
||||
Inbound Traffic for the current billing period in bytes
|
||||
:param included_traffic: int
|
||||
Free Traffic for the current billing period in bytes
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"id",
|
||||
"name",
|
||||
"public_net",
|
||||
"private_net",
|
||||
"location",
|
||||
"algorithm",
|
||||
"services",
|
||||
"load_balancer_type",
|
||||
"protection",
|
||||
"labels",
|
||||
"targets",
|
||||
"created",
|
||||
"outgoing_traffic",
|
||||
"ingoing_traffic",
|
||||
"included_traffic",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id,
|
||||
name=None,
|
||||
public_net=None,
|
||||
private_net=None,
|
||||
location=None,
|
||||
algorithm=None,
|
||||
services=None,
|
||||
load_balancer_type=None,
|
||||
protection=None,
|
||||
labels=None,
|
||||
targets=None,
|
||||
created=None,
|
||||
outgoing_traffic=None,
|
||||
ingoing_traffic=None,
|
||||
included_traffic=None,
|
||||
):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.created = isoparse(created) if created else None
|
||||
self.public_net = public_net
|
||||
self.private_net = private_net
|
||||
self.location = location
|
||||
self.algorithm = algorithm
|
||||
self.services = services
|
||||
self.load_balancer_type = load_balancer_type
|
||||
self.targets = targets
|
||||
self.protection = protection
|
||||
self.labels = labels
|
||||
self.outgoing_traffic = outgoing_traffic
|
||||
self.ingoing_traffic = ingoing_traffic
|
||||
self.included_traffic = included_traffic
|
||||
|
||||
|
||||
class LoadBalancerService(BaseDomain):
|
||||
"""LoadBalancerService Domain
|
||||
|
||||
:param protocol: str
|
||||
Protocol of the service Choices: tcp, http, https
|
||||
:param listen_port: int
|
||||
Required when protocol is tcp, must be unique per Load Balancer.
|
||||
:param destination_port: int
|
||||
Required when protocol is tcp
|
||||
:param proxyprotocol: bool
|
||||
Enable proxyprotocol
|
||||
:param health_check: LoadBalancerHealthCheck
|
||||
Configuration for health checks
|
||||
:param http: LoadBalancerServiceHttp
|
||||
Configuration for http/https protocols, required when protocol is http/https
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
protocol=None,
|
||||
listen_port=None,
|
||||
destination_port=None,
|
||||
proxyprotocol=None,
|
||||
health_check=None,
|
||||
http=None,
|
||||
):
|
||||
self.protocol = protocol
|
||||
self.listen_port = listen_port
|
||||
self.destination_port = destination_port
|
||||
self.proxyprotocol = proxyprotocol
|
||||
self.health_check = health_check
|
||||
self.http = http
|
||||
|
||||
|
||||
class LoadBalancerServiceHttp(BaseDomain):
|
||||
"""LoadBalancerServiceHttp Domain
|
||||
|
||||
:param cookie_name: str
|
||||
Name of the cookie used for Session Stickness
|
||||
:param cookie_lifetime: str
|
||||
Lifetime of the cookie used for Session Stickness
|
||||
:param certificates: list
|
||||
IDs of the Certificates to use for TLS/SSL termination by the Load Balancer; empty for TLS/SSL passthrough or if protocol is "http"
|
||||
:param redirect_http: bool
|
||||
Redirect traffic from http port 80 to port 443
|
||||
:param sticky_sessions: bool
|
||||
Use sticky sessions. Only available if protocol is "http" or "https".
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
cookie_name=None,
|
||||
cookie_lifetime=None,
|
||||
certificates=None,
|
||||
redirect_http=None,
|
||||
sticky_sessions=None,
|
||||
):
|
||||
self.cookie_name = cookie_name
|
||||
self.cookie_lifetime = cookie_lifetime
|
||||
self.certificates = certificates
|
||||
self.redirect_http = redirect_http
|
||||
self.sticky_sessions = sticky_sessions
|
||||
|
||||
|
||||
class LoadBalancerHealthCheck(BaseDomain):
|
||||
"""LoadBalancerHealthCheck Domain
|
||||
|
||||
:param protocol: str
|
||||
Protocol of the service Choices: tcp, http, https
|
||||
:param port: int
|
||||
Port the healthcheck will be performed on
|
||||
:param interval: int
|
||||
Interval we trigger health check in
|
||||
:param timeout: int
|
||||
Timeout in sec after a try is assumed as timeout
|
||||
:param retries: int
|
||||
Retries we perform until we assume a target as unhealthy
|
||||
:param http: LoadBalancerHealtCheckHttp
|
||||
HTTP Config
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
protocol=None,
|
||||
port=None,
|
||||
interval=None,
|
||||
timeout=None,
|
||||
retries=None,
|
||||
http=None,
|
||||
):
|
||||
self.protocol = protocol
|
||||
self.port = port
|
||||
self.interval = interval
|
||||
self.timeout = timeout
|
||||
self.retries = retries
|
||||
self.http = http
|
||||
|
||||
|
||||
class LoadBalancerHealtCheckHttp(BaseDomain):
|
||||
"""LoadBalancerHealtCheckHttp Domain
|
||||
|
||||
:param domain: str
|
||||
Domain name to send in HTTP request. Can be null: In that case we will not send a domain name
|
||||
:param path: str
|
||||
HTTP Path send in Request
|
||||
:param response: str
|
||||
Optional HTTP response to receive in order to pass the health check
|
||||
:param status_codes: list
|
||||
List of HTTP status codes to receive in order to pass the health check
|
||||
:param tls: bool
|
||||
Type of health check
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, domain=None, path=None, response=None, status_codes=None, tls=None
|
||||
):
|
||||
self.domain = domain
|
||||
self.path = path
|
||||
self.response = response
|
||||
self.status_codes = status_codes
|
||||
self.tls = tls
|
||||
|
||||
|
||||
class LoadBalancerTarget(BaseDomain):
|
||||
"""LoadBalancerTarget Domain
|
||||
|
||||
:param type: str
|
||||
Type of the resource, can be server or label_selector
|
||||
:param server: Server
|
||||
Target server
|
||||
:param label_selector: LoadBalancerTargetLabelSelector
|
||||
Target label selector
|
||||
:param ip: LoadBalancerTargetIP
|
||||
Target IP
|
||||
:param use_private_ip: bool
|
||||
use the private IP instead of primary public IP
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, type=None, server=None, label_selector=None, ip=None, use_private_ip=None
|
||||
):
|
||||
self.type = type
|
||||
self.server = server
|
||||
self.label_selector = label_selector
|
||||
self.ip = ip
|
||||
self.use_private_ip = use_private_ip
|
||||
|
||||
|
||||
class LoadBalancerTargetLabelSelector(BaseDomain):
|
||||
"""LoadBalancerTargetLabelSelector Domain
|
||||
|
||||
:param selector: str Target label selector
|
||||
"""
|
||||
|
||||
def __init__(self, selector=None):
|
||||
self.selector = selector
|
||||
|
||||
|
||||
class LoadBalancerTargetIP(BaseDomain):
|
||||
"""LoadBalancerTargetIP Domain
|
||||
|
||||
:param ip: str Target IP
|
||||
"""
|
||||
|
||||
def __init__(self, ip=None):
|
||||
self.ip = ip
|
||||
|
||||
|
||||
class LoadBalancerAlgorithm(BaseDomain):
|
||||
"""LoadBalancerAlgorithm Domain
|
||||
|
||||
:param type: str
|
||||
Algorithm of the Load Balancer. Choices: round_robin, least_connections
|
||||
"""
|
||||
|
||||
def __init__(self, type=None):
|
||||
self.type = type
|
||||
|
||||
|
||||
class PublicNetwork(BaseDomain):
|
||||
"""Public Network Domain
|
||||
|
||||
:param ipv4: :class:`IPv4Address <hcloud.load_balancers.domain.IPv4Address>`
|
||||
:param ipv6: :class:`IPv6Network <hcloud.load_balancers.domain.IPv6Network>`
|
||||
:param enabled: boolean
|
||||
"""
|
||||
|
||||
__slots__ = ("ipv4", "ipv6", "enabled")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
ipv4, # type: IPv4Address
|
||||
ipv6, # type: IPv6Network
|
||||
enabled, # type: bool
|
||||
):
|
||||
self.ipv4 = ipv4
|
||||
self.ipv6 = ipv6
|
||||
self.enabled = enabled
|
||||
|
||||
|
||||
class IPv4Address(BaseDomain):
|
||||
"""IPv4 Address Domain
|
||||
|
||||
:param ip: str
|
||||
The IPv4 Address
|
||||
"""
|
||||
|
||||
__slots__ = ("ip", "dns_ptr")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
ip, # type: str
|
||||
dns_ptr, # type: str
|
||||
):
|
||||
self.ip = ip
|
||||
self.dns_ptr = dns_ptr
|
||||
|
||||
|
||||
class IPv6Network(BaseDomain):
|
||||
"""IPv6 Network Domain
|
||||
|
||||
:param ip: str
|
||||
The IPv6 Network as CIDR Notation
|
||||
"""
|
||||
|
||||
__slots__ = ("ip", "dns_ptr")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
ip, # type: str
|
||||
dns_ptr, # type: str
|
||||
):
|
||||
self.ip = ip
|
||||
self.dns_ptr = dns_ptr
|
||||
|
||||
|
||||
class PrivateNet(BaseDomain):
|
||||
"""PrivateNet Domain
|
||||
|
||||
:param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>`
|
||||
The Network the LoadBalancer is attached to
|
||||
:param ip: str
|
||||
The main IP Address of the LoadBalancer in the Network
|
||||
"""
|
||||
|
||||
__slots__ = ("network", "ip")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
network, # type: BoundNetwork
|
||||
ip, # type: str
|
||||
):
|
||||
self.network = network
|
||||
self.ip = ip
|
||||
|
||||
|
||||
class CreateLoadBalancerResponse(BaseDomain):
|
||||
"""Create Load Balancer Response Domain
|
||||
|
||||
:param load_balancer: :class:`BoundLoadBalancer <hcloud.load_balancers.client.BoundLoadBalancer>`
|
||||
The created Load Balancer
|
||||
:param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
Shows the progress of the Load Balancer creation
|
||||
"""
|
||||
|
||||
__slots__ = ("load_balancer", "action")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
load_balancer, # type: BoundLoadBalancer
|
||||
action, # type: BoundAction
|
||||
):
|
||||
self.load_balancer = load_balancer
|
||||
self.action = action
|
0
plugins/module_utils/vendor/hcloud/locations/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/locations/__init__.py
vendored
Normal file
67
plugins/module_utils/vendor/hcloud/locations/client.py
vendored
Normal file
67
plugins/module_utils/vendor/hcloud/locations/client.py
vendored
Normal file
|
@ -0,0 +1,67 @@
|
|||
from ..core.client import BoundModelBase, ClientEntityBase, GetEntityByNameMixin
|
||||
from .domain import Location
|
||||
|
||||
|
||||
class BoundLocation(BoundModelBase):
|
||||
model = Location
|
||||
|
||||
|
||||
class LocationsClient(ClientEntityBase, GetEntityByNameMixin):
|
||||
results_list_attribute_name = "locations"
|
||||
|
||||
def get_by_id(self, id):
|
||||
# type: (int) -> locations.client.BoundLocation
|
||||
"""Get a specific location by its ID.
|
||||
|
||||
:param id: int
|
||||
:return: :class:`BoundLocation <hcloud.locations.client.BoundLocation>`
|
||||
"""
|
||||
response = self._client.request(url=f"/locations/{id}", method="GET")
|
||||
return BoundLocation(self, response["location"])
|
||||
|
||||
def get_list(self, name=None, page=None, per_page=None):
|
||||
# type: (Optional[str], Optional[int], Optional[int]) -> PageResult[List[BoundLocation], Meta]
|
||||
"""Get a list of locations
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter locations by their name.
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundLocation <hcloud.locations.client.BoundLocation>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
if name is not None:
|
||||
params["name"] = name
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
|
||||
response = self._client.request(url="/locations", method="GET", params=params)
|
||||
locations = [
|
||||
BoundLocation(self, location_data)
|
||||
for location_data in response["locations"]
|
||||
]
|
||||
return self._add_meta_to_result(locations, response)
|
||||
|
||||
def get_all(self, name=None):
|
||||
# type: (Optional[str]) -> List[BoundLocation]
|
||||
"""Get all locations
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter locations by their name.
|
||||
:return: List[:class:`BoundLocation <hcloud.locations.client.BoundLocation>`]
|
||||
"""
|
||||
return super().get_all(name=name)
|
||||
|
||||
def get_by_name(self, name):
|
||||
# type: (str) -> BoundLocation
|
||||
"""Get location by name
|
||||
|
||||
:param name: str
|
||||
Used to get location by name.
|
||||
:return: :class:`BoundLocation <hcloud.locations.client.BoundLocation>`
|
||||
"""
|
||||
return super().get_by_name(name)
|
54
plugins/module_utils/vendor/hcloud/locations/domain.py
vendored
Normal file
54
plugins/module_utils/vendor/hcloud/locations/domain.py
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
from ..core.domain import BaseDomain, DomainIdentityMixin
|
||||
|
||||
|
||||
class Location(BaseDomain, DomainIdentityMixin):
|
||||
"""Location Domain
|
||||
|
||||
:param id: int
|
||||
ID of location
|
||||
:param name: str
|
||||
Name of location
|
||||
:param description: str
|
||||
Description of location
|
||||
:param country: str
|
||||
ISO 3166-1 alpha-2 code of the country the location resides in
|
||||
:param city: str
|
||||
City the location is closest to
|
||||
:param latitude: float
|
||||
Latitude of the city closest to the location
|
||||
:param longitude: float
|
||||
Longitude of the city closest to the location
|
||||
:param network_zone: str
|
||||
Name of network zone this location resides in
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"id",
|
||||
"name",
|
||||
"description",
|
||||
"country",
|
||||
"city",
|
||||
"latitude",
|
||||
"longitude",
|
||||
"network_zone",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id=None,
|
||||
name=None,
|
||||
description=None,
|
||||
country=None,
|
||||
city=None,
|
||||
latitude=None,
|
||||
longitude=None,
|
||||
network_zone=None,
|
||||
):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.country = country
|
||||
self.city = city
|
||||
self.latitude = latitude
|
||||
self.longitude = longitude
|
||||
self.network_zone = network_zone
|
0
plugins/module_utils/vendor/hcloud/networks/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/networks/__init__.py
vendored
Normal file
499
plugins/module_utils/vendor/hcloud/networks/client.py
vendored
Normal file
499
plugins/module_utils/vendor/hcloud/networks/client.py
vendored
Normal file
|
@ -0,0 +1,499 @@
|
|||
from ..actions.client import BoundAction
|
||||
from ..core.client import BoundModelBase, ClientEntityBase, GetEntityByNameMixin
|
||||
from ..core.domain import add_meta_to_result
|
||||
from .domain import Network, NetworkRoute, NetworkSubnet
|
||||
|
||||
|
||||
class BoundNetwork(BoundModelBase):
|
||||
model = Network
|
||||
|
||||
def __init__(self, client, data, complete=True):
|
||||
subnets = data.get("subnets", [])
|
||||
if subnets is not None:
|
||||
subnets = [NetworkSubnet.from_dict(subnet) for subnet in subnets]
|
||||
data["subnets"] = subnets
|
||||
|
||||
routes = data.get("routes", [])
|
||||
if routes is not None:
|
||||
routes = [NetworkRoute.from_dict(route) for route in routes]
|
||||
data["routes"] = routes
|
||||
|
||||
from ..servers.client import BoundServer
|
||||
|
||||
servers = data.get("servers", [])
|
||||
if servers is not None:
|
||||
servers = [
|
||||
BoundServer(client._client.servers, {"id": server}, complete=False)
|
||||
for server in servers
|
||||
]
|
||||
data["servers"] = servers
|
||||
|
||||
super().__init__(client, data, complete)
|
||||
|
||||
def update(
|
||||
self,
|
||||
name=None, # type: Optional[str]
|
||||
expose_routes_to_vswitch=None, # type: Optional[bool]
|
||||
labels=None, # type: Optional[Dict[str, str]]
|
||||
): # type: (...) -> BoundNetwork
|
||||
"""Updates a network. You can update a network’s name and a networks’s labels.
|
||||
|
||||
:param name: str (optional)
|
||||
New name to set
|
||||
:param expose_routes_to_vswitch: Optional[bool]
|
||||
Indicates if the routes from this network should be exposed to the vSwitch connection.
|
||||
The exposing only takes effect if a vSwitch connection is active.
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:return: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>`
|
||||
"""
|
||||
return self._client.update(
|
||||
self,
|
||||
name=name,
|
||||
expose_routes_to_vswitch=expose_routes_to_vswitch,
|
||||
labels=labels,
|
||||
)
|
||||
|
||||
def delete(self):
|
||||
# type: () -> BoundAction
|
||||
"""Deletes a network.
|
||||
|
||||
:return: boolean
|
||||
"""
|
||||
return self._client.delete(self)
|
||||
|
||||
def get_actions_list(self, status=None, sort=None, page=None, per_page=None):
|
||||
# type: (Optional[List[str]], Optional[List[str]], Optional[int], Optional[int]) -> PageResults[List[BoundAction, Meta]]
|
||||
"""Returns all action objects for a network.
|
||||
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
return self._client.get_actions_list(self, status, sort, page, per_page)
|
||||
|
||||
def get_actions(self, status=None, sort=None):
|
||||
# type: (Optional[List[str]], Optional[List[str]]) -> List[BoundAction]
|
||||
"""Returns all action objects for a network.
|
||||
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
return self._client.get_actions(self, status, sort)
|
||||
|
||||
def add_subnet(self, subnet):
|
||||
# type: (NetworkSubnet) -> List[BoundAction]
|
||||
"""Adds a subnet entry to a network.
|
||||
|
||||
:param subnet: :class:`NetworkSubnet <hcloud.networks.domain.NetworkSubnet>`
|
||||
The NetworkSubnet you want to add to the Network
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.add_subnet(self, subnet=subnet)
|
||||
|
||||
def delete_subnet(self, subnet):
|
||||
# type: (NetworkSubnet) -> List[BoundAction]
|
||||
"""Removes a subnet entry from a network
|
||||
|
||||
:param subnet: :class:`NetworkSubnet <hcloud.networks.domain.NetworkSubnet>`
|
||||
The NetworkSubnet you want to remove from the Network
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.delete_subnet(self, subnet=subnet)
|
||||
|
||||
def add_route(self, route):
|
||||
# type: (NetworkRoute) -> List[BoundAction]
|
||||
"""Adds a route entry to a network.
|
||||
|
||||
:param route: :class:`NetworkRoute <hcloud.networks.domain.NetworkRoute>`
|
||||
The NetworkRoute you want to add to the Network
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.add_route(self, route=route)
|
||||
|
||||
def delete_route(self, route):
|
||||
# type: (NetworkRoute) -> List[BoundAction]
|
||||
"""Removes a route entry to a network.
|
||||
|
||||
:param route: :class:`NetworkRoute <hcloud.networks.domain.NetworkRoute>`
|
||||
The NetworkRoute you want to remove from the Network
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.delete_route(self, route=route)
|
||||
|
||||
def change_ip_range(self, ip_range):
|
||||
# type: (str) -> List[BoundAction]
|
||||
"""Changes the IP range of a network.
|
||||
|
||||
:param ip_range: str
|
||||
The new prefix for the whole network.
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.change_ip_range(self, ip_range=ip_range)
|
||||
|
||||
def change_protection(self, delete=None):
|
||||
# type: (Optional[bool]) -> BoundAction
|
||||
"""Changes the protection configuration of a network.
|
||||
|
||||
:param delete: boolean
|
||||
If True, prevents the network from being deleted
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.change_protection(self, delete=delete)
|
||||
|
||||
|
||||
class NetworksClient(ClientEntityBase, GetEntityByNameMixin):
|
||||
results_list_attribute_name = "networks"
|
||||
|
||||
def get_by_id(self, id):
|
||||
# type: (int) -> BoundNetwork
|
||||
"""Get a specific network
|
||||
|
||||
:param id: int
|
||||
:return: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>
|
||||
"""
|
||||
response = self._client.request(url=f"/networks/{id}", method="GET")
|
||||
return BoundNetwork(self, response["network"])
|
||||
|
||||
def get_list(
|
||||
self,
|
||||
name=None, # type: Optional[str]
|
||||
label_selector=None, # type: Optional[str]
|
||||
page=None, # type: Optional[int]
|
||||
per_page=None, # type: Optional[int]
|
||||
):
|
||||
# type: (...) -> PageResults[List[BoundNetwork], Meta]
|
||||
"""Get a list of networks from this account
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter networks by their name.
|
||||
:param label_selector: str (optional)
|
||||
Can be used to filter networks by labels. The response will only contain networks matching the label selector.
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundNetwork <hcloud.networks.client.BoundNetwork>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
if name is not None:
|
||||
params["name"] = name
|
||||
if label_selector is not None:
|
||||
params["label_selector"] = label_selector
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
|
||||
response = self._client.request(url="/networks", method="GET", params=params)
|
||||
|
||||
ass_networks = [
|
||||
BoundNetwork(self, network_data) for network_data in response["networks"]
|
||||
]
|
||||
return self._add_meta_to_result(ass_networks, response)
|
||||
|
||||
def get_all(self, name=None, label_selector=None):
|
||||
# type: (Optional[str], Optional[str]) -> List[BoundNetwork]
|
||||
"""Get all networks from this account
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter networks by their name.
|
||||
:param label_selector: str (optional)
|
||||
Can be used to filter networks by labels. The response will only contain networks matching the label selector.
|
||||
:return: List[:class:`BoundNetwork <hcloud.networks.client.BoundNetwork>`]
|
||||
"""
|
||||
return super().get_all(name=name, label_selector=label_selector)
|
||||
|
||||
def get_by_name(self, name):
|
||||
# type: (str) -> BoundNetwork
|
||||
"""Get network by name
|
||||
|
||||
:param name: str
|
||||
Used to get network by name.
|
||||
:return: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>`
|
||||
"""
|
||||
return super().get_by_name(name)
|
||||
|
||||
def create(
|
||||
self,
|
||||
name, # type: str
|
||||
ip_range, # type: str
|
||||
subnets=None, # type: Optional[List[NetworkSubnet]]
|
||||
routes=None, # type: Optional[List[NetworkRoute]]
|
||||
expose_routes_to_vswitch=None, # type: Optional[bool]
|
||||
labels=None, # type: Optional[Dict[str, str]]
|
||||
):
|
||||
"""Creates a network with range ip_range.
|
||||
|
||||
:param name: str
|
||||
Name of the network
|
||||
:param ip_range: str
|
||||
IP range of the whole network which must span all included subnets and route destinations
|
||||
:param subnets: List[:class:`NetworkSubnet <hcloud.networks.domain.NetworkSubnet>`]
|
||||
Array of subnets allocated
|
||||
:param routes: List[:class:`NetworkRoute <hcloud.networks.domain.NetworkRoute>`]
|
||||
Array of routes set in this network
|
||||
:param expose_routes_to_vswitch: Optional[bool]
|
||||
Indicates if the routes from this network should be exposed to the vSwitch connection.
|
||||
The exposing only takes effect if a vSwitch connection is active.
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:return: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>`
|
||||
"""
|
||||
data = {"name": name, "ip_range": ip_range}
|
||||
if subnets is not None:
|
||||
data_subnets = []
|
||||
for subnet in subnets:
|
||||
data_subnet = {
|
||||
"type": subnet.type,
|
||||
"ip_range": subnet.ip_range,
|
||||
"network_zone": subnet.network_zone,
|
||||
}
|
||||
if subnet.vswitch_id is not None:
|
||||
data_subnet["vswitch_id"] = subnet.vswitch_id
|
||||
|
||||
data_subnets.append(data_subnet)
|
||||
data["subnets"] = data_subnets
|
||||
|
||||
if routes is not None:
|
||||
data["routes"] = [
|
||||
{"destination": route.destination, "gateway": route.gateway}
|
||||
for route in routes
|
||||
]
|
||||
|
||||
if expose_routes_to_vswitch is not None:
|
||||
data["expose_routes_to_vswitch"] = expose_routes_to_vswitch
|
||||
|
||||
if labels is not None:
|
||||
data["labels"] = labels
|
||||
|
||||
response = self._client.request(url="/networks", method="POST", json=data)
|
||||
|
||||
return BoundNetwork(self, response["network"])
|
||||
|
||||
def update(self, network, name=None, expose_routes_to_vswitch=None, labels=None):
|
||||
# type:(Network, Optional[str], Optional[bool], Optional[Dict[str, str]]) -> BoundNetwork
|
||||
"""Updates a network. You can update a network’s name and a network’s labels.
|
||||
|
||||
:param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
|
||||
:param name: str (optional)
|
||||
New name to set
|
||||
:param expose_routes_to_vswitch: Optional[bool]
|
||||
Indicates if the routes from this network should be exposed to the vSwitch connection.
|
||||
The exposing only takes effect if a vSwitch connection is active.
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:return: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>`
|
||||
"""
|
||||
data = {}
|
||||
if name is not None:
|
||||
data.update({"name": name})
|
||||
|
||||
if expose_routes_to_vswitch is not None:
|
||||
data["expose_routes_to_vswitch"] = expose_routes_to_vswitch
|
||||
|
||||
if labels is not None:
|
||||
data.update({"labels": labels})
|
||||
|
||||
response = self._client.request(
|
||||
url=f"/networks/{network.id}",
|
||||
method="PUT",
|
||||
json=data,
|
||||
)
|
||||
return BoundNetwork(self, response["network"])
|
||||
|
||||
def delete(self, network):
|
||||
# type: (Network) -> BoundAction
|
||||
"""Deletes a network.
|
||||
|
||||
:param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
|
||||
:return: boolean
|
||||
"""
|
||||
self._client.request(url=f"/networks/{network.id}", method="DELETE")
|
||||
return True
|
||||
|
||||
def get_actions_list(
|
||||
self, network, status=None, sort=None, page=None, per_page=None
|
||||
):
|
||||
# type: (Network, Optional[List[str]], Optional[List[str]], Optional[int], Optional[int]) -> PageResults[List[BoundAction], Meta]
|
||||
"""Returns all action objects for a network.
|
||||
|
||||
:param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
if status is not None:
|
||||
params["status"] = status
|
||||
if sort is not None:
|
||||
params["sort"] = sort
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
|
||||
response = self._client.request(
|
||||
url=f"/networks/{network.id}/actions",
|
||||
method="GET",
|
||||
params=params,
|
||||
)
|
||||
actions = [
|
||||
BoundAction(self._client.actions, action_data)
|
||||
for action_data in response["actions"]
|
||||
]
|
||||
return add_meta_to_result(actions, response, "actions")
|
||||
|
||||
def get_actions(self, network, status=None, sort=None):
|
||||
# type: (Network, Optional[List[str]], Optional[List[str]]) -> List[BoundAction]
|
||||
"""Returns all action objects for a network.
|
||||
|
||||
:param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
return super().get_actions(network, status=status, sort=sort)
|
||||
|
||||
def add_subnet(self, network, subnet):
|
||||
# type: (Union[Network, BoundNetwork], NetworkSubnet) -> List[BoundAction]
|
||||
"""Adds a subnet entry to a network.
|
||||
|
||||
:param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
|
||||
:param subnet: :class:`NetworkSubnet <hcloud.networks.domain.NetworkSubnet>`
|
||||
The NetworkSubnet you want to add to the Network
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {"type": subnet.type, "network_zone": subnet.network_zone}
|
||||
if subnet.ip_range is not None:
|
||||
data["ip_range"] = subnet.ip_range
|
||||
if subnet.vswitch_id is not None:
|
||||
data["vswitch_id"] = subnet.vswitch_id
|
||||
|
||||
response = self._client.request(
|
||||
url="/networks/{network_id}/actions/add_subnet".format(
|
||||
network_id=network.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def delete_subnet(self, network, subnet):
|
||||
# type: (Union[Network, BoundNetwork], NetworkSubnet) -> List[BoundAction]
|
||||
"""Removes a subnet entry from a network
|
||||
|
||||
:param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
|
||||
:param subnet: :class:`NetworkSubnet <hcloud.networks.domain.NetworkSubnet>`
|
||||
The NetworkSubnet you want to remove from the Network
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {"ip_range": subnet.ip_range}
|
||||
|
||||
response = self._client.request(
|
||||
url="/networks/{network_id}/actions/delete_subnet".format(
|
||||
network_id=network.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def add_route(self, network, route):
|
||||
# type: (Union[Network, BoundNetwork], NetworkRoute) -> List[BoundAction]
|
||||
"""Adds a route entry to a network.
|
||||
|
||||
:param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
|
||||
:param route: :class:`NetworkRoute <hcloud.networks.domain.NetworkRoute>`
|
||||
The NetworkRoute you want to add to the Network
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {"destination": route.destination, "gateway": route.gateway}
|
||||
|
||||
response = self._client.request(
|
||||
url="/networks/{network_id}/actions/add_route".format(
|
||||
network_id=network.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def delete_route(self, network, route):
|
||||
# type: (Union[Network, BoundNetwork], NetworkRoute) -> List[BoundAction]
|
||||
"""Removes a route entry to a network.
|
||||
|
||||
:param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
|
||||
:param route: :class:`NetworkRoute <hcloud.networks.domain.NetworkRoute>`
|
||||
The NetworkRoute you want to remove from the Network
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {"destination": route.destination, "gateway": route.gateway}
|
||||
|
||||
response = self._client.request(
|
||||
url="/networks/{network_id}/actions/delete_route".format(
|
||||
network_id=network.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def change_ip_range(self, network, ip_range):
|
||||
# type: (Union[Network, BoundNetwork], str) -> List[BoundAction]
|
||||
"""Changes the IP range of a network.
|
||||
|
||||
:param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
|
||||
:param ip_range: str
|
||||
The new prefix for the whole network.
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {"ip_range": ip_range}
|
||||
|
||||
response = self._client.request(
|
||||
url="/networks/{network_id}/actions/change_ip_range".format(
|
||||
network_id=network.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def change_protection(self, network, delete=None):
|
||||
# type: (Union[Network, BoundNetwork], Optional[bool]) -> BoundAction
|
||||
"""Changes the protection configuration of a network.
|
||||
|
||||
:param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>` or :class:`Network <hcloud.networks.domain.Network>`
|
||||
:param delete: boolean
|
||||
If True, prevents the network from being deleted
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {}
|
||||
if delete is not None:
|
||||
data.update({"delete": delete})
|
||||
|
||||
response = self._client.request(
|
||||
url="/networks/{network_id}/actions/change_protection".format(
|
||||
network_id=network.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
136
plugins/module_utils/vendor/hcloud/networks/domain.py
vendored
Normal file
136
plugins/module_utils/vendor/hcloud/networks/domain.py
vendored
Normal file
|
@ -0,0 +1,136 @@
|
|||
try:
|
||||
from dateutil.parser import isoparse
|
||||
except ImportError:
|
||||
isoparse = None
|
||||
|
||||
from ..core.domain import BaseDomain
|
||||
|
||||
|
||||
class Network(BaseDomain):
|
||||
"""Network Domain
|
||||
|
||||
:param id: int
|
||||
ID of the network
|
||||
:param name: str
|
||||
Name of the network
|
||||
:param ip_range: str
|
||||
IPv4 prefix of the whole network
|
||||
:param subnets: List[:class:`NetworkSubnet <hcloud.networks.domain.NetworkSubnet>`]
|
||||
Subnets allocated in this network
|
||||
:param routes: List[:class:`NetworkRoute <hcloud.networks.domain.NetworkRoute>`]
|
||||
Routes set in this network
|
||||
:param expose_routes_to_vswitch: bool
|
||||
Indicates if the routes from this network should be exposed to the vSwitch connection.
|
||||
:param servers: List[:class:`BoundServer <hcloud.servers.client.BoundServer>`]
|
||||
Servers attached to this network
|
||||
:param protection: dict
|
||||
Protection configuration for the network
|
||||
:param labels: dict
|
||||
User-defined labels (key-value pairs)
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"id",
|
||||
"name",
|
||||
"ip_range",
|
||||
"subnets",
|
||||
"routes",
|
||||
"expose_routes_to_vswitch",
|
||||
"servers",
|
||||
"protection",
|
||||
"labels",
|
||||
"created",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id,
|
||||
name=None,
|
||||
created=None,
|
||||
ip_range=None,
|
||||
subnets=None,
|
||||
routes=None,
|
||||
expose_routes_to_vswitch=None,
|
||||
servers=None,
|
||||
protection=None,
|
||||
labels=None,
|
||||
):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.created = isoparse(created) if created else None
|
||||
self.ip_range = ip_range
|
||||
self.subnets = subnets
|
||||
self.routes = routes
|
||||
self.expose_routes_to_vswitch = expose_routes_to_vswitch
|
||||
self.servers = servers
|
||||
self.protection = protection
|
||||
self.labels = labels
|
||||
|
||||
|
||||
class NetworkSubnet(BaseDomain):
|
||||
"""Network Subnet Domain
|
||||
|
||||
:param type: str
|
||||
Type of sub network.
|
||||
:param ip_range: str
|
||||
Range to allocate IPs from.
|
||||
:param network_zone: str
|
||||
Name of network zone.
|
||||
:param gateway: str
|
||||
Gateway for the route.
|
||||
:param vswitch_id: int
|
||||
ID of the vSwitch.
|
||||
"""
|
||||
|
||||
TYPE_SERVER = "server"
|
||||
"""Subnet Type server, deprecated, use TYPE_CLOUD instead"""
|
||||
TYPE_CLOUD = "cloud"
|
||||
"""Subnet Type cloud"""
|
||||
TYPE_VSWITCH = "vswitch"
|
||||
"""Subnet Type vSwitch"""
|
||||
__slots__ = ("type", "ip_range", "network_zone", "gateway", "vswitch_id")
|
||||
|
||||
def __init__(
|
||||
self, ip_range, type=None, network_zone=None, gateway=None, vswitch_id=None
|
||||
):
|
||||
self.type = type
|
||||
self.ip_range = ip_range
|
||||
self.network_zone = network_zone
|
||||
self.gateway = gateway
|
||||
self.vswitch_id = vswitch_id
|
||||
|
||||
|
||||
class NetworkRoute(BaseDomain):
|
||||
"""Network Route Domain
|
||||
|
||||
:param destination: str
|
||||
Destination network or host of this route.
|
||||
:param gateway: str
|
||||
Gateway for the route.
|
||||
"""
|
||||
|
||||
__slots__ = ("destination", "gateway")
|
||||
|
||||
def __init__(self, destination, gateway):
|
||||
self.destination = destination
|
||||
self.gateway = gateway
|
||||
|
||||
|
||||
class CreateNetworkResponse(BaseDomain):
|
||||
"""Create Network Response Domain
|
||||
|
||||
:param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>`
|
||||
The network which was created
|
||||
:param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
The Action which shows the progress of the network Creation
|
||||
"""
|
||||
|
||||
__slots__ = ("network", "action")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
network, # type: BoundNetwork
|
||||
action, # type: BoundAction
|
||||
):
|
||||
self.network = network
|
||||
self.action = action
|
0
plugins/module_utils/vendor/hcloud/placement_groups/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/placement_groups/__init__.py
vendored
Normal file
194
plugins/module_utils/vendor/hcloud/placement_groups/client.py
vendored
Normal file
194
plugins/module_utils/vendor/hcloud/placement_groups/client.py
vendored
Normal file
|
@ -0,0 +1,194 @@
|
|||
from ..actions.client import BoundAction
|
||||
from ..core.client import BoundModelBase, ClientEntityBase, GetEntityByNameMixin
|
||||
from .domain import CreatePlacementGroupResponse, PlacementGroup
|
||||
|
||||
|
||||
class BoundPlacementGroup(BoundModelBase):
|
||||
model = PlacementGroup
|
||||
|
||||
def update(self, labels=None, name=None):
|
||||
# type: (Optional[str], Optional[Dict[str, str]], Optional[str]) -> BoundPlacementGroup
|
||||
"""Updates the name or labels of a Placement Group
|
||||
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:param name: str, (optional)
|
||||
New Name to set
|
||||
:return: :class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>`
|
||||
"""
|
||||
return self._client.update(self, labels, name)
|
||||
|
||||
def delete(self):
|
||||
# type: () -> bool
|
||||
"""Deletes a Placement Group
|
||||
|
||||
:return: boolean
|
||||
"""
|
||||
return self._client.delete(self)
|
||||
|
||||
|
||||
class PlacementGroupsClient(ClientEntityBase, GetEntityByNameMixin):
|
||||
results_list_attribute_name = "placement_groups"
|
||||
|
||||
def get_by_id(self, id):
|
||||
# type: (int) -> BoundPlacementGroup
|
||||
"""Returns a specific Placement Group object
|
||||
|
||||
:param id: int
|
||||
:return: :class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>`
|
||||
"""
|
||||
response = self._client.request(
|
||||
url=f"/placement_groups/{id}",
|
||||
method="GET",
|
||||
)
|
||||
return BoundPlacementGroup(self, response["placement_group"])
|
||||
|
||||
def get_list(
|
||||
self,
|
||||
label_selector=None, # type: Optional[str]
|
||||
page=None, # type: Optional[int]
|
||||
per_page=None, # type: Optional[int]
|
||||
name=None, # type: Optional[str]
|
||||
sort=None, # type: Optional[List[str]]
|
||||
type=None, # type: Optional[str]
|
||||
):
|
||||
# type: (...) -> PageResults[List[BoundPlacementGroup]]
|
||||
"""Get a list of Placement Groups
|
||||
|
||||
:param label_selector: str (optional)
|
||||
Can be used to filter Placement Groups by labels. The response will only contain Placement Groups matching the label selector values.
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:param name: str (optional)
|
||||
Can be used to filter Placement Groups by their name.
|
||||
:param sort: List[str] (optional)
|
||||
Choices: id name created (You can add one of ":asc", ":desc" to modify sort order. ( ":asc" is default))
|
||||
:return: (List[:class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
|
||||
params = {}
|
||||
|
||||
if label_selector is not None:
|
||||
params["label_selector"] = label_selector
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
if name is not None:
|
||||
params["name"] = name
|
||||
if sort is not None:
|
||||
params["sort"] = sort
|
||||
if type is not None:
|
||||
params["type"] = type
|
||||
response = self._client.request(
|
||||
url="/placement_groups", method="GET", params=params
|
||||
)
|
||||
placement_groups = [
|
||||
BoundPlacementGroup(self, placement_group_data)
|
||||
for placement_group_data in response["placement_groups"]
|
||||
]
|
||||
|
||||
return self._add_meta_to_result(placement_groups, response)
|
||||
|
||||
def get_all(self, label_selector=None, name=None, sort=None):
|
||||
# type: (Optional[str], Optional[str], Optional[List[str]]) -> List[BoundPlacementGroup]
|
||||
"""Get all Placement Groups
|
||||
|
||||
:param label_selector: str (optional)
|
||||
Can be used to filter Placement Groups by labels. The response will only contain Placement Groups matching the label selector values.
|
||||
:param name: str (optional)
|
||||
Can be used to filter Placement Groups by their name.
|
||||
:param sort: List[str] (optional)
|
||||
Choices: id name created (You can add one of ":asc", ":desc" to modify sort order. ( ":asc" is default))
|
||||
:return: List[:class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>`]
|
||||
"""
|
||||
return super().get_all(label_selector=label_selector, name=name, sort=sort)
|
||||
|
||||
def get_by_name(self, name):
|
||||
# type: (str) -> BoundPlacementGroup
|
||||
"""Get Placement Group by name
|
||||
|
||||
:param name: str
|
||||
Used to get Placement Group by name
|
||||
:return: class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>`
|
||||
"""
|
||||
return super().get_by_name(name)
|
||||
|
||||
def create(
|
||||
self,
|
||||
name, # type: str
|
||||
type, # type: str
|
||||
labels=None, # type: Optional[Dict[str, str]]
|
||||
):
|
||||
# type: (...) -> CreatePlacementGroupResponse
|
||||
"""Creates a new Placement Group.
|
||||
|
||||
:param name: str
|
||||
Placement Group Name
|
||||
:param type: str
|
||||
Type of the Placement Group
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
|
||||
:return: :class:`CreatePlacementGroupResponse <hcloud.placement_groups.domain.CreatePlacementGroupResponse>`
|
||||
"""
|
||||
data = {"name": name, "type": type}
|
||||
if labels is not None:
|
||||
data["labels"] = labels
|
||||
response = self._client.request(
|
||||
url="/placement_groups", json=data, method="POST"
|
||||
)
|
||||
|
||||
action = None
|
||||
if response.get("action") is not None:
|
||||
action = BoundAction(self._client.action, response["action"])
|
||||
|
||||
result = CreatePlacementGroupResponse(
|
||||
placement_group=BoundPlacementGroup(self, response["placement_group"]),
|
||||
action=action,
|
||||
)
|
||||
return result
|
||||
|
||||
def update(self, placement_group, labels=None, name=None):
|
||||
# type: (PlacementGroup, Optional[Dict[str, str]], Optional[str]) -> BoundPlacementGroup
|
||||
"""Updates the description or labels of a Placement Group.
|
||||
|
||||
:param placement_group: :class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>` or :class:`PlacementGroup <hcloud.placement_groups.domain.PlacementGroup>`
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:param name: str (optional)
|
||||
New name to set
|
||||
:return: :class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>`
|
||||
"""
|
||||
|
||||
data = {}
|
||||
if labels is not None:
|
||||
data["labels"] = labels
|
||||
if name is not None:
|
||||
data["name"] = name
|
||||
|
||||
response = self._client.request(
|
||||
url="/placement_groups/{placement_group_id}".format(
|
||||
placement_group_id=placement_group.id
|
||||
),
|
||||
method="PUT",
|
||||
json=data,
|
||||
)
|
||||
return BoundPlacementGroup(self, response["placement_group"])
|
||||
|
||||
def delete(self, placement_group):
|
||||
# type: (PlacementGroup) -> bool
|
||||
"""Deletes a Placement Group.
|
||||
|
||||
:param placement_group: :class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>` or :class:`PlacementGroup <hcloud.placement_groups.domain.PlacementGroup>`
|
||||
:return: boolean
|
||||
"""
|
||||
self._client.request(
|
||||
url="/placement_groups/{placement_group_id}".format(
|
||||
placement_group_id=placement_group.id
|
||||
),
|
||||
method="DELETE",
|
||||
)
|
||||
return True
|
61
plugins/module_utils/vendor/hcloud/placement_groups/domain.py
vendored
Normal file
61
plugins/module_utils/vendor/hcloud/placement_groups/domain.py
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
try:
|
||||
from dateutil.parser import isoparse
|
||||
except ImportError:
|
||||
isoparse = None
|
||||
|
||||
from ..core.domain import BaseDomain
|
||||
|
||||
|
||||
class PlacementGroup(BaseDomain):
|
||||
"""Placement Group Domain
|
||||
|
||||
:param id: int
|
||||
ID of the Placement Group
|
||||
:param name: str
|
||||
Name of the Placement Group
|
||||
:param labels: dict
|
||||
User-defined labels (key-value pairs)
|
||||
:param servers: List[ int ]
|
||||
List of server IDs assigned to the Placement Group
|
||||
:param type: str
|
||||
Type of the Placement Group
|
||||
:param created: datetime
|
||||
Point in time when the image was created
|
||||
"""
|
||||
|
||||
__slots__ = ("id", "name", "labels", "servers", "type", "created")
|
||||
|
||||
"""Placement Group type spread
|
||||
spreads all servers in the group on different vhosts
|
||||
"""
|
||||
TYPE_SPREAD = "spread"
|
||||
|
||||
def __init__(
|
||||
self, id=None, name=None, labels=None, servers=None, type=None, created=None
|
||||
):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.labels = labels
|
||||
self.servers = servers
|
||||
self.type = type
|
||||
self.created = isoparse(created) if created else None
|
||||
|
||||
|
||||
class CreatePlacementGroupResponse(BaseDomain):
|
||||
"""Create Placement Group Response Domain
|
||||
|
||||
:param placement_group: :class:`BoundPlacementGroup <hcloud.placement_groups.client.BoundPlacementGroup>`
|
||||
The Placement Group which was created
|
||||
:param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
The Action which shows the progress of the Placement Group Creation
|
||||
"""
|
||||
|
||||
__slots__ = ("placement_group", "action")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
placement_group, # type: BoundPlacementGroup
|
||||
action, # type: BoundAction
|
||||
):
|
||||
self.placement_group = placement_group
|
||||
self.action = action
|
0
plugins/module_utils/vendor/hcloud/primary_ips/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/primary_ips/__init__.py
vendored
Normal file
329
plugins/module_utils/vendor/hcloud/primary_ips/client.py
vendored
Normal file
329
plugins/module_utils/vendor/hcloud/primary_ips/client.py
vendored
Normal file
|
@ -0,0 +1,329 @@
|
|||
from ..actions.client import BoundAction
|
||||
from ..core.client import BoundModelBase, ClientEntityBase, GetEntityByNameMixin
|
||||
from .domain import CreatePrimaryIPResponse, PrimaryIP
|
||||
|
||||
|
||||
class BoundPrimaryIP(BoundModelBase):
|
||||
model = PrimaryIP
|
||||
|
||||
def __init__(self, client, data, complete=True):
|
||||
from ..datacenters.client import BoundDatacenter
|
||||
|
||||
datacenter = data.get("datacenter", {})
|
||||
if datacenter:
|
||||
data["datacenter"] = BoundDatacenter(client._client.datacenters, datacenter)
|
||||
|
||||
super().__init__(client, data, complete)
|
||||
|
||||
def update(self, auto_delete=None, labels=None, name=None):
|
||||
# type: (Optional[bool], Optional[Dict[str, str]], Optional[str]) -> BoundPrimaryIP
|
||||
"""Updates the description or labels of a Primary IP.
|
||||
|
||||
:param auto_delete: bool (optional)
|
||||
Auto delete IP when assignee gets deleted
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:param name: str (optional)
|
||||
New Name to set
|
||||
:return: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>`
|
||||
"""
|
||||
return self._client.update(
|
||||
self, auto_delete=auto_delete, labels=labels, name=name
|
||||
)
|
||||
|
||||
def delete(self):
|
||||
# type: () -> bool
|
||||
"""Deletes a Primary IP. If it is currently assigned to a server it will automatically get unassigned.
|
||||
|
||||
:return: boolean
|
||||
"""
|
||||
return self._client.delete(self)
|
||||
|
||||
def change_protection(self, delete=None):
|
||||
# type: (Optional[bool]) -> BoundAction
|
||||
"""Changes the protection configuration of the Primary IP.
|
||||
|
||||
:param delete: boolean
|
||||
If true, prevents the Primary IP from being deleted
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.change_protection(self, delete)
|
||||
|
||||
def assign(self, assignee_id, assignee_type):
|
||||
# type: (int,str) -> BoundAction
|
||||
"""Assigns a Primary IP to a assignee.
|
||||
|
||||
:param assignee_id: int`
|
||||
Id of an assignee the Primary IP shall be assigned to
|
||||
:param assignee_type: string`
|
||||
Assignee type (e.g server) the Primary IP shall be assigned to
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.assign(self, assignee_id, assignee_type)
|
||||
|
||||
def unassign(self):
|
||||
# type: () -> BoundAction
|
||||
"""Unassigns a Primary IP, resulting in it being unreachable. You may assign it to a server again at a later time.
|
||||
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.unassign(self)
|
||||
|
||||
def change_dns_ptr(self, ip, dns_ptr):
|
||||
# type: (str, str) -> BoundAction
|
||||
"""Changes the hostname that will appear when getting the hostname belonging to this Primary IP.
|
||||
|
||||
:param ip: str
|
||||
The IP address for which to set the reverse DNS entry
|
||||
:param dns_ptr: str
|
||||
Hostname to set as a reverse DNS PTR entry, will reset to original default value if `None`
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.change_dns_ptr(self, ip, dns_ptr)
|
||||
|
||||
|
||||
class PrimaryIPsClient(ClientEntityBase, GetEntityByNameMixin):
|
||||
results_list_attribute_name = "primary_ips"
|
||||
|
||||
def get_by_id(self, id):
|
||||
# type: (int) -> BoundPrimaryIP
|
||||
"""Returns a specific Primary IP object.
|
||||
|
||||
:param id: int
|
||||
:return: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>`
|
||||
"""
|
||||
response = self._client.request(url=f"/primary_ips/{id}", method="GET")
|
||||
return BoundPrimaryIP(self, response["primary_ip"])
|
||||
|
||||
def get_list(
|
||||
self,
|
||||
label_selector=None, # type: Optional[str]
|
||||
page=None, # type: Optional[int]
|
||||
per_page=None, # type: Optional[int]
|
||||
name=None, # type: Optional[str]
|
||||
ip=None, # type: Optional[ip]
|
||||
):
|
||||
# type: (...) -> PageResults[List[BoundPrimaryIP]]
|
||||
"""Get a list of primary ips from this account
|
||||
|
||||
:param label_selector: str (optional)
|
||||
Can be used to filter Primary IPs by labels. The response will only contain Primary IPs matching the label selectorable values.
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:param name: str (optional)
|
||||
Can be used to filter networks by their name.
|
||||
:param ip: str (optional)
|
||||
Can be used to filter resources by their ip. The response will only contain the resources matching the specified ip.
|
||||
:return: (List[:class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
|
||||
if label_selector is not None:
|
||||
params["label_selector"] = label_selector
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
if name is not None:
|
||||
params["name"] = name
|
||||
if ip is not None:
|
||||
params["ip"] = ip
|
||||
|
||||
response = self._client.request(url="/primary_ips", method="GET", params=params)
|
||||
primary_ips = [
|
||||
BoundPrimaryIP(self, primary_ip_data)
|
||||
for primary_ip_data in response["primary_ips"]
|
||||
]
|
||||
|
||||
return self._add_meta_to_result(primary_ips, response)
|
||||
|
||||
def get_all(self, label_selector=None, name=None):
|
||||
# type: (Optional[str], Optional[str]) -> List[BoundPrimaryIP]
|
||||
"""Get all primary ips from this account
|
||||
|
||||
:param label_selector: str (optional)
|
||||
Can be used to filter Primary IPs by labels. The response will only contain Primary IPs matching the label selector.able values.
|
||||
:param name: str (optional)
|
||||
Can be used to filter networks by their name.
|
||||
:return: List[:class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>`]
|
||||
"""
|
||||
return super().get_all(label_selector=label_selector, name=name)
|
||||
|
||||
def get_by_name(self, name):
|
||||
# type: (str) -> BoundPrimaryIP
|
||||
"""Get Primary IP by name
|
||||
|
||||
:param name: str
|
||||
Used to get Primary IP by name.
|
||||
:return: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>`
|
||||
"""
|
||||
return super().get_by_name(name)
|
||||
|
||||
def create(
|
||||
self,
|
||||
type, # type: str
|
||||
datacenter, # type: Datacenter
|
||||
name, # type: str
|
||||
assignee_type="server", # type: Optional[str]
|
||||
assignee_id=None, # type: Optional[int]
|
||||
auto_delete=False, # type: Optional[bool]
|
||||
labels=None, # type: Optional[dict]
|
||||
):
|
||||
# type: (...) -> CreatePrimaryIPResponse
|
||||
"""Creates a new Primary IP assigned to a server.
|
||||
|
||||
:param type: str
|
||||
Primary IP type Choices: ipv4, ipv6
|
||||
:param assignee_type: str
|
||||
:param assignee_id: int (optional)
|
||||
:param datacenter: Datacenter
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:param name: str
|
||||
:param auto_delete: bool (optional)
|
||||
:return: :class:`CreatePrimaryIPResponse <hcloud.primary_ips.domain.CreatePrimaryIPResponse>`
|
||||
"""
|
||||
|
||||
data = {
|
||||
"type": type,
|
||||
"assignee_type": assignee_type,
|
||||
"auto_delete": auto_delete,
|
||||
"datacenter": datacenter.id_or_name,
|
||||
"name": name,
|
||||
}
|
||||
if assignee_id:
|
||||
data["assignee_id"] = assignee_id
|
||||
if labels is not None:
|
||||
data["labels"] = labels
|
||||
|
||||
response = self._client.request(url="/primary_ips", json=data, method="POST")
|
||||
|
||||
action = None
|
||||
if response.get("action") is not None:
|
||||
action = BoundAction(self._client.actions, response["action"])
|
||||
|
||||
result = CreatePrimaryIPResponse(
|
||||
primary_ip=BoundPrimaryIP(self, response["primary_ip"]), action=action
|
||||
)
|
||||
return result
|
||||
|
||||
def update(self, primary_ip, auto_delete=None, labels=None, name=None):
|
||||
# type: (PrimaryIP, Optional[bool], Optional[Dict[str, str]], Optional[str]) -> BoundPrimaryIP
|
||||
"""Updates the name, auto_delete or labels of a Primary IP.
|
||||
|
||||
:param primary_ip: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>` or :class:`PrimaryIP <hcloud.primary_ips.domain.PrimaryIP>`
|
||||
:param auto_delete: bool (optional)
|
||||
Delete this Primary IP when the resource it is assigned to is deleted
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:param name: str (optional)
|
||||
New name to set
|
||||
:return: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>`
|
||||
"""
|
||||
data = {}
|
||||
if auto_delete is not None:
|
||||
data["auto_delete"] = auto_delete
|
||||
if labels is not None:
|
||||
data["labels"] = labels
|
||||
if name is not None:
|
||||
data["name"] = name
|
||||
|
||||
response = self._client.request(
|
||||
url=f"/primary_ips/{primary_ip.id}",
|
||||
method="PUT",
|
||||
json=data,
|
||||
)
|
||||
return BoundPrimaryIP(self, response["primary_ip"])
|
||||
|
||||
def delete(self, primary_ip):
|
||||
# type: (PrimaryIP) -> bool
|
||||
"""Deletes a Primary IP. If it is currently assigned to an assignee it will automatically get unassigned.
|
||||
|
||||
:param primary_ip: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>` or :class:`PrimaryIP <hcloud.primary_ips.domain.PrimaryIP>`
|
||||
:return: boolean
|
||||
"""
|
||||
self._client.request(
|
||||
url=f"/primary_ips/{primary_ip.id}",
|
||||
method="DELETE",
|
||||
)
|
||||
# Return always true, because the API does not return an action for it. When an error occurs a HcloudAPIException will be raised
|
||||
return True
|
||||
|
||||
def change_protection(self, primary_ip, delete=None):
|
||||
# type: (PrimaryIP, Optional[bool]) -> BoundAction
|
||||
"""Changes the protection configuration of the Primary IP.
|
||||
|
||||
:param primary_ip: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>` or :class:`PrimaryIP <hcloud.primary_ips.domain.PrimaryIP>`
|
||||
:param delete: boolean
|
||||
If true, prevents the Primary IP from being deleted
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {}
|
||||
if delete is not None:
|
||||
data.update({"delete": delete})
|
||||
|
||||
response = self._client.request(
|
||||
url="/primary_ips/{primary_ip_id}/actions/change_protection".format(
|
||||
primary_ip_id=primary_ip.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def assign(self, primary_ip, assignee_id, assignee_type="server"):
|
||||
# type: (PrimaryIP, int, str) -> BoundAction
|
||||
"""Assigns a Primary IP to a assignee_id.
|
||||
|
||||
:param primary_ip: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>` or :class:`PrimaryIP <hcloud.primary_ips.domain.PrimaryIP>`
|
||||
:param assignee_id: int
|
||||
Assignee the Primary IP shall be assigned to
|
||||
:param assignee_type: str
|
||||
Assignee the Primary IP shall be assigned to
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
response = self._client.request(
|
||||
url="/primary_ips/{primary_ip_id}/actions/assign".format(
|
||||
primary_ip_id=primary_ip.id
|
||||
),
|
||||
method="POST",
|
||||
json={"assignee_id": assignee_id, "assignee_type": assignee_type},
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def unassign(self, primary_ip):
|
||||
# type: (PrimaryIP) -> BoundAction
|
||||
"""Unassigns a Primary IP, resulting in it being unreachable. You may assign it to a server again at a later time.
|
||||
|
||||
:param primary_ip: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>` or :class:`PrimaryIP <hcloud.primary_ips.domain.PrimaryIP>`
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
response = self._client.request(
|
||||
url="/primary_ips/{primary_ip_id}/actions/unassign".format(
|
||||
primary_ip_id=primary_ip.id
|
||||
),
|
||||
method="POST",
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
||||
|
||||
def change_dns_ptr(self, primary_ip, ip, dns_ptr):
|
||||
# type: (PrimaryIP, str, str) -> BoundAction
|
||||
"""Changes the dns ptr that will appear when getting the dns ptr belonging to this Primary IP.
|
||||
|
||||
:param primary_ip: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>` or :class:`PrimaryIP <hcloud.primary_ips.domain.PrimaryIP>`
|
||||
:param ip: str
|
||||
The IP address for which to set the reverse DNS entry
|
||||
:param dns_ptr: str
|
||||
Hostname to set as a reverse DNS PTR entry, will reset to original default value if `None`
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
response = self._client.request(
|
||||
url="/primary_ips/{primary_ip_id}/actions/change_dns_ptr".format(
|
||||
primary_ip_id=primary_ip.id
|
||||
),
|
||||
method="POST",
|
||||
json={"ip": ip, "dns_ptr": dns_ptr},
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
104
plugins/module_utils/vendor/hcloud/primary_ips/domain.py
vendored
Normal file
104
plugins/module_utils/vendor/hcloud/primary_ips/domain.py
vendored
Normal file
|
@ -0,0 +1,104 @@
|
|||
try:
|
||||
from dateutil.parser import isoparse
|
||||
except ImportError:
|
||||
isoparse = None
|
||||
|
||||
from ..core.domain import BaseDomain
|
||||
|
||||
|
||||
class PrimaryIP(BaseDomain):
|
||||
"""Primary IP Domain
|
||||
|
||||
:param id: int
|
||||
ID of the Primary IP
|
||||
:param ip: str
|
||||
IP address of the Primary IP
|
||||
:param type: str
|
||||
Type of Primary IP. Choices: `ipv4`, `ipv6`
|
||||
:param dns_ptr: List[Dict]
|
||||
Array of reverse DNS entries
|
||||
:param datacenter: :class:`Datacenter <hcloud.datacenters.client.BoundDatacenter>`
|
||||
Datacenter the Primary IP was created in.
|
||||
:param blocked: boolean
|
||||
Whether the IP is blocked
|
||||
:param protection: dict
|
||||
Protection configuration for the Primary IP
|
||||
:param labels: dict
|
||||
User-defined labels (key-value pairs)
|
||||
:param created: datetime
|
||||
Point in time when the Primary IP was created
|
||||
:param name: str
|
||||
Name of the Primary IP
|
||||
:param assignee_id: int
|
||||
Assignee ID the Primary IP is assigned to
|
||||
:param assignee_type: str
|
||||
Assignee Type of entity the Primary IP is assigned to
|
||||
:param auto_delete: bool
|
||||
Delete the Primary IP when the Assignee it is assigned to is deleted.
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"id",
|
||||
"ip",
|
||||
"type",
|
||||
"dns_ptr",
|
||||
"datacenter",
|
||||
"blocked",
|
||||
"protection",
|
||||
"labels",
|
||||
"created",
|
||||
"name",
|
||||
"assignee_id",
|
||||
"assignee_type",
|
||||
"auto_delete",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id=None,
|
||||
type=None,
|
||||
ip=None,
|
||||
dns_ptr=None,
|
||||
datacenter=None,
|
||||
blocked=None,
|
||||
protection=None,
|
||||
labels=None,
|
||||
created=None,
|
||||
name=None,
|
||||
assignee_id=None,
|
||||
assignee_type=None,
|
||||
auto_delete=None,
|
||||
):
|
||||
self.id = id
|
||||
self.type = type
|
||||
self.ip = ip
|
||||
self.dns_ptr = dns_ptr
|
||||
self.datacenter = datacenter
|
||||
self.blocked = blocked
|
||||
self.protection = protection
|
||||
self.labels = labels
|
||||
self.created = isoparse(created) if created else None
|
||||
self.name = name
|
||||
self.assignee_id = assignee_id
|
||||
self.assignee_type = assignee_type
|
||||
self.auto_delete = auto_delete
|
||||
|
||||
|
||||
class CreatePrimaryIPResponse(BaseDomain):
|
||||
"""Create Primary IP Response Domain
|
||||
|
||||
:param primary_ip: :class:`BoundPrimaryIP <hcloud.primary_ips.client.BoundPrimaryIP>`
|
||||
The Primary IP which was created
|
||||
:param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
The Action which shows the progress of the Primary IP Creation
|
||||
"""
|
||||
|
||||
__slots__ = ("primary_ip", "action")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
primary_ip, # type: BoundPrimaryIP
|
||||
action, # type: BoundAction
|
||||
):
|
||||
self.primary_ip = primary_ip
|
||||
self.action = action
|
0
plugins/module_utils/vendor/hcloud/server_types/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/server_types/__init__.py
vendored
Normal file
69
plugins/module_utils/vendor/hcloud/server_types/client.py
vendored
Normal file
69
plugins/module_utils/vendor/hcloud/server_types/client.py
vendored
Normal file
|
@ -0,0 +1,69 @@
|
|||
from ..core.client import BoundModelBase, ClientEntityBase, GetEntityByNameMixin
|
||||
from .domain import ServerType
|
||||
|
||||
|
||||
class BoundServerType(BoundModelBase):
|
||||
model = ServerType
|
||||
|
||||
|
||||
class ServerTypesClient(ClientEntityBase, GetEntityByNameMixin):
|
||||
results_list_attribute_name = "server_types"
|
||||
|
||||
def get_by_id(self, id):
|
||||
# type: (int) -> BoundServerType
|
||||
"""Returns a specific Server Type.
|
||||
|
||||
:param id: int
|
||||
:return: :class:`BoundServerType <hcloud.server_types.client.BoundServerType>`
|
||||
"""
|
||||
response = self._client.request(url=f"/server_types/{id}", method="GET")
|
||||
return BoundServerType(self, response["server_type"])
|
||||
|
||||
def get_list(self, name=None, page=None, per_page=None):
|
||||
# type: (Optional[str], Optional[int], Optional[int]) -> PageResults[List[BoundServerType], Meta]
|
||||
"""Get a list of Server types
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter server type by their name.
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundServerType <hcloud.server_types.client.BoundServerType>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
if name is not None:
|
||||
params["name"] = name
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
|
||||
response = self._client.request(
|
||||
url="/server_types", method="GET", params=params
|
||||
)
|
||||
server_types = [
|
||||
BoundServerType(self, server_type_data)
|
||||
for server_type_data in response["server_types"]
|
||||
]
|
||||
return self._add_meta_to_result(server_types, response)
|
||||
|
||||
def get_all(self, name=None):
|
||||
# type: (Optional[str]) -> List[BoundServerType]
|
||||
"""Get all Server types
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter server type by their name.
|
||||
:return: List[:class:`BoundServerType <hcloud.server_types.client.BoundServerType>`]
|
||||
"""
|
||||
return super().get_all(name=name)
|
||||
|
||||
def get_by_name(self, name):
|
||||
# type: (str) -> BoundServerType
|
||||
"""Get Server type by name
|
||||
|
||||
:param name: str
|
||||
Used to get Server type by name.
|
||||
:return: :class:`BoundServerType <hcloud.server_types.client.BoundServerType>`
|
||||
"""
|
||||
return super().get_by_name(name)
|
83
plugins/module_utils/vendor/hcloud/server_types/domain.py
vendored
Normal file
83
plugins/module_utils/vendor/hcloud/server_types/domain.py
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
from ..core.domain import BaseDomain, DomainIdentityMixin
|
||||
from ..deprecation.domain import DeprecationInfo
|
||||
|
||||
|
||||
class ServerType(BaseDomain, DomainIdentityMixin):
|
||||
"""ServerType Domain
|
||||
|
||||
:param id: int
|
||||
ID of the server type
|
||||
:param name: str
|
||||
Unique identifier of the server type
|
||||
:param description: str
|
||||
Description of the server type
|
||||
:param cores: int
|
||||
Number of cpu cores a server of this type will have
|
||||
:param memory: int
|
||||
Memory a server of this type will have in GB
|
||||
:param disk: int
|
||||
Disk size a server of this type will have in GB
|
||||
:param prices: Dict
|
||||
Prices in different locations
|
||||
:param storage_type: str
|
||||
Type of server boot drive. Local has higher speed. Network has better availability. Choices: `local`, `network`
|
||||
:param cpu_type: string
|
||||
Type of cpu. Choices: `shared`, `dedicated`
|
||||
:param architecture: string
|
||||
Architecture of cpu. Choices: `x86`, `arm`
|
||||
:param deprecated: bool
|
||||
True if server type is deprecated. This field is deprecated. Use `deprecation` instead.
|
||||
:param deprecation: :class:`DeprecationInfo <hcloud.deprecation.domain.DeprecationInfo>`, None
|
||||
Describes if, when & how the resources was deprecated. If this field is set to None the resource is not
|
||||
deprecated. If it has a value, it is considered deprecated.
|
||||
:param included_traffic: int
|
||||
Free traffic per month in bytes
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"id",
|
||||
"name",
|
||||
"description",
|
||||
"cores",
|
||||
"memory",
|
||||
"disk",
|
||||
"prices",
|
||||
"storage_type",
|
||||
"cpu_type",
|
||||
"architecture",
|
||||
"deprecated",
|
||||
"deprecation",
|
||||
"included_traffic",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id=None,
|
||||
name=None,
|
||||
description=None,
|
||||
cores=None,
|
||||
memory=None,
|
||||
disk=None,
|
||||
prices=None,
|
||||
storage_type=None,
|
||||
cpu_type=None,
|
||||
architecture=None,
|
||||
deprecated=None,
|
||||
deprecation=None,
|
||||
included_traffic=None,
|
||||
):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.cores = cores
|
||||
self.memory = memory
|
||||
self.disk = disk
|
||||
self.prices = prices
|
||||
self.storage_type = storage_type
|
||||
self.cpu_type = cpu_type
|
||||
self.architecture = architecture
|
||||
self.deprecated = deprecated
|
||||
self.deprecation = (
|
||||
DeprecationInfo.from_dict(deprecation) if deprecation is not None else None
|
||||
)
|
||||
self.included_traffic = included_traffic
|
0
plugins/module_utils/vendor/hcloud/servers/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/servers/__init__.py
vendored
Normal file
1089
plugins/module_utils/vendor/hcloud/servers/client.py
vendored
Normal file
1089
plugins/module_utils/vendor/hcloud/servers/client.py
vendored
Normal file
File diff suppressed because it is too large
Load diff
395
plugins/module_utils/vendor/hcloud/servers/domain.py
vendored
Normal file
395
plugins/module_utils/vendor/hcloud/servers/domain.py
vendored
Normal file
|
@ -0,0 +1,395 @@
|
|||
try:
|
||||
from dateutil.parser import isoparse
|
||||
except ImportError:
|
||||
isoparse = None
|
||||
|
||||
from ..core.domain import BaseDomain
|
||||
|
||||
|
||||
class Server(BaseDomain):
|
||||
"""Server Domain
|
||||
|
||||
:param id: int
|
||||
ID of the server
|
||||
:param name: str
|
||||
Name of the server (must be unique per project and a valid hostname as per RFC 1123)
|
||||
:param status: str
|
||||
Status of the server Choices: `running`, `initializing`, `starting`, `stopping`, `off`, `deleting`, `migrating`, `rebuilding`, `unknown`
|
||||
:param created: datetime
|
||||
Point in time when the server was created
|
||||
:param public_net: :class:`PublicNetwork <hcloud.servers.domain.PublicNetwork>`
|
||||
Public network information.
|
||||
:param server_type: :class:`BoundServerType <hcloud.server_types.client.BoundServerType>`
|
||||
:param datacenter: :class:`BoundDatacenter <hcloud.datacenters.client.BoundDatacenter>`
|
||||
:param image: :class:`BoundImage <hcloud.images.client.BoundImage>`, None
|
||||
:param iso: :class:`BoundIso <hcloud.isos.client.BoundIso>`, None
|
||||
:param rescue_enabled: bool
|
||||
True if rescue mode is enabled: Server will then boot into rescue system on next reboot.
|
||||
:param locked: bool
|
||||
True if server has been locked and is not available to user.
|
||||
:param backup_window: str, None
|
||||
Time window (UTC) in which the backup will run, or None if the backups are not enabled
|
||||
:param outgoing_traffic: int, None
|
||||
Outbound Traffic for the current billing period in bytes
|
||||
:param ingoing_traffic: int, None
|
||||
Inbound Traffic for the current billing period in bytes
|
||||
:param included_traffic: int
|
||||
Free Traffic for the current billing period in bytes
|
||||
:param primary_disk_size: int
|
||||
Size of the primary Disk
|
||||
:param protection: dict
|
||||
Protection configuration for the server
|
||||
:param labels: dict
|
||||
User-defined labels (key-value pairs)
|
||||
:param volumes: List[:class:`BoundVolume <hcloud.volumes.client.BoundVolume>`]
|
||||
Volumes assigned to this server.
|
||||
:param private_net: List[:class:`PrivateNet <hcloud.servers.domain.PrivateNet>`]
|
||||
Private networks information.
|
||||
"""
|
||||
|
||||
STATUS_RUNNING = "running"
|
||||
"""Server Status running"""
|
||||
STATUS_INIT = "initializing"
|
||||
"""Server Status initializing"""
|
||||
STATUS_STARTING = "starting"
|
||||
"""Server Status starting"""
|
||||
STATUS_STOPPING = "stopping"
|
||||
"""Server Status stopping"""
|
||||
STATUS_OFF = "off"
|
||||
"""Server Status off"""
|
||||
STATUS_DELETING = "deleting"
|
||||
"""Server Status deleting"""
|
||||
STATUS_MIGRATING = "migrating"
|
||||
"""Server Status migrating"""
|
||||
STATUS_REBUILDING = "rebuilding"
|
||||
"""Server Status rebuilding"""
|
||||
STATUS_UNKNOWN = "unknown"
|
||||
"""Server Status unknown"""
|
||||
__slots__ = (
|
||||
"id",
|
||||
"name",
|
||||
"status",
|
||||
"public_net",
|
||||
"server_type",
|
||||
"datacenter",
|
||||
"image",
|
||||
"iso",
|
||||
"rescue_enabled",
|
||||
"locked",
|
||||
"backup_window",
|
||||
"outgoing_traffic",
|
||||
"ingoing_traffic",
|
||||
"included_traffic",
|
||||
"protection",
|
||||
"labels",
|
||||
"volumes",
|
||||
"private_net",
|
||||
"created",
|
||||
"primary_disk_size",
|
||||
"placement_group",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id,
|
||||
name=None,
|
||||
status=None,
|
||||
created=None,
|
||||
public_net=None,
|
||||
server_type=None,
|
||||
datacenter=None,
|
||||
image=None,
|
||||
iso=None,
|
||||
rescue_enabled=None,
|
||||
locked=None,
|
||||
backup_window=None,
|
||||
outgoing_traffic=None,
|
||||
ingoing_traffic=None,
|
||||
included_traffic=None,
|
||||
protection=None,
|
||||
labels=None,
|
||||
volumes=None,
|
||||
private_net=None,
|
||||
primary_disk_size=None,
|
||||
placement_group=None,
|
||||
):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.status = status
|
||||
self.created = isoparse(created) if created else None
|
||||
self.public_net = public_net
|
||||
self.server_type = server_type
|
||||
self.datacenter = datacenter
|
||||
self.image = image
|
||||
self.iso = iso
|
||||
self.rescue_enabled = rescue_enabled
|
||||
self.locked = locked
|
||||
self.backup_window = backup_window
|
||||
self.outgoing_traffic = outgoing_traffic
|
||||
self.ingoing_traffic = ingoing_traffic
|
||||
self.included_traffic = included_traffic
|
||||
self.protection = protection
|
||||
self.labels = labels
|
||||
self.volumes = volumes
|
||||
self.private_net = private_net
|
||||
self.primary_disk_size = primary_disk_size
|
||||
self.placement_group = placement_group
|
||||
|
||||
|
||||
class CreateServerResponse(BaseDomain):
|
||||
"""Create Server Response Domain
|
||||
|
||||
:param server: :class:`BoundServer <hcloud.servers.client.BoundServer>`
|
||||
The created server
|
||||
:param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
Shows the progress of the server creation
|
||||
:param next_actions: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
Additional actions like a `start_server` action after the server creation
|
||||
:param root_password: str, None
|
||||
The root password of the server if no SSH-Key was given on server creation
|
||||
"""
|
||||
|
||||
__slots__ = ("server", "action", "next_actions", "root_password")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
server, # type: BoundServer
|
||||
action, # type: BoundAction
|
||||
next_actions, # type: List[Action]
|
||||
root_password, # type: str
|
||||
):
|
||||
self.server = server
|
||||
self.action = action
|
||||
self.next_actions = next_actions
|
||||
self.root_password = root_password
|
||||
|
||||
|
||||
class ResetPasswordResponse(BaseDomain):
|
||||
"""Reset Password Response Domain
|
||||
|
||||
:param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
Shows the progress of the server passwort reset action
|
||||
:param root_password: str
|
||||
The root password of the server
|
||||
"""
|
||||
|
||||
__slots__ = ("action", "root_password")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
action, # type: BoundAction
|
||||
root_password, # type: str
|
||||
):
|
||||
self.action = action
|
||||
self.root_password = root_password
|
||||
|
||||
|
||||
class EnableRescueResponse(BaseDomain):
|
||||
"""Enable Rescue Response Domain
|
||||
|
||||
:param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
Shows the progress of the server enable rescue action
|
||||
:param root_password: str
|
||||
The root password of the server in the rescue mode
|
||||
"""
|
||||
|
||||
__slots__ = ("action", "root_password")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
action, # type: BoundAction
|
||||
root_password, # type: str
|
||||
):
|
||||
self.action = action
|
||||
self.root_password = root_password
|
||||
|
||||
|
||||
class RequestConsoleResponse(BaseDomain):
|
||||
"""Request Console Response Domain
|
||||
|
||||
:param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
Shows the progress of the server request console action
|
||||
:param wss_url: str
|
||||
URL of websocket proxy to use. This includes a token which is valid for a limited time only.
|
||||
:param password: str
|
||||
VNC password to use for this connection. This password only works in combination with a wss_url with valid token.
|
||||
"""
|
||||
|
||||
__slots__ = ("action", "wss_url", "password")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
action, # type: BoundAction
|
||||
wss_url, # type: str
|
||||
password, # type: str
|
||||
):
|
||||
self.action = action
|
||||
self.wss_url = wss_url
|
||||
self.password = password
|
||||
|
||||
|
||||
class PublicNetwork(BaseDomain):
|
||||
"""Public Network Domain
|
||||
|
||||
:param ipv4: :class:`IPv4Address <hcloud.servers.domain.IPv4Address>`
|
||||
:param ipv6: :class:`IPv6Network <hcloud.servers.domain.IPv6Network>`
|
||||
:param floating_ips: List[:class:`BoundFloatingIP <hcloud.floating_ips.client.BoundFloatingIP>`]
|
||||
:param primary_ipv4: :class:`BoundPrimaryIP <hcloud.primary_ips.domain.BoundPrimaryIP>`
|
||||
:param primary_ipv6: :class:`BoundPrimaryIP <hcloud.primary_ips.domain.BoundPrimaryIP>`
|
||||
:param firewalls: List[:class:`PublicNetworkFirewall <hcloud.servers.client.PublicNetworkFirewall>`]
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"ipv4",
|
||||
"ipv6",
|
||||
"floating_ips",
|
||||
"firewalls",
|
||||
"primary_ipv4",
|
||||
"primary_ipv6",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
ipv4, # type: IPv4Address
|
||||
ipv6, # type: IPv6Network
|
||||
floating_ips, # type: List[BoundFloatingIP]
|
||||
primary_ipv4, # type: BoundPrimaryIP
|
||||
primary_ipv6, # type: BoundPrimaryIP
|
||||
firewalls=None, # type: List[PublicNetworkFirewall]
|
||||
):
|
||||
self.ipv4 = ipv4
|
||||
self.ipv6 = ipv6
|
||||
self.floating_ips = floating_ips
|
||||
self.firewalls = firewalls
|
||||
self.primary_ipv4 = primary_ipv4
|
||||
self.primary_ipv6 = primary_ipv6
|
||||
|
||||
|
||||
class PublicNetworkFirewall(BaseDomain):
|
||||
"""Public Network Domain
|
||||
|
||||
:param firewall: :class:`BoundFirewall <hcloud.firewalls.domain.BoundFirewall>`
|
||||
:param status: str
|
||||
"""
|
||||
|
||||
__slots__ = ("firewall", "status")
|
||||
|
||||
STATUS_APPLIED = "applied"
|
||||
"""Public Network Firewall Status applied"""
|
||||
STATUS_PENDING = "pending"
|
||||
"""Public Network Firewall Status pending"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
firewall, # type: BoundFirewall
|
||||
status, # type: str
|
||||
):
|
||||
self.firewall = firewall
|
||||
self.status = status
|
||||
|
||||
|
||||
class IPv4Address(BaseDomain):
|
||||
"""IPv4 Address Domain
|
||||
|
||||
:param ip: str
|
||||
The IPv4 Address
|
||||
:param blocked: bool
|
||||
Determine if the IP is blocked
|
||||
:param dns_ptr: str
|
||||
DNS PTR for the ip
|
||||
"""
|
||||
|
||||
__slots__ = ("ip", "blocked", "dns_ptr")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
ip, # type: str
|
||||
blocked, # type: bool
|
||||
dns_ptr, # type: str
|
||||
):
|
||||
self.ip = ip
|
||||
self.blocked = blocked
|
||||
self.dns_ptr = dns_ptr
|
||||
|
||||
|
||||
class IPv6Network(BaseDomain):
|
||||
"""IPv6 Network Domain
|
||||
|
||||
:param ip: str
|
||||
The IPv6 Network as CIDR Notation
|
||||
:param blocked: bool
|
||||
Determine if the Network is blocked
|
||||
:param dns_ptr: dict
|
||||
DNS PTR Records for the Network as Dict
|
||||
:param network: str
|
||||
The network without the network mask
|
||||
:param network_mask: str
|
||||
The network mask
|
||||
"""
|
||||
|
||||
__slots__ = ("ip", "blocked", "dns_ptr", "network", "network_mask")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
ip, # type: str
|
||||
blocked, # type: bool
|
||||
dns_ptr, # type: list
|
||||
):
|
||||
self.ip = ip
|
||||
self.blocked = blocked
|
||||
self.dns_ptr = dns_ptr
|
||||
ip_parts = self.ip.split("/") # 2001:db8::/64 to 2001:db8:: and 64
|
||||
self.network = ip_parts[0]
|
||||
self.network_mask = ip_parts[1]
|
||||
|
||||
|
||||
class PrivateNet(BaseDomain):
|
||||
"""PrivateNet Domain
|
||||
|
||||
:param network: :class:`BoundNetwork <hcloud.networks.client.BoundNetwork>`
|
||||
The network the server is attached to
|
||||
:param ip: str
|
||||
The main IP Address of the server in the Network
|
||||
:param alias_ips: List[str]
|
||||
The alias ips for a server
|
||||
:param mac_address: str
|
||||
The mac address of the interface on the server
|
||||
"""
|
||||
|
||||
__slots__ = ("network", "ip", "alias_ips", "mac_address")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
network, # type: BoundNetwork
|
||||
ip, # type: str
|
||||
alias_ips, # type: List[str]
|
||||
mac_address, # type: str
|
||||
):
|
||||
self.network = network
|
||||
self.ip = ip
|
||||
self.alias_ips = alias_ips
|
||||
self.mac_address = mac_address
|
||||
|
||||
|
||||
class ServerCreatePublicNetwork(BaseDomain):
|
||||
"""Server Create Public Network Domain
|
||||
|
||||
:param ipv4: Optional[:class:`PrimaryIP <hcloud.primary_ips.domain.PrimaryIP>`]
|
||||
:param ipv6: Optional[:class:`PrimaryIP <hcloud.primary_ips.domain.PrimaryIP>`]
|
||||
:param enable_ipv4: bool
|
||||
:param enable_ipv6: bool
|
||||
"""
|
||||
|
||||
__slots__ = ("ipv4", "ipv6", "enable_ipv4", "enable_ipv6")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
ipv4=None, # type: hcloud.primary_ips.domain.PrimaryIP
|
||||
ipv6=None, # type: hcloud.primary_ips.domain.PrimaryIP
|
||||
enable_ipv4=True, # type: bool
|
||||
enable_ipv6=True, # type: bool
|
||||
):
|
||||
self.ipv4 = ipv4
|
||||
self.ipv6 = ipv6
|
||||
self.enable_ipv4 = enable_ipv4
|
||||
self.enable_ipv6 = enable_ipv6
|
0
plugins/module_utils/vendor/hcloud/ssh_keys/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/ssh_keys/__init__.py
vendored
Normal file
170
plugins/module_utils/vendor/hcloud/ssh_keys/client.py
vendored
Normal file
170
plugins/module_utils/vendor/hcloud/ssh_keys/client.py
vendored
Normal file
|
@ -0,0 +1,170 @@
|
|||
from ..core.client import BoundModelBase, ClientEntityBase, GetEntityByNameMixin
|
||||
from .domain import SSHKey
|
||||
|
||||
|
||||
class BoundSSHKey(BoundModelBase):
|
||||
model = SSHKey
|
||||
|
||||
def update(self, name=None, labels=None):
|
||||
# type: (Optional[str], Optional[Dict[str, str]]) -> BoundSSHKey
|
||||
"""Updates an SSH key. You can update an SSH key name and an SSH key labels.
|
||||
|
||||
:param description: str (optional)
|
||||
New Description to set
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:return: :class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>
|
||||
"""
|
||||
return self._client.update(self, name, labels)
|
||||
|
||||
def delete(self):
|
||||
# type: () -> bool
|
||||
"""Deletes an SSH key. It cannot be used anymore.
|
||||
:return: boolean
|
||||
"""
|
||||
return self._client.delete(self)
|
||||
|
||||
|
||||
class SSHKeysClient(ClientEntityBase, GetEntityByNameMixin):
|
||||
results_list_attribute_name = "ssh_keys"
|
||||
|
||||
def get_by_id(self, id):
|
||||
# type: (int) -> BoundSSHKey
|
||||
"""Get a specific SSH Key by its ID
|
||||
|
||||
:param id: int
|
||||
:return: :class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>`
|
||||
"""
|
||||
response = self._client.request(url=f"/ssh_keys/{id}", method="GET")
|
||||
return BoundSSHKey(self, response["ssh_key"])
|
||||
|
||||
def get_list(
|
||||
self,
|
||||
name=None, # type: Optional[str]
|
||||
fingerprint=None, # type: Optional[str]
|
||||
label_selector=None, # type: Optional[str]
|
||||
page=None, # type: Optional[int]
|
||||
per_page=None, # type: Optional[int]
|
||||
):
|
||||
# type: (...) -> PageResults[List[BoundSSHKey], Meta]
|
||||
"""Get a list of SSH keys from the account
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter SSH keys by their name. The response will only contain the SSH key matching the specified name.
|
||||
:param fingerprint: str (optional)
|
||||
Can be used to filter SSH keys by their fingerprint. The response will only contain the SSH key matching the specified fingerprint.
|
||||
:param label_selector: str (optional)
|
||||
Can be used to filter SSH keys by labels. The response will only contain SSH keys matching the label selector.
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
if name is not None:
|
||||
params["name"] = name
|
||||
if fingerprint is not None:
|
||||
params["fingerprint"] = fingerprint
|
||||
if label_selector is not None:
|
||||
params["label_selector"] = label_selector
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
|
||||
response = self._client.request(url="/ssh_keys", method="GET", params=params)
|
||||
|
||||
ass_ssh_keys = [
|
||||
BoundSSHKey(self, server_data) for server_data in response["ssh_keys"]
|
||||
]
|
||||
return self._add_meta_to_result(ass_ssh_keys, response)
|
||||
|
||||
def get_all(self, name=None, fingerprint=None, label_selector=None):
|
||||
# type: (Optional[str], Optional[str], Optional[str]) -> List[BoundSSHKey]
|
||||
"""Get all SSH keys from the account
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter SSH keys by their name. The response will only contain the SSH key matching the specified name.
|
||||
:param fingerprint: str (optional)
|
||||
Can be used to filter SSH keys by their fingerprint. The response will only contain the SSH key matching the specified fingerprint.
|
||||
:param label_selector: str (optional)
|
||||
Can be used to filter SSH keys by labels. The response will only contain SSH keys matching the label selector.
|
||||
:return: List[:class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>`]
|
||||
"""
|
||||
return super().get_all(
|
||||
name=name, fingerprint=fingerprint, label_selector=label_selector
|
||||
)
|
||||
|
||||
def get_by_name(self, name):
|
||||
# type: (str) -> SSHKeysClient
|
||||
"""Get ssh key by name
|
||||
|
||||
:param name: str
|
||||
Used to get ssh key by name.
|
||||
:return: :class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>`
|
||||
"""
|
||||
return super().get_by_name(name)
|
||||
|
||||
def get_by_fingerprint(self, fingerprint):
|
||||
# type: (str) -> BoundSSHKey
|
||||
"""Get ssh key by fingerprint
|
||||
|
||||
:param fingerprint: str
|
||||
Used to get ssh key by fingerprint.
|
||||
:return: :class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>`
|
||||
"""
|
||||
response = self.get_list(fingerprint=fingerprint)
|
||||
sshkeys = response.ssh_keys
|
||||
return sshkeys[0] if sshkeys else None
|
||||
|
||||
def create(self, name, public_key, labels=None):
|
||||
# type: (str, str, Optional[Dict[str, str]]) -> BoundSSHKey
|
||||
"""Creates a new SSH key with the given name and public_key.
|
||||
|
||||
:param name: str
|
||||
:param public_key: str
|
||||
Public Key of the SSH Key you want create
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:return: :class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>`
|
||||
"""
|
||||
data = {"name": name, "public_key": public_key}
|
||||
if labels is not None:
|
||||
data["labels"] = labels
|
||||
response = self._client.request(url="/ssh_keys", method="POST", json=data)
|
||||
return BoundSSHKey(self, response["ssh_key"])
|
||||
|
||||
def update(self, ssh_key, name=None, labels=None):
|
||||
# type: (SSHKey, Optional[str], Optional[Dict[str, str]]) -> BoundSSHKey
|
||||
"""Updates an SSH key. You can update an SSH key name and an SSH key labels.
|
||||
|
||||
:param ssh_key: :class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>` or :class:`SSHKey <hcloud.ssh_keys.domain.SSHKey>`
|
||||
:param name: str (optional)
|
||||
New Description to set
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:return: :class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>`
|
||||
"""
|
||||
data = {}
|
||||
if name is not None:
|
||||
data["name"] = name
|
||||
if labels is not None:
|
||||
data["labels"] = labels
|
||||
response = self._client.request(
|
||||
url=f"/ssh_keys/{ssh_key.id}",
|
||||
method="PUT",
|
||||
json=data,
|
||||
)
|
||||
return BoundSSHKey(self, response["ssh_key"])
|
||||
|
||||
def delete(self, ssh_key):
|
||||
# type: (SSHKey) -> bool
|
||||
self._client.request(url=f"/ssh_keys/{ssh_key.id}", method="DELETE")
|
||||
"""Deletes an SSH key. It cannot be used anymore.
|
||||
|
||||
:param ssh_key: :class:`BoundSSHKey <hcloud.ssh_keys.client.BoundSSHKey>` or :class:`SSHKey <hcloud.ssh_keys.domain.SSHKey>`
|
||||
:return: True
|
||||
"""
|
||||
# Return always true, because the API does not return an action for it. When an error occurs a HcloudAPIException will be raised
|
||||
return True
|
42
plugins/module_utils/vendor/hcloud/ssh_keys/domain.py
vendored
Normal file
42
plugins/module_utils/vendor/hcloud/ssh_keys/domain.py
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
try:
|
||||
from dateutil.parser import isoparse
|
||||
except ImportError:
|
||||
isoparse = None
|
||||
|
||||
from ..core.domain import BaseDomain, DomainIdentityMixin
|
||||
|
||||
|
||||
class SSHKey(BaseDomain, DomainIdentityMixin):
|
||||
"""SSHKey Domain
|
||||
|
||||
:param id: int
|
||||
ID of the SSH key
|
||||
:param name: str
|
||||
Name of the SSH key (must be unique per project)
|
||||
:param fingerprint: str
|
||||
Fingerprint of public key
|
||||
:param public_key: str
|
||||
Public Key
|
||||
:param labels: Dict
|
||||
User-defined labels (key-value pairs)
|
||||
:param created: datetime
|
||||
Point in time when the SSH Key was created
|
||||
"""
|
||||
|
||||
__slots__ = ("id", "name", "fingerprint", "public_key", "labels", "created")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id=None,
|
||||
name=None,
|
||||
fingerprint=None,
|
||||
public_key=None,
|
||||
labels=None,
|
||||
created=None,
|
||||
):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.fingerprint = fingerprint
|
||||
self.public_key = public_key
|
||||
self.labels = labels
|
||||
self.created = isoparse(created) if created else None
|
0
plugins/module_utils/vendor/hcloud/volumes/__init__.py
vendored
Normal file
0
plugins/module_utils/vendor/hcloud/volumes/__init__.py
vendored
Normal file
395
plugins/module_utils/vendor/hcloud/volumes/client.py
vendored
Normal file
395
plugins/module_utils/vendor/hcloud/volumes/client.py
vendored
Normal file
|
@ -0,0 +1,395 @@
|
|||
from ..actions.client import BoundAction
|
||||
from ..core.client import BoundModelBase, ClientEntityBase, GetEntityByNameMixin
|
||||
from ..core.domain import add_meta_to_result
|
||||
from ..locations.client import BoundLocation
|
||||
from .domain import CreateVolumeResponse, Volume
|
||||
|
||||
|
||||
class BoundVolume(BoundModelBase):
|
||||
model = Volume
|
||||
|
||||
def __init__(self, client, data, complete=True):
|
||||
location = data.get("location")
|
||||
if location is not None:
|
||||
data["location"] = BoundLocation(client._client.locations, location)
|
||||
|
||||
from ..servers.client import BoundServer
|
||||
|
||||
server = data.get("server")
|
||||
if server is not None:
|
||||
data["server"] = BoundServer(
|
||||
client._client.servers, {"id": server}, complete=False
|
||||
)
|
||||
super().__init__(client, data, complete)
|
||||
|
||||
def get_actions_list(self, status=None, sort=None, page=None, per_page=None):
|
||||
# type: (Optional[List[str]], Optional[List[str]], Optional[int], Optional[int]) -> PageResults[List[BoundAction, Meta]]
|
||||
"""Returns all action objects for a volume.
|
||||
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
return self._client.get_actions_list(self, status, sort, page, per_page)
|
||||
|
||||
def get_actions(self, status=None, sort=None):
|
||||
# type: (Optional[List[str]], Optional[List[str]]) -> List[BoundAction]
|
||||
"""Returns all action objects for a volume.
|
||||
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort:List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
return self._client.get_actions(self, status, sort)
|
||||
|
||||
def update(self, name=None, labels=None):
|
||||
# type: (Optional[str], Optional[Dict[str, str]]) -> BoundAction
|
||||
"""Updates the volume properties.
|
||||
|
||||
:param name: str (optional)
|
||||
New volume name
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.update(self, name, labels)
|
||||
|
||||
def delete(self):
|
||||
# type: () -> BoundAction
|
||||
"""Deletes a volume. All volume data is irreversibly destroyed. The volume must not be attached to a server and it must not have delete protection enabled.
|
||||
|
||||
:return: boolean
|
||||
"""
|
||||
return self._client.delete(self)
|
||||
|
||||
def attach(self, server, automount=None):
|
||||
# type: (Union[Server, BoundServer], Optional[bool]) -> BoundAction
|
||||
"""Attaches a volume to a server. Works only if the server is in the same location as the volume.
|
||||
|
||||
:param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
|
||||
:param automount: boolean
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.attach(self, server, automount)
|
||||
|
||||
def detach(self):
|
||||
# type: () -> BoundAction
|
||||
"""Detaches a volume from the server it’s attached to. You may attach it to a server again at a later time.
|
||||
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.detach(self)
|
||||
|
||||
def resize(self, size):
|
||||
# type: (int) -> BoundAction
|
||||
"""Changes the size of a volume. Note that downsizing a volume is not possible.
|
||||
|
||||
:param size: int
|
||||
New volume size in GB (must be greater than current size)
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.resize(self, size)
|
||||
|
||||
def change_protection(self, delete=None):
|
||||
# type: (Optional[bool]) -> BoundAction
|
||||
"""Changes the protection configuration of a volume.
|
||||
|
||||
:param delete: boolean
|
||||
If True, prevents the volume from being deleted
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
return self._client.change_protection(self, delete)
|
||||
|
||||
|
||||
class VolumesClient(ClientEntityBase, GetEntityByNameMixin):
|
||||
results_list_attribute_name = "volumes"
|
||||
|
||||
def get_by_id(self, id):
|
||||
# type: (int) -> volumes.client.BoundVolume
|
||||
"""Get a specific volume by its id
|
||||
|
||||
:param id: int
|
||||
:return: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>`
|
||||
"""
|
||||
response = self._client.request(url=f"/volumes/{id}", method="GET")
|
||||
return BoundVolume(self, response["volume"])
|
||||
|
||||
def get_list(
|
||||
self, name=None, label_selector=None, page=None, per_page=None, status=None
|
||||
):
|
||||
# type: (Optional[str], Optional[str], Optional[int], Optional[int], Optional[List[str]]) -> PageResults[List[BoundVolume], Meta]
|
||||
"""Get a list of volumes from this account
|
||||
|
||||
:param name: str (optional)
|
||||
Can be used to filter volumes by their name.
|
||||
:param label_selector: str (optional)
|
||||
Can be used to filter volumes by labels. The response will only contain volumes matching the label selector.
|
||||
:param status: List[str] (optional)
|
||||
Can be used to filter volumes by their status. The response will only contain volumes matching the status.
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundVolume <hcloud.volumes.client.BoundVolume>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
if name is not None:
|
||||
params["name"] = name
|
||||
if label_selector is not None:
|
||||
params["label_selector"] = label_selector
|
||||
if status is not None:
|
||||
params["status"] = status
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
|
||||
response = self._client.request(url="/volumes", method="GET", params=params)
|
||||
volumes = [
|
||||
BoundVolume(self, volume_data) for volume_data in response["volumes"]
|
||||
]
|
||||
return self._add_meta_to_result(volumes, response)
|
||||
|
||||
def get_all(self, label_selector=None, status=None):
|
||||
# type: (Optional[str], Optional[List[str]]) -> List[BoundVolume]
|
||||
"""Get all volumes from this account
|
||||
|
||||
:param label_selector:
|
||||
Can be used to filter volumes by labels. The response will only contain volumes matching the label selector.
|
||||
:param status: List[str] (optional)
|
||||
Can be used to filter volumes by their status. The response will only contain volumes matching the status.
|
||||
:return: List[:class:`BoundVolume <hcloud.volumes.client.BoundVolume>`]
|
||||
"""
|
||||
return super().get_all(label_selector=label_selector, status=status)
|
||||
|
||||
def get_by_name(self, name):
|
||||
# type: (str) -> BoundVolume
|
||||
"""Get volume by name
|
||||
|
||||
:param name: str
|
||||
Used to get volume by name.
|
||||
:return: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>`
|
||||
"""
|
||||
return super().get_by_name(name)
|
||||
|
||||
def create(
|
||||
self,
|
||||
size, # type: int
|
||||
name, # type: str
|
||||
labels=None, # type: Optional[str]
|
||||
location=None, # type: Optional[Location]
|
||||
server=None, # type: Optional[Server],
|
||||
automount=None, # type: Optional[bool],
|
||||
format=None, # type: Optional[str],
|
||||
):
|
||||
# type: (...) -> CreateVolumeResponse
|
||||
"""Creates a new volume attached to a server.
|
||||
|
||||
:param size: int
|
||||
Size of the volume in GB
|
||||
:param name: str
|
||||
Name of the volume
|
||||
:param labels: Dict[str,str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:param location: :class:`BoundLocation <hcloud.locations.client.BoundLocation>` or :class:`Location <hcloud.locations.domain.Location>`
|
||||
:param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
|
||||
:param automount: boolean (optional)
|
||||
Auto mount volumes after attach.
|
||||
:param format: str (optional)
|
||||
Format volume after creation. One of: xfs, ext4
|
||||
:return: :class:`CreateVolumeResponse <hcloud.volumes.domain.CreateVolumeResponse>`
|
||||
"""
|
||||
|
||||
if size <= 0:
|
||||
raise ValueError("size must be greater than 0")
|
||||
|
||||
if not (bool(location) ^ bool(server)):
|
||||
raise ValueError("only one of server or location must be provided")
|
||||
|
||||
data = {"name": name, "size": size}
|
||||
if labels is not None:
|
||||
data["labels"] = labels
|
||||
if location is not None:
|
||||
data["location"] = location.id_or_name
|
||||
|
||||
if server is not None:
|
||||
data["server"] = server.id
|
||||
if automount is not None:
|
||||
data["automount"] = automount
|
||||
if format is not None:
|
||||
data["format"] = format
|
||||
|
||||
response = self._client.request(url="/volumes", json=data, method="POST")
|
||||
|
||||
result = CreateVolumeResponse(
|
||||
volume=BoundVolume(self, response["volume"]),
|
||||
action=BoundAction(self._client.actions, response["action"]),
|
||||
next_actions=[
|
||||
BoundAction(self._client.actions, action)
|
||||
for action in response["next_actions"]
|
||||
],
|
||||
)
|
||||
return result
|
||||
|
||||
def get_actions_list(
|
||||
self, volume, status=None, sort=None, page=None, per_page=None
|
||||
):
|
||||
# type: (Volume, Optional[List[str]], Optional[List[str]], Optional[int], Optional[int]) -> PageResults[List[BoundAction], Meta]
|
||||
"""Returns all action objects for a volume.
|
||||
|
||||
:param volume: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>` or :class:`Volume <hcloud.volumes.domain.Volume>`
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort: List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:param page: int (optional)
|
||||
Specifies the page to fetch
|
||||
:param per_page: int (optional)
|
||||
Specifies how many results are returned by page
|
||||
:return: (List[:class:`BoundAction <hcloud.actions.client.BoundAction>`], :class:`Meta <hcloud.core.domain.Meta>`)
|
||||
"""
|
||||
params = {}
|
||||
if status is not None:
|
||||
params["status"] = status
|
||||
if sort is not None:
|
||||
params["sort"] = sort
|
||||
if page is not None:
|
||||
params["page"] = page
|
||||
if per_page is not None:
|
||||
params["per_page"] = per_page
|
||||
|
||||
response = self._client.request(
|
||||
url=f"/volumes/{volume.id}/actions",
|
||||
method="GET",
|
||||
params=params,
|
||||
)
|
||||
actions = [
|
||||
BoundAction(self._client.actions, action_data)
|
||||
for action_data in response["actions"]
|
||||
]
|
||||
return add_meta_to_result(actions, response, "actions")
|
||||
|
||||
def get_actions(self, volume, status=None, sort=None):
|
||||
# type: (Union[Volume, BoundVolume], Optional[List[str]], Optional[List[str]]) -> List[BoundAction]
|
||||
"""Returns all action objects for a volume.
|
||||
|
||||
:param volume: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>` or :class:`Volume <hcloud.volumes.domain.Volume>`
|
||||
:param status: List[str] (optional)
|
||||
Response will have only actions with specified statuses. Choices: `running` `success` `error`
|
||||
:param sort:List[str] (optional)
|
||||
Specify how the results are sorted. Choices: `id` `id:asc` `id:desc` `command` `command:asc` `command:desc` `status` `status:asc` `status:desc` `progress` `progress:asc` `progress:desc` `started` `started:asc` `started:desc` `finished` `finished:asc` `finished:desc`
|
||||
:return: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
"""
|
||||
return super().get_actions(volume, status=status, sort=sort)
|
||||
|
||||
def update(self, volume, name=None, labels=None):
|
||||
# type:(Union[Volume, BoundVolume], Optional[str], Optional[Dict[str, str]]) -> BoundVolume
|
||||
"""Updates the volume properties.
|
||||
|
||||
:param volume: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>` or :class:`Volume <hcloud.volumes.domain.Volume>`
|
||||
:param name: str (optional)
|
||||
New volume name
|
||||
:param labels: Dict[str, str] (optional)
|
||||
User-defined labels (key-value pairs)
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {}
|
||||
if name is not None:
|
||||
data.update({"name": name})
|
||||
if labels is not None:
|
||||
data.update({"labels": labels})
|
||||
response = self._client.request(
|
||||
url=f"/volumes/{volume.id}",
|
||||
method="PUT",
|
||||
json=data,
|
||||
)
|
||||
return BoundVolume(self, response["volume"])
|
||||
|
||||
def delete(self, volume):
|
||||
# type: (Union[Volume, BoundVolume]) -> BoundAction
|
||||
"""Deletes a volume. All volume data is irreversibly destroyed. The volume must not be attached to a server and it must not have delete protection enabled.
|
||||
|
||||
:param volume: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>` or :class:`Volume <hcloud.volumes.domain.Volume>`
|
||||
:return: boolean
|
||||
"""
|
||||
self._client.request(url=f"/volumes/{volume.id}", method="DELETE")
|
||||
return True
|
||||
|
||||
def resize(self, volume, size):
|
||||
# type: (Union[Volume, BoundVolume], int) -> BoundAction
|
||||
"""Changes the size of a volume. Note that downsizing a volume is not possible.
|
||||
|
||||
:param volume: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>` or :class:`Volume <hcloud.volumes.domain.Volume>`
|
||||
:param size: int
|
||||
New volume size in GB (must be greater than current size)
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = self._client.request(
|
||||
url=f"/volumes/{volume.id}/actions/resize",
|
||||
json={"size": size},
|
||||
method="POST",
|
||||
)
|
||||
return BoundAction(self._client.actions, data["action"])
|
||||
|
||||
def attach(self, volume, server, automount=None):
|
||||
# type: (Union[Volume, BoundVolume], Union[Server, BoundServer], Optional[bool]) -> BoundAction
|
||||
"""Attaches a volume to a server. Works only if the server is in the same location as the volume.
|
||||
|
||||
:param volume: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>` or :class:`Volume <hcloud.volumes.domain.Volume>`
|
||||
:param server: :class:`BoundServer <hcloud.servers.client.BoundServer>` or :class:`Server <hcloud.servers.domain.Server>`
|
||||
:param automount: boolean
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {"server": server.id}
|
||||
if automount is not None:
|
||||
data["automount"] = automount
|
||||
|
||||
data = self._client.request(
|
||||
url=f"/volumes/{volume.id}/actions/attach",
|
||||
json=data,
|
||||
method="POST",
|
||||
)
|
||||
return BoundAction(self._client.actions, data["action"])
|
||||
|
||||
def detach(self, volume):
|
||||
# type: (Union[Volume, BoundVolume]) -> BoundAction
|
||||
"""Detaches a volume from the server it’s attached to. You may attach it to a server again at a later time.
|
||||
|
||||
:param volume: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>` or :class:`Volume <hcloud.volumes.domain.Volume>`
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = self._client.request(
|
||||
url=f"/volumes/{volume.id}/actions/detach",
|
||||
method="POST",
|
||||
)
|
||||
return BoundAction(self._client.actions, data["action"])
|
||||
|
||||
def change_protection(self, volume, delete=None):
|
||||
# type: (Union[Volume, BoundVolume], Optional[bool], Optional[bool]) -> BoundAction
|
||||
"""Changes the protection configuration of a volume.
|
||||
|
||||
:param volume: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>` or :class:`Volume <hcloud.volumes.domain.Volume>`
|
||||
:param delete: boolean
|
||||
If True, prevents the volume from being deleted
|
||||
:return: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
"""
|
||||
data = {}
|
||||
if delete is not None:
|
||||
data.update({"delete": delete})
|
||||
|
||||
response = self._client.request(
|
||||
url="/volumes/{volume_id}/actions/change_protection".format(
|
||||
volume_id=volume.id
|
||||
),
|
||||
method="POST",
|
||||
json=data,
|
||||
)
|
||||
return BoundAction(self._client.actions, response["action"])
|
103
plugins/module_utils/vendor/hcloud/volumes/domain.py
vendored
Normal file
103
plugins/module_utils/vendor/hcloud/volumes/domain.py
vendored
Normal file
|
@ -0,0 +1,103 @@
|
|||
try:
|
||||
from dateutil.parser import isoparse
|
||||
except ImportError:
|
||||
isoparse = None
|
||||
|
||||
from ..core.domain import BaseDomain, DomainIdentityMixin
|
||||
|
||||
|
||||
class Volume(BaseDomain, DomainIdentityMixin):
|
||||
"""Volume Domain
|
||||
|
||||
:param id: int
|
||||
ID of the Volume
|
||||
:param name: str
|
||||
Name of the Volume
|
||||
:param server: :class:`BoundServer <hcloud.servers.client.BoundServer>`, None
|
||||
Server the Volume is attached to, None if it is not attached at all.
|
||||
:param created: datetime
|
||||
Point in time when the Volume was created
|
||||
:param location: :class:`BoundLocation <hcloud.locations.client.BoundLocation>`
|
||||
Location of the Volume. Volume can only be attached to Servers in the same location.
|
||||
:param size: int
|
||||
Size in GB of the Volume
|
||||
:param linux_device: str
|
||||
Device path on the file system for the Volume
|
||||
:param protection: dict
|
||||
Protection configuration for the Volume
|
||||
:param labels: dict
|
||||
User-defined labels (key-value pairs)
|
||||
:param status: str
|
||||
Current status of the volume Choices: `creating`, `available`
|
||||
:param format: str, None
|
||||
Filesystem of the volume if formatted on creation, None if not formatted on creation.
|
||||
"""
|
||||
|
||||
STATUS_CREATING = "creating"
|
||||
"""Volume Status creating"""
|
||||
STATUS_AVAILABLE = "available"
|
||||
"""Volume Status available"""
|
||||
|
||||
__slots__ = (
|
||||
"id",
|
||||
"name",
|
||||
"server",
|
||||
"location",
|
||||
"size",
|
||||
"linux_device",
|
||||
"format",
|
||||
"protection",
|
||||
"labels",
|
||||
"status",
|
||||
"created",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id,
|
||||
name=None,
|
||||
server=None,
|
||||
created=None,
|
||||
location=None,
|
||||
size=None,
|
||||
linux_device=None,
|
||||
format=None,
|
||||
protection=None,
|
||||
labels=None,
|
||||
status=None,
|
||||
):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.server = server
|
||||
self.created = isoparse(created) if created else None
|
||||
self.location = location
|
||||
self.size = size
|
||||
self.linux_device = linux_device
|
||||
self.format = format
|
||||
self.protection = protection
|
||||
self.labels = labels
|
||||
self.status = status
|
||||
|
||||
|
||||
class CreateVolumeResponse(BaseDomain):
|
||||
"""Create Volume Response Domain
|
||||
|
||||
:param volume: :class:`BoundVolume <hcloud.volumes.client.BoundVolume>`
|
||||
The created volume
|
||||
:param action: :class:`BoundAction <hcloud.actions.client.BoundAction>`
|
||||
The action that shows the progress of the Volume Creation
|
||||
:param next_actions: List[:class:`BoundAction <hcloud.actions.client.BoundAction>`]
|
||||
List of actions that are performed after the creation, like attaching to a server
|
||||
"""
|
||||
|
||||
__slots__ = ("volume", "action", "next_actions")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
volume, # type: BoundVolume
|
||||
action, # type: BoundAction
|
||||
next_actions, # type: List[BoundAction]
|
||||
):
|
||||
self.volume = volume
|
||||
self.action = action
|
||||
self.next_actions = next_actions
|
|
@ -171,13 +171,12 @@ import time
|
|||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud
|
||||
|
||||
try:
|
||||
from hcloud import APIException
|
||||
from hcloud.firewalls.domain import FirewallRule
|
||||
except ImportError:
|
||||
APIException = None
|
||||
FirewallRule = None
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.vendor.hcloud import (
|
||||
APIException,
|
||||
)
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.vendor.hcloud.firewalls.domain import (
|
||||
FirewallRule,
|
||||
)
|
||||
|
||||
|
||||
class AnsibleHcloudFirewall(Hcloud):
|
||||
|
|
|
@ -282,17 +282,15 @@ hcloud_load_balancer_service:
|
|||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud
|
||||
|
||||
try:
|
||||
from hcloud import APIException
|
||||
from hcloud.load_balancers.domain import (
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.vendor.hcloud import (
|
||||
APIException,
|
||||
)
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.vendor.hcloud.load_balancers.domain import (
|
||||
LoadBalancerHealtCheckHttp,
|
||||
LoadBalancerHealthCheck,
|
||||
LoadBalancerService,
|
||||
LoadBalancerServiceHttp,
|
||||
)
|
||||
except ImportError:
|
||||
APIException = None
|
||||
|
||||
|
||||
class AnsibleHcloudLoadBalancerService(Hcloud):
|
||||
|
|
|
@ -138,17 +138,11 @@ hcloud_load_balancer_target:
|
|||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud
|
||||
|
||||
try:
|
||||
from hcloud.load_balancers.domain import (
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.vendor.hcloud.load_balancers.domain import (
|
||||
LoadBalancerTarget,
|
||||
LoadBalancerTargetIP,
|
||||
LoadBalancerTargetLabelSelector,
|
||||
)
|
||||
except ImportError:
|
||||
LoadBalancerTarget = None
|
||||
LoadBalancerTargetLabelSelector = None
|
||||
LoadBalancerTargetIP = None
|
||||
|
||||
|
||||
class AnsibleHcloudLoadBalancerTarget(Hcloud):
|
||||
|
|
|
@ -90,11 +90,9 @@ hcloud_route:
|
|||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud
|
||||
|
||||
try:
|
||||
from hcloud.networks.domain import NetworkRoute
|
||||
except ImportError:
|
||||
NetworkRoute = None
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.vendor.hcloud.networks.domain import (
|
||||
NetworkRoute,
|
||||
)
|
||||
|
||||
|
||||
class AnsibleHcloudRoute(Hcloud):
|
||||
|
|
|
@ -333,18 +333,19 @@ from datetime import datetime, timedelta, timezone
|
|||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud
|
||||
|
||||
try:
|
||||
from hcloud.firewalls.domain import FirewallResource
|
||||
from hcloud.servers.domain import Server, ServerCreatePublicNetwork
|
||||
from hcloud.ssh_keys.domain import SSHKey
|
||||
from hcloud.volumes.domain import Volume
|
||||
except ImportError:
|
||||
Volume = None
|
||||
SSHKey = None
|
||||
Server = None
|
||||
ServerCreatePublicNetwork = None
|
||||
FirewallResource = None
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.vendor.hcloud.firewalls.domain import (
|
||||
FirewallResource,
|
||||
)
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.vendor.hcloud.servers.domain import (
|
||||
Server,
|
||||
ServerCreatePublicNetwork,
|
||||
)
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.vendor.hcloud.ssh_keys.domain import (
|
||||
SSHKey,
|
||||
)
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.vendor.hcloud.volumes.domain import (
|
||||
Volume,
|
||||
)
|
||||
|
||||
|
||||
class AnsibleHcloudServer(Hcloud):
|
||||
|
|
|
@ -115,11 +115,9 @@ hcloud_server_network:
|
|||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud
|
||||
|
||||
try:
|
||||
from hcloud import APIException
|
||||
except ImportError:
|
||||
APIException = None
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.vendor.hcloud import (
|
||||
APIException,
|
||||
)
|
||||
|
||||
|
||||
class AnsibleHcloudServerNetwork(Hcloud):
|
||||
|
|
|
@ -127,11 +127,9 @@ hcloud_subnetwork:
|
|||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud
|
||||
|
||||
try:
|
||||
from hcloud.networks.domain import NetworkSubnet
|
||||
except ImportError:
|
||||
NetworkSubnet = None
|
||||
from ansible_collections.hetzner.hcloud.plugins.module_utils.vendor.hcloud.networks.domain import (
|
||||
NetworkSubnet,
|
||||
)
|
||||
|
||||
|
||||
class AnsibleHcloudSubnetwork(Hcloud):
|
||||
|
|
103
scripts/vendor.py
Executable file
103
scripts/vendor.py
Executable file
|
@ -0,0 +1,103 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
Fetch and bundles the hcloud package inside the collection.
|
||||
|
||||
Fetch the desired version `HCLOUD_VERSION` from https://github.com/hetznercloud/hcloud-python
|
||||
`HCLOUD_SOURCE_URL` using git, apply some code modifications to comply with ansible,
|
||||
move the modified files at the vendor location `HCLOUD_VENDOR_PATH`.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import re
|
||||
from pathlib import Path
|
||||
from shutil import move, rmtree
|
||||
from subprocess import check_call
|
||||
from tempfile import TemporaryDirectory
|
||||
from textwrap import dedent
|
||||
|
||||
logger = logging.getLogger("vendor")
|
||||
|
||||
HCLOUD_SOURCE_URL = "https://github.com/hetznercloud/hcloud-python"
|
||||
HCLOUD_VERSION = "v1.24.0"
|
||||
HCLOUD_VENDOR_PATH = "plugins/module_utils/vendor/hcloud"
|
||||
|
||||
|
||||
def apply_code_modifications(source_path: Path):
|
||||
# The ansible galaxy-importer consider __version___.py to be an invalid filename in module_utils/
|
||||
# Move the __version__.py file to _version.py
|
||||
move(source_path / "__version__.py", source_path / "_version.py")
|
||||
|
||||
for file in source_path.rglob("*.py"):
|
||||
content = file.read_text()
|
||||
content_orig = content
|
||||
|
||||
# Move the __version__.py file to _version.py
|
||||
content = re.sub(
|
||||
r"from .__version__ import VERSION",
|
||||
r"from ._version import VERSION",
|
||||
content,
|
||||
)
|
||||
|
||||
# Wrap requests imports
|
||||
content = re.sub(
|
||||
r"import requests",
|
||||
dedent(
|
||||
r"""
|
||||
try:
|
||||
import requests
|
||||
except ImportError:
|
||||
requests = None
|
||||
"""
|
||||
).strip(),
|
||||
content,
|
||||
)
|
||||
|
||||
# Wrap dateutil imports
|
||||
content = re.sub(
|
||||
r"from dateutil.parser import isoparse",
|
||||
dedent(
|
||||
r"""
|
||||
try:
|
||||
from dateutil.parser import isoparse
|
||||
except ImportError:
|
||||
isoparse = None
|
||||
"""
|
||||
).strip(),
|
||||
content,
|
||||
)
|
||||
|
||||
# Remove requests.Response typings
|
||||
content = re.sub(
|
||||
r": requests\.Response",
|
||||
r"",
|
||||
content,
|
||||
)
|
||||
|
||||
if content != content_orig:
|
||||
logger.info("Applied code modifications on %s", file)
|
||||
|
||||
file.write_text(content)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
with TemporaryDirectory() as tmp_dir:
|
||||
tmp_dir_path = Path(tmp_dir)
|
||||
logger.info("Created temporary directory %s", tmp_dir_path)
|
||||
|
||||
check_call(["git", "clone", "--depth=1", "--branch", HCLOUD_VERSION, HCLOUD_SOURCE_URL, tmp_dir_path])
|
||||
logger.info("Cloned the source files in %s", tmp_dir_path)
|
||||
|
||||
apply_code_modifications(tmp_dir_path / "hcloud")
|
||||
logger.info("Applied code modifications on the source files")
|
||||
|
||||
rmtree(HCLOUD_VENDOR_PATH)
|
||||
move(tmp_dir_path / "hcloud", HCLOUD_VENDOR_PATH)
|
||||
logger.info("Bundled the modified sources files in the collection")
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(level=logging.INFO, format="%(levelname)-8s: %(message)s")
|
||||
raise SystemExit(main())
|
|
@ -1 +1,2 @@
|
|||
hcloud >= 1.10.0 # minimum version
|
||||
python-dateutil>=2.7.5
|
||||
requests>=2.20
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
netaddr
|
||||
hcloud
|
||||
python-dateutil
|
||||
requests
|
||||
|
|
|
@ -59,7 +59,8 @@ retry ansible-galaxy -vvv collection install community.general
|
|||
retry ansible-galaxy -vvv collection install ansible.netcommon
|
||||
retry ansible-galaxy -vvv collection install community.internal_test_tools
|
||||
retry pip install netaddr --disable-pip-version-check
|
||||
retry pip install hcloud
|
||||
retry pip install python-dateutil
|
||||
retry pip install requests
|
||||
retry pip install rstcheck
|
||||
# END: HACK
|
||||
|
||||
|
|
|
@ -43,5 +43,7 @@ pip install pylint==2.5.3
|
|||
# shellcheck disable=SC2086
|
||||
ansible-test sanity --color -v --junit ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} \
|
||||
--base-branch "${base_branch}" \
|
||||
--exclude plugins/module_utils/vendor/ \
|
||||
--exclude scripts/ \
|
||||
--exclude tests/utils/ \
|
||||
"${options[@]}" --allow-disabled
|
||||
|
|
|
@ -24,4 +24,6 @@ fi
|
|||
# shellcheck disable=SC2086
|
||||
ansible-test sanity --color -v --junit ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} \
|
||||
--docker --base-branch "${base_branch}" \
|
||||
--exclude plugins/module_utils/vendor/ \
|
||||
--exclude scripts/ \
|
||||
--allow-disabled
|
||||
|
|
|
@ -77,7 +77,8 @@ fi
|
|||
retry ansible-galaxy -vvv collection install community.general
|
||||
retry ansible-galaxy -vvv collection install ansible.netcommon
|
||||
|
||||
retry pip install hcloud
|
||||
retry pip install python-dateutil
|
||||
retry pip install requests
|
||||
retry pip install netaddr --disable-pip-version-check
|
||||
retry ansible-galaxy -vvv collection install community.internal_test_tools
|
||||
# END: HACK
|
||||
|
|
Loading…
Reference in a new issue