1717""" BVT tests for webhooks delivery with a basic server
1818"""
1919# Import Local Modules
20+ from marvin .cloudstackAPI import issueCertificate
2021from marvin .cloudstackTestCase import cloudstackTestCase
2122from marvin .lib .base import (Account ,
2223 Domain ,
3435import json
3536import socket
3637import _thread
38+ import tempfile
39+ import ssl
3740
3841
3942_multiprocess_shared_ = True
@@ -55,15 +58,23 @@ def do_POST(self):
5558 event_id = self .headers .get ('X-CS-Event-ID' )
5659 print ("POST request,\n Path: %s\n Headers:\n %s\n \n Body:\n %s\n " %
5760 (str (self .path ), str (self .headers ), post_data ))
58- self ._set_response ()
5961 global deliveries_received
6062 if deliveries_received is None :
6163 deliveries_received = []
6264 deliveries_received .append ({'event' : event_id , 'payload' : post_data })
65+
6366 if event_id != None :
64- self . wfile . write ( "Event with ID: {} successfully processed!" .format (str (event_id )).encode ('utf-8' ) )
67+ data = "Event with ID: {} successfully processed!" .format (str (event_id )).encode ('utf-8' )
6568 else :
66- self .wfile .write ("POST request for {}" .format (self .path ).encode ('utf-8' ))
69+ data = "POST request for {}" .format (self .path ).encode ('utf-8' )
70+
71+ self .send_response (200 )
72+ self .send_header ('Content-type' , 'text/html' )
73+ self .send_header ('Content-Length' , len (data ))
74+ self .end_headers ()
75+
76+ self .wfile .write (data )
77+ self .wfile .flush ()
6778
6879class TestWebhookDelivery (cloudstackTestCase ):
6980
@@ -97,13 +108,38 @@ def setUpClass(cls):
97108 cls .webhook_receiver_url = "http://" + cls .server_ip + ":" + str (cls .server_port )
98109 cls .logger .debug ("Running Webhook receiver @ %s" % cls .webhook_receiver_url )
99110 def startMgmtServer (tname , server ):
100- cls .logger .debug ("Starting WebhookReceiver" )
111+ cls .logger .debug ("Starting WebhookReceiver %s" % tname )
101112 try :
102113 server .serve_forever ()
103114 except Exception : pass
104115 cls .server = HTTPServer (('0.0.0.0' , cls .server_port ), WebhookReceiver )
105116 _thread .start_new_thread (startMgmtServer , ("webhook-receiver" , cls .server ,))
106117
118+ # Setup HTTPS server
119+ s = socket .socket ()
120+ s .bind (('' , 0 ))
121+ cls .server_port = s .getsockname ()[1 ]
122+ s .close ()
123+ cls .webhook_receiver_https_url = "https://" + cls .server_ip + ":" + str (cls .server_port )
124+ cls .logger .debug ("Running Webhook HTTPS receiver @ %s" % cls .webhook_receiver_https_url )
125+
126+ cls .logger .debug ("Getting certificate from management server" )
127+ issueCertificateCmd = issueCertificate .issueCertificateCmd ()
128+ issueCertificateCmd .domain = cls .server_ip
129+ issueCertificateResponse = cls .apiclient .issueCertificate (issueCertificateCmd )
130+ if issueCertificateResponse is None :
131+ cls .https_server = None
132+ else :
133+ with tempfile .NamedTemporaryFile (delete = False , mode = "w" ) as cert_file , \
134+ tempfile .NamedTemporaryFile (delete = False , mode = "w" ) as key_file :
135+ cert_file .write (issueCertificateResponse .certificate )
136+ key_file .write (issueCertificateResponse .privatekey )
137+ ssl_context = ssl .SSLContext (ssl .PROTOCOL_TLS_SERVER )
138+ ssl_context .load_cert_chain (certfile = cert_file .name , keyfile = key_file .name )
139+ cls .https_server = HTTPServer (('0.0.0.0' , cls .server_port ), WebhookReceiver )
140+ cls .https_server .socket = ssl_context .wrap_socket (cls .https_server .socket , server_side = True )
141+ _thread .start_new_thread (startMgmtServer , ("webhook-receiver-https" , cls .https_server ,))
142+
107143 cls ._cleanup = []
108144
109145 @classmethod
@@ -122,6 +158,8 @@ def setUp(self):
122158 self .cleanup .append (self .domain1 )
123159
124160 def tearDown (self ):
161+ global deliveries_received
162+ deliveries_received = []
125163 super (TestWebhookDelivery , self ).tearDown ()
126164
127165 def popItemFromCleanup (self , item_id ):
@@ -210,3 +248,58 @@ def test_01_webhook_deliveries(self):
210248 delivery_matched ,
211249 "Delivery for %s did not match with server" % delivery .id
212250 )
251+
252+ @attr (tags = ["devcloud" , "advanced" , "advancedns" , "smoke" , "basic" , "sg" ], required_hardware = "false" )
253+ def test_02_webhook_deliveries_https (self ):
254+ if not self .https_server :
255+ self .skipTest ('Failed to setup HTTPS server. skipping' )
256+ global deliveries_received
257+ self .createDomainAccount ()
258+ self .createWebhook (self .userapiclient ,
259+ payloadurl = self .webhook_receiver_https_url ,
260+ sslverification = True )
261+ self .keypair = SSHKeyPair .register (
262+ self .userapiclient ,
263+ name = "Test-" + random_gen (),
264+ publickey = "ssh-rsa: e6:9a:1e:b5:98:75:88:5d:56:bc:92:7b:43:48:05:b2"
265+ )
266+ self .logger .debug ("Registered sshkeypair: %s" % str (self .keypair .__dict__ ))
267+ time .sleep (2 )
268+ list_deliveries = self .webhook .list_deliveries (
269+ self .userapiclient ,
270+ page = 1 ,
271+ pagesize = 20
272+ )
273+ self .assertNotEqual (
274+ list_deliveries ,
275+ None ,
276+ "Check webhook deliveries list"
277+ )
278+ self .assertTrue (
279+ len (list_deliveries ) > 0 ,
280+ "Check webhook deliveries list length"
281+ )
282+ for delivery in list_deliveries :
283+ self .assertEqual (
284+ delivery .success ,
285+ True ,
286+ "Check webhook delivery success"
287+ )
288+ self .assertEqual (
289+ delivery .response ,
290+ ("Event with ID: %s successfully processed!" % delivery .eventid ),
291+ "Check webhook delivery response"
292+ )
293+ delivery_matched = False
294+ for received in deliveries_received :
295+ if received ['event' ] == delivery .eventid :
296+ self .assertEqual (
297+ delivery .payload ,
298+ received ['payload' ],
299+ "Check webhook delivery payload"
300+ )
301+ delivery_matched = True
302+ self .assertTrue (
303+ delivery_matched ,
304+ "Delivery for %s did not match with server" % delivery .id
305+ )
0 commit comments