| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you 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. |
| """ BVT tests for webhooks lifecycle functionalities |
| """ |
| # Import Local Modules |
| from marvin.cloudstackTestCase import cloudstackTestCase |
| from marvin.cloudstackAPI import (listEvents) |
| from marvin.lib.base import (Account, |
| Domain, |
| Webhook, |
| SSHKeyPair) |
| from marvin.lib.common import (get_domain, |
| get_zone) |
| from marvin.lib.utils import (random_gen) |
| from marvin.cloudstackException import CloudstackAPIException |
| from nose.plugins.attrib import attr |
| import logging |
| # Import System modules |
| import time |
| from datetime import datetime |
| |
| |
| _multiprocess_shared_ = True |
| HTTP_PAYLOAD_URL = "http://smee.io/C9LPa7Ei3iB6Qj2" |
| HTTPS_PAYLOAD_URL = "https://smee.io/C9LPa7Ei3iB6Qj2" |
| |
| class TestWebhooks(cloudstackTestCase): |
| |
| @classmethod |
| def setUpClass(cls): |
| testClient = super(TestWebhooks, cls).getClsTestClient() |
| cls.apiclient = testClient.getApiClient() |
| cls.services = testClient.getParsedTestDataConfig() |
| |
| # Get Zone, Domain and templates |
| cls.domain = get_domain(cls.apiclient) |
| cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) |
| |
| cls._cleanup = [] |
| cls.logger = logging.getLogger('TestWebhooks') |
| cls.logger.setLevel(logging.DEBUG) |
| |
| @classmethod |
| def tearDownClass(cls): |
| super(TestWebhooks, cls).tearDownClass() |
| |
| def setUp(self): |
| self.cleanup = [] |
| self.domain1 = Domain.create( |
| self.apiclient, |
| self.services["domain"]) |
| self.cleanup.append(self.domain1) |
| |
| def tearDown(self): |
| super(TestWebhooks, self).tearDown() |
| |
| def popItemFromCleanup(self, item_id): |
| for idx, x in enumerate(self.cleanup): |
| if x.id == item_id: |
| self.cleanup.pop(idx) |
| break |
| |
| def createDomainAccount(self, isDomainAdmin=False): |
| self.account = Account.create( |
| self.apiclient, |
| self.services["account"], |
| admin=isDomainAdmin, |
| domainid=self.domain1.id) |
| self.cleanup.append(self.account) |
| self.userapiclient = self.testClient.getUserApiClient( |
| UserName=self.account.name, |
| DomainName=self.account.domain |
| ) |
| |
| def runWebhookLifecycleTest(self, apiclient, scope=None, domainid=None, account=None, normaluser=None, payloadurl=None, description=None, sslverification=None, secretkey=None, state=None, isdelete=True): |
| name = "Test-" + random_gen() |
| if payloadurl is None: |
| payloadurl = HTTP_PAYLOAD_URL |
| self.webhook = Webhook.create( |
| apiclient, |
| name=name, |
| payloadurl=payloadurl, |
| description=description, |
| scope=scope, |
| sslverification=sslverification, |
| secretkey=secretkey, |
| state=state, |
| domainid=domainid, |
| account=account |
| ) |
| self.cleanup.append(self.webhook) |
| self.assertNotEqual( |
| self.webhook, |
| None, |
| "Check webhook created" |
| ) |
| webhook_id = self.webhook.id |
| self.logger.debug("Created webhook: %s" % str(self.webhook.__dict__)) |
| self.assertEqual( |
| name, |
| self.webhook.name, |
| "Check webhook name" |
| ) |
| self.assertEqual( |
| payloadurl, |
| self.webhook.payloadurl, |
| "Check webhook payloadurl" |
| ) |
| if state is None: |
| state = 'Enabled' |
| self.assertEqual( |
| state, |
| self.webhook.state, |
| "Check webhook state" |
| ) |
| if scope is None or normaluser is not None: |
| scope = 'Local' |
| self.assertEqual( |
| scope, |
| self.webhook.scope, |
| "Check webhook scope" |
| ) |
| if sslverification is None: |
| sslverification = False |
| self.assertEqual( |
| sslverification, |
| self.webhook.sslverification, |
| "Check webhook sslverification" |
| ) |
| if domainid is not None: |
| if normaluser is not None: |
| domainid = normaluser.domainid |
| self.assertEqual( |
| domainid, |
| self.webhook.domainid, |
| "Check webhook domainid" |
| ) |
| if account is not None: |
| self.assertEqual( |
| account, |
| self.webhook.account, |
| "Check webhook account" |
| ) |
| if description is not None: |
| self.assertEqual( |
| description, |
| self.webhook.description, |
| "Check webhook description" |
| ) |
| if secretkey is not None: |
| self.assertEqual( |
| secretkey, |
| self.webhook.secretkey, |
| "Check webhook secretkey" |
| ) |
| list_webhook = Webhook.list( |
| apiclient, |
| id=webhook_id |
| ) |
| self.assertNotEqual( |
| list_webhook, |
| None, |
| "Check webhook list" |
| ) |
| self.assertEqual( |
| len(list_webhook), |
| 1, |
| "Check webhook list length" |
| ) |
| self.assertEqual( |
| list_webhook[0].id, |
| webhook_id, |
| "Check webhook list item" |
| ) |
| if isdelete == False: |
| return |
| self.webhook.delete(apiclient) |
| self.popItemFromCleanup(webhook_id) |
| list_webhook = Webhook.list( |
| apiclient, |
| id=webhook_id |
| ) |
| self.assertTrue( |
| list_webhook is None or len(list_webhook) == 0, |
| "Check webhook list after delete" |
| ) |
| |
| @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") |
| def test_01_create_webhook_admin_local(self): |
| self.runWebhookLifecycleTest(self.apiclient) |
| |
| @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") |
| def test_02_create_webhook_admin_domain(self): |
| self.runWebhookLifecycleTest(self.apiclient, 'Domain', self.domain1.id) |
| |
| @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") |
| def test_03_create_webhook_admin_global(self): |
| self.runWebhookLifecycleTest(self.apiclient, 'Global') |
| |
| @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") |
| def test_04_create_webhook_domainadmin_local(self): |
| self.createDomainAccount(True) |
| self.runWebhookLifecycleTest(self.userapiclient) |
| |
| @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") |
| def test_05_create_webhook_domainadmin_subdomain(self): |
| self.createDomainAccount(True) |
| self.domain11 = Domain.create( |
| self.apiclient, |
| self.services["domain"], |
| parentdomainid=self.domain1.id) |
| self.cleanup.append(self.domain11) |
| self.runWebhookLifecycleTest(self.userapiclient, 'Domain', self.domain11.id) |
| |
| @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") |
| def test_06_create_webhook_domainadmin_global_negative(self): |
| self.createDomainAccount(True) |
| try: |
| self.runWebhookLifecycleTest(self.userapiclient, 'Global') |
| except CloudstackAPIException as e: |
| self.assertTrue( |
| "errorText:Scope Global can not be specified for owner" in str(e), |
| "Check Global scope error check" |
| ) |
| |
| @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") |
| def test_07_create_webhook_user_local(self): |
| self.createDomainAccount() |
| self.runWebhookLifecycleTest(self.userapiclient) |
| |
| @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") |
| def test_08_create_webhook_user_domain(self): |
| """For normal user scope will always be Local irrespective of the passed value |
| """ |
| self.createDomainAccount() |
| self.runWebhookLifecycleTest(self.userapiclient, 'Domain', self.domain1.id, normaluser=self.account) |
| |
| @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") |
| def test_09_create_webhook_user_gloabl(self): |
| """For normal user scope will always be Local irrespective of the passed value |
| """ |
| self.createDomainAccount() |
| self.runWebhookLifecycleTest(self.userapiclient, 'Global', normaluser=self.account) |
| |
| @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") |
| def test_10_create_webhook_admin_advanced(self): |
| self.createDomainAccount() |
| self.runWebhookLifecycleTest( |
| self.apiclient, |
| payloadurl=HTTPS_PAYLOAD_URL, |
| scope="Local", |
| description="Webhook", |
| sslverification=True, |
| secretkey="webhook", |
| state="Disabled", |
| domainid=self.domain1.id, |
| account=self.account.name |
| ) |
| |
| @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") |
| def test_11_update_webhook(self): |
| self.createDomainAccount() |
| self.runWebhookLifecycleTest(self.userapiclient, isdelete=False) |
| description = "Desc-" + random_gen() |
| secretkey = random_gen() |
| state = 'Disabled' |
| updated_webhook = self.webhook.update( |
| self.userapiclient, |
| description=description, |
| secretkey=secretkey, |
| state=state |
| )['webhook'] |
| self.assertNotEqual( |
| updated_webhook, |
| None, |
| "Check updated webhook" |
| ) |
| self.assertEqual( |
| description, |
| updated_webhook.description, |
| "Check webhook description" |
| ) |
| self.assertEqual( |
| secretkey, |
| updated_webhook.secretkey, |
| "Check webhook secretkey" |
| ) |
| self.assertEqual( |
| state, |
| updated_webhook.state, |
| "Check webhook state" |
| ) |
| |
| @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") |
| def test_12_list_user_webhook_deliveries(self): |
| self.createDomainAccount() |
| self.runWebhookLifecycleTest(self.userapiclient, isdelete=False) |
| now = datetime.now() # current date and time |
| start_time = now.strftime("%Y-%m-%d %H:%M:%S") |
| self.keypair = SSHKeyPair.register( |
| self.userapiclient, |
| name="Test-" + random_gen(), |
| publickey="ssh-rsa: e6:9a:1e:b5:98:75:88:5d:56:bc:92:7b:43:48:05:b2" |
| ) |
| self.logger.debug("Registered sshkeypair: %s" % str(self.keypair.__dict__)) |
| cmd = listEvents.listEventsCmd() |
| cmd.startdate = start_time |
| cmd.listall = True |
| events = self.apiclient.listEvents(cmd) |
| register_sshkeypair_event_count = 0 |
| if events is not None: |
| for event in events: |
| if event.type == "REGISTER.SSH.KEYPAIR": |
| register_sshkeypair_event_count = register_sshkeypair_event_count + 1 |
| time.sleep(5) |
| list_deliveries = self.webhook.list_deliveries( |
| self.userapiclient, |
| page=1, |
| pagesize=20 |
| ) |
| self.assertNotEqual( |
| list_deliveries, |
| None, |
| "Check webhook deliveries list" |
| ) |
| self.assertTrue( |
| len(list_deliveries) > 0, |
| "Check webhook deliveries list length" |
| ) |
| register_sshkeypair_delivery_count = 0 |
| for delivery in list_deliveries: |
| if delivery.eventtype == "REGISTER.SSH.KEYPAIR": |
| register_sshkeypair_delivery_count = register_sshkeypair_delivery_count + 1 |
| self.assertEqual( |
| register_sshkeypair_event_count, |
| register_sshkeypair_delivery_count, |
| "Check sshkeypair webhook deliveries count" |
| ) |
| self.webhook.delete_deliveries( |
| self.userapiclient |
| ) |
| list_deliveries = self.webhook.list_deliveries( |
| self.userapiclient |
| ) |
| self.assertTrue( |
| list_deliveries is None or len(list_deliveries) == 0, |
| "Check webhook deliveries list after delete" |
| ) |
| |
| @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") |
| def test_13_webhook_execute_delivery(self): |
| self.createDomainAccount() |
| self.runWebhookLifecycleTest(self.userapiclient, isdelete=False) |
| payload = "{ \"CloudStack\": \"Integration Test\" }" |
| delivery = self.webhook.execute_delivery( |
| self.userapiclient, |
| payload=payload |
| ) |
| self.assertNotEqual( |
| delivery, |
| None, |
| "Check test webhook delivery" |
| ) |
| self.assertEqual( |
| self.webhook.id, |
| delivery.webhookid, |
| "Check test webhook delivery webhook" |
| ) |
| self.assertEqual( |
| payload, |
| delivery.payload, |
| "Check test webhook delivery payload" |
| ) |
| self.assertEqual( |
| self.webhook.id, |
| delivery.webhookid, |
| "Check test webhook delivery webhook" |
| ) |