diff --git a/changelogs/fragments/server-type-deprecation.yml b/changelogs/fragments/server-type-deprecation.yml new file mode 100644 index 0000000..b08e637 --- /dev/null +++ b/changelogs/fragments/server-type-deprecation.yml @@ -0,0 +1,3 @@ +minor_changes: +- hcloud_server_type_info Return deprecation info for server types. +- hcloud_server Show warning if used server_type is deprecated. \ No newline at end of file diff --git a/plugins/module_utils/utc.py b/plugins/module_utils/utc.py new file mode 100644 index 0000000..012e39b --- /dev/null +++ b/plugins/module_utils/utc.py @@ -0,0 +1,24 @@ +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +from datetime import timedelta, tzinfo + +ZERO = timedelta(0) +HOUR = timedelta(hours=1) + + +class UTC(tzinfo): + """Custom UTC for compatibility with Python 2.7""" + + def utcoffset(self, dt): + return ZERO + + def tzname(self, dt): + return "UTC" + + def dst(self, dt): + return ZERO + + +utc = UTC() diff --git a/plugins/modules/hcloud_server.py b/plugins/modules/hcloud_server.py index 43c6518..4cfcc2d 100644 --- a/plugins/modules/hcloud_server.py +++ b/plugins/modules/hcloud_server.py @@ -335,7 +335,8 @@ hcloud_server: from ansible.module_utils.basic import AnsibleModule from ansible.module_utils._text import to_native from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud -from datetime import timedelta +from ansible_collections.hetzner.hcloud.plugins.module_utils.utc import utc +from datetime import timedelta, datetime try: from hcloud.volumes.domain import Volume @@ -535,8 +536,28 @@ class AnsibleHcloudServer(Hcloud): except Exception: self.module.fail_json(msg="server_type %s was not found" % self.module.params.get('server_type')) + self._check_and_warn_deprecated_server(server_type) + return server_type + def _check_and_warn_deprecated_server(self, server_type): + if server_type.deprecation is None: + return + + if server_type.deprecation.unavailable_after < datetime.now(utc): + self.module.warn( + 'Attention: The server plan %s is deprecated and can no longer be ordered. Existing servers of ' % server_type.name + + 'that plan will continue to work as before and no action is required on your part. It is possible ' + 'to migrate this server to another server plan by setting the server_type parameter on the hetzner.hcloud.hcloud_server module.' + ) + else: + self.module.warn( + 'Attention: The server plan % is deprecated and will no longer be available for order as of ' % server_type.name + + '%s. Existing servers of that plan will continue to work as before ' % server_type.deprecation.unavailable_after.strftime("%Y-%m-%d") + + 'and no action is required on your part. It is possible to migrate this server to another server plan by setting ' + 'the server_type parameter on the hetzner.hcloud.hcloud_server module.' + ) + def _get_placement_group(self): if self.module.params.get("placement_group") is None: return None @@ -731,20 +752,26 @@ class AnsibleHcloudServer(Hcloud): self._mark_as_changed() server_type = self.module.params.get("server_type") - if server_type is not None and self.hcloud_server.server_type.name != server_type: - self.stop_server_if_forced() + if server_type is not None: + if self.hcloud_server.server_type.name == server_type: + # Check if we should warn for using an deprecated server type + self._check_and_warn_deprecated_server(self.hcloud_server.server_type) - timeout = 100 - if self.module.params.get("upgrade_disk"): - timeout = ( - 1000 - ) # When we upgrade the disk to the resize progress takes some more time. - if not self.module.check_mode: - self.hcloud_server.change_type( - server_type=self._get_server_type(), - upgrade_disk=self.module.params.get("upgrade_disk"), - ).wait_until_finished(timeout) - self._mark_as_changed() + else: + # Server type should be changed + self.stop_server_if_forced() + + timeout = 100 + if self.module.params.get("upgrade_disk"): + timeout = ( + 1000 + ) # When we upgrade the disk to the resize progress takes some more time. + if not self.module.check_mode: + self.hcloud_server.change_type( + server_type=self._get_server_type(), + upgrade_disk=self.module.params.get("upgrade_disk"), + ).wait_until_finished(timeout) + self._mark_as_changed() if ( not self.module.check_mode and diff --git a/plugins/modules/hcloud_server_type_info.py b/plugins/modules/hcloud_server_type_info.py index dbe59d7..ddbddd1 100644 --- a/plugins/modules/hcloud_server_type_info.py +++ b/plugins/modules/hcloud_server_type_info.py @@ -103,6 +103,27 @@ hcloud_server_type_info: returned: always type: int sample: 21990232555520 + deprecation: + description: | + 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. + returned: success + type: dict + contains: + announced: + description: Date of when the deprecation was announced. + returned: success + type: str + sample: "2021-11-09T09:00:00+00:00" + unavailable_after: + description: | + 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. + returned: success + type: str + sample: "2021-12-01T00:00:00+00:00" + """ from ansible.module_utils.basic import AnsibleModule @@ -130,7 +151,11 @@ class AnsibleHcloudServerTypeInfo(Hcloud): "storage_type": to_native(server_type.storage_type), "cpu_type": to_native(server_type.cpu_type), "architecture": to_native(server_type.architecture), - "included_traffic": server_type.included_traffic + "included_traffic": server_type.included_traffic, + "deprecation": { + "announced": server_type.deprecation.announced.isoformat(), + "unavailable_after": server_type.deprecation.unavailable_after.isoformat(), + } if server_type.deprecation is not None else None }) return tmp diff --git a/tests/integration/targets/hcloud_server_type_info/defaults/main.yml b/tests/integration/targets/hcloud_server_type_info/defaults/main.yml index 05502aa..3106418 100644 --- a/tests/integration/targets/hcloud_server_type_info/defaults/main.yml +++ b/tests/integration/targets/hcloud_server_type_info/defaults/main.yml @@ -3,3 +3,5 @@ --- hcloud_server_type_name: "cx11" hcloud_server_type_id: 1 + +hcloud_server_type_id_deprecated: "2" # cx11-ceph \ No newline at end of file diff --git a/tests/integration/targets/hcloud_server_type_info/tasks/main.yml b/tests/integration/targets/hcloud_server_type_info/tasks/main.yml index 3c1fce8..d60256b 100644 --- a/tests/integration/targets/hcloud_server_type_info/tasks/main.yml +++ b/tests/integration/targets/hcloud_server_type_info/tasks/main.yml @@ -27,6 +27,7 @@ assert: that: - hcloud_server_types.hcloud_server_type_info|selectattr('name','equalto','{{ hcloud_server_type_name }}') | list | count == 1 + - hcloud_server_types.hcloud_server_type_info[0].deprecation is none # fails if cx11 is ever deprecated - name: test gather hcloud server type infos with correct id hcloud_server_type_info: @@ -36,3 +37,15 @@ assert: that: - hcloud_server_types.hcloud_server_type_info|selectattr('name','equalto','{{ hcloud_server_type_name }}') | list | count == 1 + +- name: test gather hcloud server type infos for deprecated server type + hcloud_server_type_info: + id: "{{hcloud_server_type_id_deprecated}}" + register: hcloud_server_types + +- name: verify test gather hcloud server type with deprecated field + assert: + that: + - hcloud_server_types.hcloud_server_type_info[0].deprecation is not none + - hcloud_server_types.hcloud_server_type_info[0].deprecation.announced == '2021-11-09T09:00:00+00:00' + - hcloud_server_types.hcloud_server_type_info[0].deprecation.unavailable_after == '2021-12-01T00:00:00+00:00'