Skip to content

Commit

Permalink
Fix SQLAlchemy 1.4 support
Browse files Browse the repository at this point in the history
* Fix list_metrics in amqp1d not properly
  validating list/set is not empty.

* Dont set database or drivername on  the
  new immutable SQLAlchemy URL object.

* Validate values is not None before using.

(cherry picked from commit 5ed9cc9)
  • Loading branch information
tobias-urdin authored and mergify-bot committed Jun 30, 2021
1 parent 76fa465 commit 58c78bf
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 13 deletions.
7 changes: 5 additions & 2 deletions gnocchi/amqp1d.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,17 @@ def _flush(self):
for host_id, measures_by_names in six.iteritems(self._measures):
resource = resources[host_id]

names = set(measures_by_names.keys())
mbn_keys = measures_by_names.keys()
names = (set(mbn_keys) if len(mbn_keys)
else set())

for name in names:
if name not in archive_policies:
archive_policies[name] = (
self.indexer.get_archive_policy_for_metric(name))
known_metrics = self.indexer.list_metrics(attribute_filter={
"and": [{"=": {"resource_id": resource.id}},
{"in": {"name": names}}]
{"in": {"name": list(names)}}]
})
known_names = set((m.name for m in known_metrics))
already_exists_names = []
Expand Down
39 changes: 30 additions & 9 deletions gnocchi/indexer/sqlalchemy.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,27 +260,46 @@ def _safe_execute(self, connection, works):
class SQLAlchemyIndexer(indexer.IndexerDriver):
_RESOURCE_TYPE_MANAGER = ResourceClassMapper()

@staticmethod
def _set_url_database(url, database):
if hasattr(url, "set"):
return url.set(database=database)
else:
url.database = database
return url

@staticmethod
def _set_url_drivername(url, drivername):
if hasattr(url, "set"):
return url.set(drivername=drivername)
else:
url.drivername = drivername
return url

@classmethod
def _create_new_database(cls, url):
"""Used by testing to create a new database."""
purl = sqlalchemy_url.make_url(
cls.dress_url(
url))
purl.database = purl.database + str(uuid.uuid4()).replace('-', '')
new_database = purl.database + str(uuid.uuid4()).replace('-', '')
purl = cls._set_url_database(purl, new_database)
new_url = str(purl)
sqlalchemy_utils.create_database(new_url)
return new_url

@staticmethod
def dress_url(url):
@classmethod
def dress_url(cls, url):
# If no explicit driver has been set, we default to pymysql
if url.startswith("mysql://"):
url = sqlalchemy_url.make_url(url)
url.drivername = "mysql+pymysql"
new_drivername = "mysql+pymysql"
url = cls._set_url_drivername(url, new_drivername)
return str(url)
if url.startswith("postgresql://"):
url = sqlalchemy_url.make_url(url)
url.drivername = "postgresql+psycopg2"
new_drivername = "postgresql+psycopg2"
url = cls._set_url_drivername(url, new_drivername)
return str(url)
return url

Expand Down Expand Up @@ -951,8 +970,6 @@ def delete_resources(self, resource_type='generic',
target_cls = self._resource_type_to_mappers(
session, resource_type)["resource"]

q = session.query(target_cls.id)

engine = session.connection()
try:
f = QueryTransformer.build_filter(engine.dialect.name,
Expand All @@ -964,12 +981,16 @@ def delete_resources(self, resource_type='generic',
raise indexer.ResourceAttributeError(resource_type,
e.attribute)

q = q.filter(f)
q1 = session.query(target_cls.id)
q1 = q1.filter(f)

session.query(Metric).filter(
Metric.resource_id.in_(q)
Metric.resource_id.in_(q1)
).update({"status": "delete"},
synchronize_session=False)

q = session.query(target_cls)
q = q.filter(f)
return q.delete(synchronize_session=False)

@retry_on_deadlock
Expand Down
8 changes: 6 additions & 2 deletions gnocchi/indexer/sqlalchemy_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,17 @@ def process_bind_param(self, value, dialect):
def process_result_value(self, value, dialect):
values = super(ArchivePolicyDefinitionType,
self).process_result_value(value, dialect)
if values is None:
return []
return [archive_policy.ArchivePolicyItem(**v) for v in values]


class SetType(sqlalchemy_utils.JSONType):
def process_result_value(self, value, dialect):
return set(super(SetType,
self).process_result_value(value, dialect))
values = super(SetType, self).process_result_value(value, dialect)
if values is None:
return set()
return set(values)


class ArchivePolicy(Base, GnocchiBase, archive_policy.ArchivePolicy):
Expand Down

0 comments on commit 58c78bf

Please sign in to comment.