diff --git a/CHANGES.rst b/CHANGES.rst index 88b983e4bf..2ada299e81 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -14,6 +14,13 @@ Common Compute ~~~~~~~ +- [DigitalOcean] Include IPv6 addresses in ``Node.public_ips`` and + ``Node.private_ips``. Only the ``v4`` networks were inspected, and each + address overwrote the previous one, so a droplet's public IPv6 address was + silently dropped. + (GITHUB-1738) + [Sanjay Santhanam - @Sanjays2402] + - [SSH] Support paramiko 4 RSA key support has been removed as of paramiko 4, so only import it diff --git a/libcloud/compute/drivers/digitalocean.py b/libcloud/compute/drivers/digitalocean.py index 761199dcf3..d489bfb2a0 100644 --- a/libcloud/compute/drivers/digitalocean.py +++ b/libcloud/compute/drivers/digitalocean.py @@ -674,11 +674,11 @@ def _to_node(self, data): private_ips = [] public_ips = [] if networks: - for net in networks["v4"]: + for net in networks.get("v4", []) + networks.get("v6", []): if net["type"] == "private": - private_ips = [net["ip_address"]] + private_ips.append(net["ip_address"]) if net["type"] == "public": - public_ips = [net["ip_address"]] + public_ips.append(net["ip_address"]) extra = {} for key in extra_keys: diff --git a/libcloud/test/compute/test_digitalocean_v2.py b/libcloud/test/compute/test_digitalocean_v2.py index 7ff55ce881..84eb5f01d5 100644 --- a/libcloud/test/compute/test_digitalocean_v2.py +++ b/libcloud/test/compute/test_digitalocean_v2.py @@ -129,11 +129,41 @@ def test_list_nodes_success(self): nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 1) self.assertEqual(nodes[0].name, "ubuntu-s-1vcpu-1gb-sfo3-01") - self.assertEqual(nodes[0].public_ips, ["128.199.13.158"]) + self.assertEqual( + nodes[0].public_ips, + ["128.199.13.158", "2604:a880:4:1d0::142:9000"], + ) self.assertEqual(nodes[0].extra["image"]["id"], 69463186) self.assertEqual(nodes[0].extra["size_slug"], "s-1vcpu-1gb") self.assertEqual(len(nodes[0].extra["tags"]), 0) + def test_to_node_includes_ipv6_addresses(self): + # Both IPv4 and IPv6 addresses must be reported, and multiple + # addresses of the same type must all be kept. See GITHUB-1738. + data = { + "id": 1, + "name": "ipv6-droplet", + "status": "active", + "created_at": "2020-10-15T13:58:22Z", + "networks": { + "v4": [ + {"ip_address": "10.0.0.1", "type": "private"}, + {"ip_address": "10.0.0.2", "type": "private"}, + {"ip_address": "159.223.187.157", "type": "public"}, + {"ip_address": "159.223.187.158", "type": "public"}, + ], + "v6": [ + {"ip_address": "2604:a880:400:d0::1c58:e001", "type": "public"}, + ], + }, + } + node = self.driver._to_node(data) + self.assertEqual( + node.public_ips, + ["159.223.187.157", "159.223.187.158", "2604:a880:400:d0::1c58:e001"], + ) + self.assertEqual(node.private_ips, ["10.0.0.1", "10.0.0.2"]) + def test_list_nodes_fills_created_datetime(self): nodes = self.driver.list_nodes() self.assertEqual(nodes[0].created_at, datetime(2020, 10, 15, 13, 58, 22, tzinfo=UTC))