Skip to content

Commit 6f06fbe

Browse files
tillahoffmannSergeyPirogov
authored andcommitted
Add Google Cloud PubSub emulator container. (#30)
1 parent 173d4ca commit 6f06fbe

File tree

9 files changed

+641
-331
lines changed

9 files changed

+641
-331
lines changed

Pipfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ pymongo = "*"
2222
selenium = "*"
2323
sqlalchemy = "*"
2424
pymysql = "*"
25-
25+
google-cloud-pubsub = "*"

Pipfile.lock

Lines changed: 540 additions & 325 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/google-cloud-emulators.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Google Cloud Emulators
2+
======================
3+
4+
Allows to spin up google cloud emulators, such as PubSub.
5+
6+
PubSub example
7+
--------------
8+
9+
::
10+
11+
def test_docker_run_pubsub():
12+
config = PubSubContainer('google/cloud-sdk:latest')
13+
with config as pubsub:
14+
publisher = pubsub.get_publisher()
15+
topic_path = publisher.topic_path(pubsub.project, "my-topic")
16+
topic = publisher.create_topic(topic_path)
17+
18+
The example will spin up a Google Cloud PubSub emulator that you can use for integration tests. The :code:`pubsub` instance provides convenience methods :code:`get_publisher` and :code:`get_subscriber` to connect to the emulator without having to set the environment variable :code:`PUBSUB_EMULATOR_HOST`.

docs/index.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Currently available features:
1313
- Selenim Standalone containers
1414
- MySql db container
1515
- PostgreSQL db container
16+
- Google Cloud PubSub emulator container
1617
- Generic Docker containers
1718

1819
Installation
@@ -28,8 +29,9 @@ and can be installed using pip, depending on which containers you need:
2829
pip install testcontainers[mysql]
2930
pip install testcontainers[postgresql]
3031
pip install testcontainers[selenium]
32+
pip install testcontainers[google-cloud-pubsub]
3133
# or with multiple
32-
pip install testcontainers[mysql,postgresql,selenium]
34+
pip install testcontainers[mysql,postgresql,selenium,google-cloud-pubsub]
3335

3436

3537
Compatibility
@@ -47,5 +49,6 @@ Usage modes
4749

4850
Database containers <database>
4951
Selenium containers <selenium>
50-
Generic containers <generic>
52+
Generic containers <generic>
5153
Docker Compose <compose>
54+
Google Cloud Emulators <google-cloud-emulators>

release-process.rst

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Release process
22
===============
33

4-
Run tests on target brunch
4+
Run tests on target branch
55
--------------------------
66

77
Steps::
@@ -67,5 +67,3 @@ Submit release to PYPI
6767
Steps::
6868

6969
twine dist/* upload
70-
71-

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,6 @@
4848
'mysql': ['sqlalchemy', 'pymysql'],
4949
'postgresql': ['sqlalchemy', 'psycopg2'],
5050
'selenium': ['selenium==2.53.1'],
51+
'google-cloud-pubsub': ['google-cloud-pubsub'],
5152
}
5253
)

testcontainers/google/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .pubsub import PubSubContainer

testcontainers/google/pubsub.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#
2+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
3+
# not use this file except in compliance with the License. You may obtain
4+
# a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11+
# License for the specific language governing permissions and limitations
12+
# under the License.
13+
import os
14+
15+
from ..core.generic import GenericContainer
16+
17+
18+
class PubSubContainer(GenericContainer):
19+
def __init__(self, image="google/cloud-sdk:latest",
20+
project="test-project", port=8432):
21+
super(PubSubContainer, self).__init__(image=image)
22+
self.project = project
23+
self.port = port
24+
self.with_exposed_ports(self.port)
25+
self.with_command("gcloud beta emulators pubsub start --project="
26+
"{project} --host-port=0.0.0.0:{port}".format(
27+
project=self.project, port=self.port,
28+
))
29+
30+
def get_pubsub_emulator_host(self):
31+
return "{host}:{port}".format(host=self.get_container_host_ip(),
32+
port=self.get_exposed_port(self.port))
33+
34+
def _get_channel(self, channel=None):
35+
if channel is None:
36+
import grpc
37+
return grpc.insecure_channel(target=self.get_pubsub_emulator_host())
38+
39+
def get_publisher_client(self, **kwargs):
40+
from google.cloud import pubsub
41+
kwargs['channel'] = self._get_channel(kwargs.get('channel'))
42+
return pubsub.PublisherClient(**kwargs)
43+
44+
def get_subscriber_client(self, **kwargs):
45+
from google.cloud import pubsub
46+
kwargs['channel'] = self._get_channel(kwargs.get('channel'))
47+
return pubsub.SubscriberClient(**kwargs)

tests/test_google.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from testcontainers.google import PubSubContainer
2+
from queue import Queue
3+
4+
5+
def test_pubsub_container():
6+
with PubSubContainer() as pubsub:
7+
import time; time.sleep(5)
8+
# Create a new topic
9+
publisher = pubsub.get_publisher_client()
10+
topic_path = publisher.topic_path(pubsub.project, "my-topic")
11+
publisher.create_topic(topic_path)
12+
13+
# Create a subscription
14+
subscriber = pubsub.get_subscriber_client()
15+
subscription_path = subscriber.subscription_path(pubsub.project,
16+
"my-subscription")
17+
subscriber.create_subscription(subscription_path, topic_path)
18+
19+
# Publish a message
20+
publisher.publish(topic_path, b"Hello world!")
21+
22+
# Receive the message
23+
queue = Queue()
24+
subscriber.subscribe(subscription_path, queue.put)
25+
message = queue.get(timeout=1)
26+
assert message.data == b"Hello world!"
27+
message.ack()

0 commit comments

Comments
 (0)