diff --git a/octavia/db/base_models.py b/octavia/db/base_models.py index b5cd75e1dc..f2722c2145 100644 --- a/octavia/db/base_models.py +++ b/octavia/db/base_models.py @@ -132,6 +132,13 @@ class OctaviaBase(models.ModelBase): query = query.join(getattr(model, k)).filter_by(**v) return query + def __repr__(self): + params = sorted( + (k, getattr(self, k)) for k in self.__mapper__.columns.keys() + ) + params = ", ".join(f"{k}={v!r}" for k, v in params) + return f"{self.__class__.__name__}({params})" + class LookupTableMixin(object): """Mixin to add to classes that are lookup tables.""" diff --git a/octavia/db/models.py b/octavia/db/models.py index 61d4e34c4b..cd36f1c228 100644 --- a/octavia/db/models.py +++ b/octavia/db/models.py @@ -237,6 +237,15 @@ class Member(base_models.BASE, base_models.IdMixin, base_models.ProjectMixin, primaryjoin='and_(foreign(Tags.resource_id)==Member.id)' ) + def __str__(self): + return (f"Member(id={self.id!r}, name={self.name!r}, " + f"project_id={self.project_id!r}, " + f"provisioning_status={self.provisioning_status!r}, " + f"ip_address={self.ip_address!r}, " + f"protocol_port={self.protocol_port!r}, " + f"operating_status={self.operating_status!r}, " + f"weight={self.weight!r})") + class HealthMonitor(base_models.BASE, base_models.IdMixin, base_models.ProjectMixin, models.TimestampMixin, @@ -293,6 +302,11 @@ class HealthMonitor(base_models.BASE, base_models.IdMixin, http_version = sa.Column(sa.Float, nullable=True) domain_name = sa.Column(sa.String(255), nullable=True) + def __str__(self): + return (f"HealthMonitor(id={self.id!r}, name={self.name!r}, " + f"project_id={self.project_id!r}, type={self.type!r}, " + f"enabled={self.enabled!r})") + class Pool(base_models.BASE, base_models.IdMixin, base_models.ProjectMixin, models.TimestampMixin, base_models.NameMixin, base_models.TagMixin): @@ -372,6 +386,14 @@ class Pool(base_models.BASE, base_models.IdMixin, base_models.ProjectMixin, _l_ids.append(li.id) return _listeners + def __str__(self): + return (f"Pool(id={self.id!r}, name={self.name!r}, " + f"project_id={self.project_id!r}, " + f"provisioning_status={self.provisioning_status!r}, " + f"protocol={self.protocol!r}, " + f"lb_algorithm={self.lb_algorithm!r}, " + f"enabled={self.enabled!r})") + class LoadBalancer(base_models.BASE, base_models.IdMixin, base_models.ProjectMixin, models.TimestampMixin, @@ -425,6 +447,13 @@ class LoadBalancer(base_models.BASE, base_models.IdMixin, name="fk_load_balancer_availability_zone_name"), nullable=True) + def __str__(self): + return (f"LoadBalancer(id={self.id!r}, name={self.name!r}, " + f"project_id={self.project_id!r}, vip={self.vip!r}, " + f"provisioning_status={self.provisioning_status!r}, " + f"operating_status={self.operating_status!r}, " + f"provider={self.provider!r})") + class VRRPGroup(base_models.BASE): @@ -574,6 +603,13 @@ class Listener(base_models.BASE, base_models.IdMixin, 'ListenerCidr', cascade='all,delete-orphan', uselist=True, backref=orm.backref('listener', uselist=False)) + def __str__(self): + return (f"Listener(id={self.id!r}, " + f"default_pool={self.default_pool!r}, name={self.name!r}, " + f"project_id={self.project_id!r}, protocol={self.protocol!r}, " + f"protocol_port={self.protocol_port!r}, " + f"enabled={self.enabled!r})") + class SNI(base_models.BASE): @@ -630,6 +666,12 @@ class Amphora(base_models.BASE, base_models.IdMixin, models.TimestampMixin): back_populates='amphorae') compute_flavor = sa.Column(sa.String(255), nullable=True) + def __str__(self): + return (f"Amphora(id={self.id!r}, load_balancer_id=" + f"{self.load_balancer_id!r}, status={self.status!r}, " + f"role={self.role!r}, lb_network_ip={self.lb_network_ip!r}, " + f"vrrp_ip={self.vrrp_ip!r})") + class AmphoraHealth(base_models.BASE): __data_model__ = data_models.AmphoraHealth @@ -692,6 +734,12 @@ class L7Rule(base_models.BASE, base_models.IdMixin, base_models.ProjectMixin, primaryjoin='and_(foreign(Tags.resource_id)==L7Rule.id)' ) + def __str__(self): + return (f"L7Rule(id={self.id!r}, project_id={self.project_id!r}, " + f"provisioning_status={self.provisioning_status!r}, " + f"type={self.type!r}, key={self.key!r}, value={self.value!r}, " + f"invert={self.invert!r}, enabled={self.enabled!r})") + class L7Policy(base_models.BASE, base_models.IdMixin, base_models.ProjectMixin, models.TimestampMixin, base_models.NameMixin, @@ -751,6 +799,13 @@ class L7Policy(base_models.BASE, base_models.IdMixin, base_models.ProjectMixin, primaryjoin='and_(foreign(Tags.resource_id)==L7Policy.id)' ) + def __str__(self): + return (f"L7Policy(id={self.id!r}, name={self.name!r}, " + f"project_id={self.project_id!r}, " + f"provisioning_status={self.provisioning_status!r}, " + f"action={self.action!r}, position={self.position!r}, " + f"enabled={self.enabled!r})") + class Quotas(base_models.BASE): @@ -776,6 +831,14 @@ class Quotas(base_models.BASE): in_use_l7policy = sa.Column(sa.Integer(), nullable=True) in_use_l7rule = sa.Column(sa.Integer(), nullable=True) + def __str__(self): + return (f"Quotas(project_id={self.project_id!r}, " + f"load_balancer={self.load_balancer!r}, " + f"listener={self.listener!r}, pool={self.pool!r}, " + f"health_monitor={self.health_monitor!r}, " + f"member={self.member!r}, l7policy={self.l7policy!r}, " + f"l7rule={self.l7rule!r})") + class FlavorProfile(base_models.BASE, base_models.IdMixin, base_models.NameMixin): diff --git a/octavia/tests/functional/db/test_models.py b/octavia/tests/functional/db/test_models.py index 60bc8d9d4a..ea549e0d82 100644 --- a/octavia/tests/functional/db/test_models.py +++ b/octavia/tests/functional/db/test_models.py @@ -197,11 +197,21 @@ class ModelTestMixin(object): kwargs = {'listener_id': listener_id, 'cidr': cidr} return self._insert(session, models.ListenerCidr, kwargs) + def create_quotas(self, session, **overrides): + kwargs = {"project_id": self.FAKE_UUID_1} + kwargs.update(overrides) + return self._insert(session, models.Quotas, kwargs) + class PoolModelTest(base.OctaviaDBTestBase, ModelTestMixin): def test_create(self): pool = self.create_pool(self.session) + self.assertEqual(f"Pool(id={pool.id!r}, name=None, " + f"project_id={pool.project_id!r}, " + f"provisioning_status='ACTIVE', protocol='HTTP', " + f"lb_algorithm='LEAST_CONNECTIONS', enabled=True)", + str(pool)) self.assertIsNotNone(pool.created_at) self.assertIsNone(pool.updated_at) @@ -276,6 +286,12 @@ class MemberModelTest(base.OctaviaDBTestBase, ModelTestMixin): def test_create(self): member = self.create_member(self.session, self.pool.id) + self.assertEqual(f"Member(id={member.id!r}, name=None, " + f"project_id={member.project_id!r}, " + f"provisioning_status='ACTIVE', " + f"ip_address='10.0.0.1', protocol_port=80, " + f"operating_status='ONLINE', weight=None)", + str(member)) self.assertIsNotNone(member.created_at) self.assertIsNone(member.updated_at) @@ -321,7 +337,11 @@ class SessionPersistenceModelTest(base.OctaviaDBTestBase, ModelTestMixin): self.pool = self.create_pool(self.session) def test_create(self): - self.create_session_persistence(self.session, self.pool.id) + obj = self.create_session_persistence(self.session, self.pool.id) + self.assertEqual(f"SessionPersistence(cookie_name='cookie_name', " + f"persistence_granularity=None, " + f"persistence_timeout=None, pool_id={obj.pool_id!r}, " + f"type='HTTP_COOKIE')", str(obj)) def test_update(self): session_persistence = self.create_session_persistence(self.session, @@ -353,6 +373,10 @@ class ListenerModelTest(base.OctaviaDBTestBase, ModelTestMixin): def test_create(self): listener = self.create_listener(self.session) + self.assertEqual(f"Listener(id={listener.id!r}, default_pool=None, " + f"name=None, project_id={listener.project_id!r}, " + f"protocol='HTTP', protocol_port=80, enabled=True)", + str(listener)) self.assertIsNotNone(listener.created_at) self.assertIsNone(listener.updated_at) @@ -454,8 +478,12 @@ class ListenerStatisticsModelTest(base.OctaviaDBTestBase, ModelTestMixin): self.amphora = self.create_amphora(self.session) def test_create(self): - self.create_listener_statistics(self.session, self.listener.id, - self.amphora.id) + obj = self.create_listener_statistics(self.session, self.listener.id, + self.amphora.id) + self.assertEqual(f"ListenerStatistics(active_connections=0, " + f"amphora_id={obj.amphora_id!r}, bytes_in=0, " + f"bytes_out=0, listener_id={obj.listener_id!r}, " + f"request_errors=0, total_connections=0)", str(obj)) def test_create_with_negative_int(self): overrides = {'bytes_in': -1} @@ -490,7 +518,10 @@ class HealthMonitorModelTest(base.OctaviaDBTestBase, ModelTestMixin): self.pool = self.create_pool(self.session) def test_create(self): - self.create_health_monitor(self.session, self.pool.id) + obj = self.create_health_monitor(self.session, self.pool.id) + self.assertEqual(f"HealthMonitor(id={obj.id!r}, name=None, " + f"project_id={obj.project_id!r}, type='HTTP', " + f"enabled=True)", str(obj)) def test_update(self): health_monitor = self.create_health_monitor(self.session, self.pool.id) @@ -524,6 +555,11 @@ class LoadBalancerModelTest(base.OctaviaDBTestBase, ModelTestMixin): def test_create(self): load_balancer = self.create_load_balancer(self.session) + self.assertEqual(f"LoadBalancer(id={load_balancer.id!r}, name=None, " + f"project_id={load_balancer.project_id!r}, " + f"vip=None, provisioning_status='ACTIVE', " + f"operating_status='ONLINE', provider=None)", + str(load_balancer)) self.assertIsNotNone(load_balancer.created_at) self.assertIsNone(load_balancer.updated_at) @@ -582,7 +618,11 @@ class VipModelTest(base.OctaviaDBTestBase, ModelTestMixin): self.load_balancer = self.create_load_balancer(self.session) def test_create(self): - self.create_vip(self.session, self.load_balancer.id) + obj = self.create_vip(self.session, self.load_balancer.id) + self.assertEqual(f"Vip(ip_address=None, " + f"load_balancer_id={obj.load_balancer_id!r}, " + f"network_id=None, octavia_owned=None, port_id=None, " + f"qos_policy_id=None, subnet_id=None)", str(obj)) def test_update(self): vip = self.create_vip(self.session, self.load_balancer.id) @@ -616,7 +656,11 @@ class SNIModelTest(base.OctaviaDBTestBase, ModelTestMixin): self.listener = self.create_listener(self.session) def test_create(self): - self.create_sni(self.session, listener_id=self.listener.id) + obj = self.create_sni(self.session, listener_id=self.listener.id) + self.assertEqual(f"SNI(listener_id={obj.listener_id!r}, " + f"position=None, " + f"tls_container_id={obj.tls_container_id!r})", + str(obj)) def test_update(self): sni = self.create_sni(self.session, listener_id=self.listener.id) @@ -649,7 +693,11 @@ class AmphoraModelTest(base.OctaviaDBTestBase, ModelTestMixin): self.load_balancer = self.create_load_balancer(self.session) def test_create(self): - self.create_amphora(self.session) + obj = self.create_amphora(self.session) + self.assertEqual(f"Amphora(id={obj.id!r}, load_balancer_id=None, " + f"status='ACTIVE', role=None, " + f"lb_network_ip='10.0.0.1', vrrp_ip='10.0.0.1')", + str(obj)) def test_update(self): amphora = self.create_amphora( @@ -684,7 +732,10 @@ class AmphoraHealthModelTest(base.OctaviaDBTestBase, ModelTestMixin): self.amphora = self.create_amphora(self.session) def test_create(self): - self.create_amphora_health(self.session) + obj = self.create_amphora_health(self.session) + self.assertEqual(f"AmphoraHealth(amphora_id={obj.amphora_id!r}, " + f"busy=True, last_update={obj.last_update!r})", + str(obj)) def test_update(self): amphora_health = self.create_amphora_health(self.session) @@ -715,6 +766,10 @@ class L7PolicyModelTest(base.OctaviaDBTestBase, ModelTestMixin): def test_create(self): l7policy = self.create_l7policy(self.session, self.listener.id) + self.assertEqual(f"L7Policy(id={l7policy.id!r}, name=None, " + f"project_id=None, provisioning_status='ACTIVE', " + f"action='REJECT', position=1, enabled=True)", + str(l7policy)) self.assertIsInstance(l7policy, models.L7Policy) def test_update(self): @@ -836,6 +891,10 @@ class L7RuleModelTest(base.OctaviaDBTestBase, ModelTestMixin): def test_create(self): l7rule = self.create_l7rule(self.session, self.l7policy.id) + self.assertEqual(f"L7Rule(id={l7rule.id!r}, project_id=None, " + f"provisioning_status='ACTIVE', type='PATH', " + f"key=None, value='/api', invert=False, " + f"enabled=True)", str(l7rule)) self.assertIsInstance(l7rule, models.L7Rule) def test_update(self): @@ -1757,6 +1816,9 @@ class FlavorModelTest(base.OctaviaDBTestBase, ModelTestMixin): def test_create(self): flavor = self.create_flavor(self.session, self.profile.id) + self.assertEqual(f"Flavor(description='fake flavor', enabled=True, " + f"flavor_profile_id={flavor.flavor_profile_id!r}, " + f"id={flavor.id!r}, name='fake_flavor')", str(flavor)) self.assertIsNotNone(flavor.id) def test_delete(self): @@ -1776,6 +1838,9 @@ class FlavorProfileModelTest(base.OctaviaDBTestBase, ModelTestMixin): def test_create(self): fp = self.create_flavor_profile(self.session) + self.assertEqual(f"FlavorProfile(flavor_data={fp.flavor_data!r}, " + f"id={fp.id!r}, name='fake_profile', " + f"provider_name='fake_provider')", str(fp)) self.assertIsNotNone(fp.id) def test_delete(self): @@ -1789,3 +1854,15 @@ class FlavorProfileModelTest(base.OctaviaDBTestBase, ModelTestMixin): new_fp = self.session.query( models.FlavorProfile).filter_by(id=id).first() self.assertIsNone(new_fp) + + +class QuotasModelTest(base.OctaviaDBTestBase, ModelTestMixin): + + def test_create(self): + obj = self.create_quotas(self.session, load_balancer=1, listener=2, + pool=3, health_monitor=4, member=5, + l7policy=6, l7rule=8) + self.assertEqual(f"Quotas(project_id={obj.project_id!r}, " + f"load_balancer=1, listener=2, pool=3, " + f"health_monitor=4, member=5, l7policy=6, l7rule=8)", + str(obj))