From 40e83d54572b684c5839abc73351ef3dec565b9f Mon Sep 17 00:00:00 2001 From: ezilber-akamai Date: Thu, 5 Jun 2025 14:50:24 -0400 Subject: [PATCH 1/2] Implemented support for VPC DBaaS Integration --- linode_api4/groups/database.py | 9 +++++++++ linode_api4/objects/database.py | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/linode_api4/groups/database.py b/linode_api4/groups/database.py index 9de02ac35..2de37d4ec 100644 --- a/linode_api4/groups/database.py +++ b/linode_api4/groups/database.py @@ -10,6 +10,7 @@ Database, DatabaseEngine, DatabaseType, + DatabasePrivateNetwork, MySQLDatabase, PostgreSQLDatabase, drop_null_keys, @@ -126,6 +127,7 @@ def mysql_create( engine, ltype, engine_config: Union[MySQLDatabaseConfigOptions, Dict[str, Any]] = None, + private_network: Union[DatabasePrivateNetwork, Dict[str, Any]] = None, **kwargs, ): """ @@ -159,6 +161,8 @@ def mysql_create( :type ltype: str or Type :param engine_config: The configuration options for this MySQL cluster :type engine_config: Dict[str, Any] or MySQLDatabaseConfigOptions + :param private_network: The private network settings to use for this cluster + :type private_network: Dict[str, Any] or DatabasePrivateNetwork """ params = { @@ -167,6 +171,7 @@ def mysql_create( "engine": engine, "type": ltype, "engine_config": engine_config, + "private_network": private_network, } params.update(kwargs) @@ -262,6 +267,7 @@ def postgresql_create( engine_config: Union[ PostgreSQLDatabaseConfigOptions, Dict[str, Any] ] = None, + private_network: Union[DatabasePrivateNetwork, Dict[str, Any]] = None, **kwargs, ): """ @@ -295,6 +301,8 @@ def postgresql_create( :type ltype: str or Type :param engine_config: The configuration options for this PostgreSQL cluster :type engine_config: Dict[str, Any] or PostgreSQLDatabaseConfigOptions + :param private_network: The private network settings to use for this cluster + :type private_network: Dict[str, Any] or DatabasePrivateNetwork """ params = { @@ -303,6 +311,7 @@ def postgresql_create( "engine": engine, "type": ltype, "engine_config": engine_config, + "private_network": private_network, } params.update(kwargs) diff --git a/linode_api4/objects/database.py b/linode_api4/objects/database.py index 39249bbf9..e628fbdbd 100644 --- a/linode_api4/objects/database.py +++ b/linode_api4/objects/database.py @@ -73,6 +73,15 @@ def invalidate(self): Base.invalidate(self) +@dataclass +class DatabasePrivateNetwork(JSONObject): + """ + DatabasePrivateNetwork is used to specify + a Database Cluster's private network settings during its creation. + """ + vpc_id: int + subnet_id: int + public_access: bool @deprecated( reason="Backups are not supported for non-legacy database clusters." @@ -304,6 +313,7 @@ class MySQLDatabase(Base): "engine_config": Property( mutable=True, json_object=MySQLDatabaseConfigOptions ), + "private_network": Property(mutable=True, json_object=DatabasePrivateNetwork), } @property @@ -470,6 +480,7 @@ class PostgreSQLDatabase(Base): "engine_config": Property( mutable=True, json_object=PostgreSQLDatabaseConfigOptions ), + "private_network": Property(mutable=True, json_object=DatabasePrivateNetwork), } @property @@ -636,6 +647,7 @@ class Database(Base): "updated": Property(), "updates": Property(), "version": Property(), + "private_network": Property(json_object=DatabasePrivateNetwork), } @property From 4864bd5c67cd0ea209217f35cd76d8a32237b2a1 Mon Sep 17 00:00:00 2001 From: ezilber-akamai Date: Fri, 6 Jun 2025 11:29:29 -0400 Subject: [PATCH 2/2] Added unit tests --- linode_api4/groups/database.py | 2 +- linode_api4/objects/database.py | 21 ++++++--- test/fixtures/databases_instances.json | 7 ++- test/fixtures/databases_mysql_instances.json | 5 ++ .../databases_postgresql_instances.json | 5 ++ test/unit/groups/database_test.py | 11 +++++ test/unit/objects/database_test.py | 46 +++++++++++++++++++ 7 files changed, 89 insertions(+), 8 deletions(-) diff --git a/linode_api4/groups/database.py b/linode_api4/groups/database.py index 2de37d4ec..9546100a8 100644 --- a/linode_api4/groups/database.py +++ b/linode_api4/groups/database.py @@ -9,8 +9,8 @@ from linode_api4.objects import ( Database, DatabaseEngine, - DatabaseType, DatabasePrivateNetwork, + DatabaseType, MySQLDatabase, PostgreSQLDatabase, drop_null_keys, diff --git a/linode_api4/objects/database.py b/linode_api4/objects/database.py index e628fbdbd..979990e8e 100644 --- a/linode_api4/objects/database.py +++ b/linode_api4/objects/database.py @@ -73,15 +73,18 @@ def invalidate(self): Base.invalidate(self) + @dataclass class DatabasePrivateNetwork(JSONObject): """ DatabasePrivateNetwork is used to specify a Database Cluster's private network settings during its creation. """ - vpc_id: int - subnet_id: int - public_access: bool + + vpc_id: Optional[int] = None + subnet_id: Optional[int] = None + public_access: Optional[bool] = None + @deprecated( reason="Backups are not supported for non-legacy database clusters." @@ -313,7 +316,9 @@ class MySQLDatabase(Base): "engine_config": Property( mutable=True, json_object=MySQLDatabaseConfigOptions ), - "private_network": Property(mutable=True, json_object=DatabasePrivateNetwork), + "private_network": Property( + mutable=True, json_object=DatabasePrivateNetwork, nullable=True + ), } @property @@ -480,7 +485,9 @@ class PostgreSQLDatabase(Base): "engine_config": Property( mutable=True, json_object=PostgreSQLDatabaseConfigOptions ), - "private_network": Property(mutable=True, json_object=DatabasePrivateNetwork), + "private_network": Property( + mutable=True, json_object=DatabasePrivateNetwork, nullable=True + ), } @property @@ -647,7 +654,9 @@ class Database(Base): "updated": Property(), "updates": Property(), "version": Property(), - "private_network": Property(json_object=DatabasePrivateNetwork), + "private_network": Property( + json_object=DatabasePrivateNetwork, nullable=True + ), } @property diff --git a/test/fixtures/databases_instances.json b/test/fixtures/databases_instances.json index 3b3f4d602..5e92515a5 100644 --- a/test/fixtures/databases_instances.json +++ b/test/fixtures/databases_instances.json @@ -27,7 +27,12 @@ "hour_of_day": 0, "week_of_month": null }, - "version": "8.0.26" + "version": "8.0.26", + "private_network": { + "vpc_id": 1234, + "subnet_id": 5678, + "public_access": true + } } ], "page": 1, diff --git a/test/fixtures/databases_mysql_instances.json b/test/fixtures/databases_mysql_instances.json index d6e3f2e64..e60bfe019 100644 --- a/test/fixtures/databases_mysql_instances.json +++ b/test/fixtures/databases_mysql_instances.json @@ -61,6 +61,11 @@ "tmp_table_size": 16777216, "wait_timeout": 28800 } + }, + "private_network": { + "vpc_id": 1234, + "subnet_id": 5678, + "public_access": true } } ], diff --git a/test/fixtures/databases_postgresql_instances.json b/test/fixtures/databases_postgresql_instances.json index 92d5ce945..47573aa12 100644 --- a/test/fixtures/databases_postgresql_instances.json +++ b/test/fixtures/databases_postgresql_instances.json @@ -83,6 +83,11 @@ }, "shared_buffers_percentage": 41.5, "work_mem": 4 + }, + "private_network": { + "vpc_id": 1234, + "subnet_id": 5678, + "public_access": true } } ], diff --git a/test/unit/groups/database_test.py b/test/unit/groups/database_test.py index 9647fed82..5e2964c8d 100644 --- a/test/unit/groups/database_test.py +++ b/test/unit/groups/database_test.py @@ -61,6 +61,9 @@ def test_get_databases(self): self.assertEqual(dbs[0].region, "us-east") self.assertEqual(dbs[0].updates.duration, 3) self.assertEqual(dbs[0].version, "8.0.26") + self.assertEqual(dbs[0].private_network.vpc_id, 1234) + self.assertEqual(dbs[0].private_network.subnet_id, 5678) + self.assertEqual(dbs[0].private_network.public_access, True) def test_database_instance(self): """ @@ -1338,6 +1341,10 @@ def test_get_mysql_instances(self): self.assertEqual(dbs[0].engine_config.mysql.tmp_table_size, 16777216) self.assertEqual(dbs[0].engine_config.mysql.wait_timeout, 28800) + self.assertEqual(dbs[0].private_network.vpc_id, 1234) + self.assertEqual(dbs[0].private_network.subnet_id, 5678) + self.assertEqual(dbs[0].private_network.public_access, True) + def test_get_postgresql_instances(self): """ Test that postgresql instances can be retrieved properly @@ -1452,3 +1459,7 @@ def test_get_postgresql_instances(self): self.assertEqual(dbs[0].engine_config.pg.track_io_timing, "off") self.assertEqual(dbs[0].engine_config.pg.wal_sender_timeout, 60000) self.assertEqual(dbs[0].engine_config.pg.wal_writer_delay, 50) + + self.assertEqual(dbs[0].private_network.vpc_id, 1234) + self.assertEqual(dbs[0].private_network.subnet_id, 5678) + self.assertEqual(dbs[0].private_network.public_access, True) diff --git a/test/unit/objects/database_test.py b/test/unit/objects/database_test.py index c5abe3a58..535b2a336 100644 --- a/test/unit/objects/database_test.py +++ b/test/unit/objects/database_test.py @@ -2,6 +2,7 @@ from test.unit.base import ClientBaseCase from linode_api4 import ( + DatabasePrivateNetwork, MySQLDatabaseConfigMySQLOptions, MySQLDatabaseConfigOptions, PostgreSQLDatabase, @@ -41,6 +42,11 @@ def test_create(self): ), binlog_retention_period=200, ), + private_network=DatabasePrivateNetwork( + vpc_id=1234, + subnet_id=5678, + public_access=True, + ), ) except Exception as e: logger.warning( @@ -61,6 +67,12 @@ def test_create(self): m.call_data["engine_config"]["binlog_retention_period"], 200 ) + self.assertEqual(m.call_data["private_network"]["vpc_id"], 1234) + self.assertEqual(m.call_data["private_network"]["subnet_id"], 5678) + self.assertEqual( + m.call_data["private_network"]["public_access"], True + ) + def test_update(self): """ Test that the MySQL database can be updated @@ -78,6 +90,11 @@ def test_update(self): mysql=MySQLDatabaseConfigMySQLOptions(connect_timeout=20), binlog_retention_period=200, ) + db.private_network = DatabasePrivateNetwork( + vpc_id=1234, + subnet_id=5678, + public_access=True, + ) db.save() @@ -93,6 +110,12 @@ def test_update(self): m.call_data["engine_config"]["binlog_retention_period"], 200 ) + self.assertEqual(m.call_data["private_network"]["vpc_id"], 1234) + self.assertEqual(m.call_data["private_network"]["subnet_id"], 5678) + self.assertEqual( + m.call_data["private_network"]["public_access"], True + ) + def test_list_backups(self): """ Test that MySQL backups list properly @@ -259,6 +282,11 @@ def test_create(self): ), work_mem=4, ), + private_network=DatabasePrivateNetwork( + vpc_id=1234, + subnet_id=5678, + public_access=True, + ), ) except Exception: pass @@ -302,6 +330,12 @@ def test_create(self): ) self.assertEqual(m.call_data["engine_config"]["work_mem"], 4) + self.assertEqual(m.call_data["private_network"]["vpc_id"], 1234) + self.assertEqual(m.call_data["private_network"]["subnet_id"], 5678) + self.assertEqual( + m.call_data["private_network"]["public_access"], True + ) + def test_update(self): """ Test that the PostgreSQL database can be updated @@ -322,6 +356,12 @@ def test_update(self): work_mem=4, ) + db.private_network = DatabasePrivateNetwork( + vpc_id=1234, + subnet_id=5678, + public_access=True, + ) + db.save() self.assertEqual(m.method, "put") @@ -337,6 +377,12 @@ def test_update(self): ) self.assertEqual(m.call_data["engine_config"]["work_mem"], 4) + self.assertEqual(m.call_data["private_network"]["vpc_id"], 1234) + self.assertEqual(m.call_data["private_network"]["subnet_id"], 5678) + self.assertEqual( + m.call_data["private_network"]["public_access"], True + ) + def test_list_backups(self): """ Test that PostgreSQL backups list properly