2020import time
2121import uuid
2222
23+ import backoff
2324from google .api_core .exceptions import NotFound
2425from google .cloud import pubsub_v1
2526from google .cloud .logging_v2 .services .logging_service_v2 import LoggingServiceV2Client
26-
27-
2827import pytest
2928
3029
31- SUFFIX = uuid .uuid4 ().hex [ 0 : 6 ]
30+ SUFFIX = uuid .uuid4 ().hex
3231PROJECT = os .environ ["GOOGLE_CLOUD_PROJECT" ]
3332CLOUD_RUN_SERVICE = f"pubsub-test-{ SUFFIX } "
3433TOPIC = f"pubsub-test_{ SUFFIX } "
3534IMAGE_NAME = f"gcr.io/{ PROJECT } /pubsub-test-{ SUFFIX } "
3635
3736
38- @pytest . fixture
39- def container_image ( ):
40- # Build container image for Cloud Run deployment
37+ @backoff . on_exception ( backoff . expo , Exception , max_tries = 3 )
38+ def build_container_image ( image_name , project ):
39+ """ Build container image for Cloud Run deployment."""
4140 subprocess .check_call (
4241 [
4342 "gcloud" ,
4443 "builds" ,
4544 "submit" ,
4645 "--tag" ,
47- IMAGE_NAME ,
46+ image_name ,
4847 "--project" ,
49- PROJECT ,
48+ project ,
5049 "--quiet" ,
5150 ]
5251 )
53- yield IMAGE_NAME
5452
55- # Delete container image
53+
54+ @backoff .on_exception (backoff .expo , Exception , max_tries = 3 )
55+ def delete_container_image (image_name , project ):
56+ """Delete container image."""
5657 subprocess .check_call (
5758 [
5859 "gcloud" ,
5960 "container" ,
6061 "images" ,
6162 "delete" ,
62- IMAGE_NAME ,
63+ image_name ,
6364 "--quiet" ,
6465 "--project" ,
65- PROJECT ,
66+ project ,
6667 ]
6768 )
6869
6970
70- @pytest .fixture
71- def deployed_service (container_image ):
72- # Deploy image to Cloud Run
71+ @pytest .fixture (scope = 'module' )
72+ def container_image ():
73+ try :
74+ build_container_image (IMAGE_NAME , PROJECT )
75+ yield IMAGE_NAME
76+ finally :
77+ delete_container_image (IMAGE_NAME , PROJECT )
78+
7379
80+ @backoff .on_exception (backoff .expo , Exception , max_tries = 3 )
81+ def deploy_image (cloud_run_service , container_image , project ):
82+ """Deploy image to Cloud Run."""
7483 subprocess .check_call (
7584 [
7685 "gcloud" ,
7786 "run" ,
7887 "deploy" ,
79- CLOUD_RUN_SERVICE ,
88+ cloud_run_service ,
8089 "--image" ,
8190 container_image ,
8291 "--region=us-central1" ,
8392 "--project" ,
84- PROJECT ,
93+ project ,
8594 "--platform=managed" ,
8695 "--no-allow-unauthenticated" ,
8796 ]
8897 )
8998
90- yield CLOUD_RUN_SERVICE
9199
100+ @backoff .on_exception (backoff .expo , Exception , max_tries = 3 )
101+ def delete_service (cloud_run_service , project ):
92102 subprocess .check_call (
93103 [
94104 "gcloud" ,
95105 "run" ,
96106 "services" ,
97107 "delete" ,
98- CLOUD_RUN_SERVICE ,
108+ cloud_run_service ,
99109 "--platform=managed" ,
100110 "--region=us-central1" ,
101111 "--quiet" ,
102112 "--async" ,
103113 "--project" ,
104- PROJECT ,
114+ project ,
105115 ]
106116 )
107117
108118
109- @pytest .fixture
110- def service_url (deployed_service ):
111- # Get the URL for the cloud run service
112- service_url = subprocess .run (
119+ @backoff .on_exception (backoff .expo , Exception , max_tries = 3 )
120+ def get_service_url (cloud_run_service , project ):
121+ return subprocess .run (
113122 [
114123 "gcloud" ,
115124 "run" ,
116125 "--project" ,
117- PROJECT ,
126+ project ,
118127 "services" ,
119128 "describe" ,
120- CLOUD_RUN_SERVICE ,
129+ cloud_run_service ,
121130 "--platform=managed" ,
122131 "--region=us-central1" ,
123132 "--format=value(status.url)" ,
124133 ],
125134 stdout = subprocess .PIPE ,
126135 check = True ,
127- ).stdout .strip ()
136+ ).stdout .strip (). decode ()
128137
129- yield service_url .decode ()
130138
139+ @pytest .fixture (scope = 'module' )
140+ def service_url (container_image ):
141+ try :
142+ deploy_image (CLOUD_RUN_SERVICE , container_image , PROJECT )
143+ yield get_service_url (CLOUD_RUN_SERVICE , PROJECT )
144+ finally :
145+ delete_service (CLOUD_RUN_SERVICE , PROJECT )
131146
132- @pytest .fixture ()
133- def pubsub_topic ():
147+
148+ @backoff .on_exception (backoff .expo , Exception , max_tries = 3 )
149+ def create_topic (project , topic ):
134150 publisher = pubsub_v1 .PublisherClient ()
135- topic_path = publisher .topic_path (PROJECT , TOPIC )
151+ topic_path = publisher .topic_path (project , topic )
136152 publisher .create_topic (request = {"name" : topic_path })
137- yield TOPIC
153+ return TOPIC
154+
155+
156+ @backoff .on_exception (backoff .expo , Exception , max_tries = 3 )
157+ def delete_topic (project , topic ):
158+ publisher = pubsub_v1 .PublisherClient ()
159+ topic_path = publisher .topic_path (project , topic )
138160 try :
139161 publisher .delete_topic (request = {"topic" : topic_path })
140162 except NotFound :
141163 print ("Topic not found, it was either never created or was already deleted." )
142164
143165
144- @pytest . fixture ( autouse = True )
145- def pubsub_subscription (pubsub_topic , service_url ):
166+ @backoff . on_exception ( backoff . expo , Exception , max_tries = 3 )
167+ def create_subscription (pubsub_topic , service_url ):
146168 # Create pubsub push subscription to Cloud Run Service
147169 # Attach service account with Cloud Run Invoker role
148170 # See tutorial for details on setting up service-account:
@@ -168,9 +190,13 @@ def pubsub_subscription(pubsub_topic, service_url):
168190 "push_config" : push_config ,
169191 }
170192 )
171- yield
172- subscriber = pubsub_v1 .SubscriberClient ()
173193
194+
195+ @backoff .on_exception (backoff .expo , Exception , max_tries = 3 )
196+ def delete_subscription (pubsub_topic ):
197+ subscriber = pubsub_v1 .SubscriberClient ()
198+ subscription_id = f"{ pubsub_topic } _sub"
199+ subscription_path = subscriber .subscription_path (PROJECT , subscription_id )
174200 # delete subscription
175201 with subscriber :
176202 try :
@@ -181,6 +207,17 @@ def pubsub_subscription(pubsub_topic, service_url):
181207 )
182208
183209
210+ @pytest .fixture (scope = 'module' )
211+ def pubsub_topic (service_url ):
212+ try :
213+ topic = create_topic (PROJECT , TOPIC )
214+ create_subscription (topic , service_url )
215+ yield topic
216+ finally :
217+ delete_topic (PROJECT , TOPIC )
218+ delete_subscription (topic )
219+
220+
184221def test_end_to_end (pubsub_topic ):
185222 # Post the message "Runner" to the topic
186223 publisher = pubsub_v1 .PublisherClient ()
0 commit comments