Files
zuul/zuul/driver/gerrit/gerriteventgcloudpubsub.py
James E. Blair 36276806b8 Add gcloud pubsub support to Gerrit driver
This adds support for the Google Cloud Pub/Sub service to the
Gerrit driver.  It is very similar to Kafka.

Change-Id: Ib6e4dc01058b74e1042bfd1deb9fa4f3f43f7a36
2023-08-02 14:50:28 -07:00

96 lines
3.4 KiB
Python

# Copyright 2023 Acme Gating, LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import json
import google.api_core.exceptions
from google.oauth2 import service_account
from google.cloud import pubsub_v1
import logging
import pprint
import threading
class GerritGcloudPubsubEventListener:
log = logging.getLogger("zuul.GerritConnection.gcloudpubsub")
RECONNECTION_DELAY = 5
def __init__(self, gerrit_connection, connection_config):
self.gerrit_connection = gerrit_connection
project = connection_config.get('gcloud_pubsub_project')
topic = connection_config.get('gcloud_pubsub_topic', 'gerrit')
sub = connection_config.get('gcloud_pubsub_subscription_id', 'zuul')
key = connection_config.get('gcloud_pubsub_private_key')
self.kwargs = {}
if key:
with open(key) as keyfile:
info = json.load(keyfile)
credentials = service_account.Credentials.\
from_service_account_info(info)
self.kwargs['credentials'] = credentials
self.topic_name = f'projects/{project}/topics/{topic}'
self.subscription_name = f'projects/{project}/subscriptions/{sub}'
self._stop_event = threading.Event()
self._stopped = False
self._thread = None
self._future = None
def start(self):
self._thread = threading.Thread(target=self.run)
self._thread.start()
def stop(self):
self.log.debug("Stopping gcloud pubsub listener")
self._stopped = True
self._stop_event.set()
try:
if self._future:
self._future.cancel()
except Exception:
self.log.exception("Error canceling future:")
def join(self):
if self._thread:
self._thread.join()
def callback(self, message):
data = json.loads(message.data)
self.log.info("Received data from gcloud: \n%s" %
pprint.pformat(data))
self.gerrit_connection.addEvent(data)
message.ack()
def _run(self):
subscriber = pubsub_v1.SubscriberClient(**self.kwargs)
# So the unit tests can access it
self.subscriber = subscriber
with subscriber as client:
try:
client.create_subscription(name=self.subscription_name,
topic=self.topic_name)
except google.api_core.exceptions.AlreadyExists:
pass
self._future = client.subscribe(
self.subscription_name, self.callback)
self._future.result()
def run(self):
while not self._stopped:
try:
self._run()
except Exception:
self.log.exception(
"Exception in gcloud pubsub consumer with %s:",
self.gerrit_connection.connection_name)
self._stop_event.wait(self.RECONNECTION_DELAY)