2018-05-03 08:47:08 +03:00
|
|
|
import os
|
2018-04-30 04:03:26 +03:00
|
|
|
import pycurl
|
2018-04-26 09:52:23 +03:00
|
|
|
import sys
|
2018-05-03 08:47:08 +03:00
|
|
|
import tempfile
|
2018-04-27 07:17:48 +03:00
|
|
|
import time
|
2018-05-03 08:47:08 +03:00
|
|
|
import urllib
|
|
|
|
from io import BytesIO
|
2018-04-30 04:03:26 +03:00
|
|
|
from pycurl import Curl
|
2018-04-26 09:52:23 +03:00
|
|
|
|
|
|
|
from azure.mgmt.resource import ResourceManagementClient
|
2018-05-03 06:42:45 +03:00
|
|
|
from azure.mgmt.subscription import SubscriptionClient
|
2018-04-26 09:52:23 +03:00
|
|
|
from msrestazure.azure_active_directory import ServicePrincipalCredentials
|
|
|
|
|
|
|
|
from travis.Configuration import Configuration
|
|
|
|
|
2018-04-27 04:33:54 +03:00
|
|
|
|
2018-04-27 07:17:48 +03:00
|
|
|
class DeploymentTester:
|
2018-04-30 04:03:26 +03:00
|
|
|
@staticmethod
|
|
|
|
def elapsed(since):
|
|
|
|
elapsed = int(time.time() - since)
|
|
|
|
elapsed = '{:02d}:{:02d}:{:02d}'.format(elapsed // 3600, (elapsed % 3600 // 60), elapsed % 60)
|
|
|
|
return elapsed
|
|
|
|
|
2018-04-26 09:52:23 +03:00
|
|
|
def __init__(self):
|
|
|
|
self.config = Configuration()
|
2018-04-27 07:17:48 +03:00
|
|
|
self.deployment = None
|
|
|
|
|
2018-04-26 09:52:23 +03:00
|
|
|
self.credentials = None
|
2018-04-27 07:17:48 +03:00
|
|
|
""":type : ServicePrincipalCredentials"""
|
|
|
|
|
|
|
|
self.resource_client = None
|
|
|
|
""":type : ResourceManagementClient"""
|
2018-04-26 09:52:23 +03:00
|
|
|
|
|
|
|
def run(self):
|
|
|
|
self.check_configuration()
|
|
|
|
self.login()
|
|
|
|
self.create_resource_group()
|
2018-04-27 04:33:54 +03:00
|
|
|
self.validate()
|
2018-05-04 08:58:08 +03:00
|
|
|
if not self.config.should_run_full_ci():
|
|
|
|
print('\n\nBasic CI tests successful.')
|
|
|
|
return
|
2018-04-27 07:17:48 +03:00
|
|
|
self.deploy()
|
|
|
|
self.moodle_smoke_test()
|
2018-05-03 08:47:08 +03:00
|
|
|
self.moodle_admin_login()
|
2018-05-04 08:58:08 +03:00
|
|
|
print('\n\nFull CI tests successful!')
|
2018-04-26 09:52:23 +03:00
|
|
|
|
|
|
|
def check_configuration(self):
|
2018-04-27 07:17:48 +03:00
|
|
|
print('\nChecking configuration...')
|
2018-04-26 09:52:23 +03:00
|
|
|
if not self.config.is_valid():
|
|
|
|
print('No Azure deployment info given, skipping test deployment and exiting.')
|
|
|
|
print('Further information: https://github.com/Azure/Moodle#automated-testing-travis-ci')
|
|
|
|
sys.exit()
|
2018-05-01 10:56:49 +03:00
|
|
|
artifacts_location = self.config.deployment_properties['parameters']['_artifactsLocation']
|
|
|
|
print('- Detected "_artifactsLocation": ' + artifacts_location['value'])
|
2018-04-27 07:17:48 +03:00
|
|
|
print("(all check)")
|
2018-04-26 09:52:23 +03:00
|
|
|
|
|
|
|
def login(self):
|
2018-04-27 07:17:48 +03:00
|
|
|
print('\nLogging in...')
|
2018-04-26 09:52:23 +03:00
|
|
|
self.credentials = ServicePrincipalCredentials(
|
|
|
|
client_id=self.config.client_id,
|
|
|
|
secret=self.config.secret,
|
|
|
|
tenant=self.config.tenant_id,
|
|
|
|
)
|
2018-05-03 06:42:45 +03:00
|
|
|
print('(got credentials)')
|
|
|
|
subscription_client = SubscriptionClient(self.credentials)
|
|
|
|
subscription = next(subscription_client.subscriptions.list())
|
|
|
|
print('(found subscription)')
|
|
|
|
self.resource_client = ResourceManagementClient(self.credentials, subscription.subscription_id)
|
2018-04-27 07:17:48 +03:00
|
|
|
print("(logged in)")
|
2018-04-26 09:52:23 +03:00
|
|
|
|
|
|
|
def create_resource_group(self):
|
2018-04-27 07:17:48 +03:00
|
|
|
print('\nCreating group "{}" on "{}"...'.format(self.config.resource_group, self.config.location))
|
|
|
|
self.resource_client.resource_groups.create_or_update(self.config.resource_group,
|
|
|
|
{'location': self.config.location})
|
|
|
|
print('(created)')
|
2018-04-27 04:33:54 +03:00
|
|
|
|
|
|
|
def validate(self):
|
2018-04-27 07:17:48 +03:00
|
|
|
print('\nValidating template...')
|
|
|
|
|
|
|
|
validation = self.resource_client.deployments.validate(self.config.resource_group,
|
|
|
|
self.config.deployment_name,
|
|
|
|
self.config.deployment_properties)
|
2018-04-27 04:33:54 +03:00
|
|
|
if validation.error is not None:
|
2018-05-01 10:56:49 +03:00
|
|
|
print("*** VALIDATION FAILED ({}) ***".format(validation.error))
|
2018-04-27 04:33:54 +03:00
|
|
|
print(validation.error.message)
|
2018-05-01 10:56:49 +03:00
|
|
|
for detail in validation.error.details:
|
|
|
|
print("- {}:\n{}".format(detail.code, detail.message))
|
2018-04-27 07:17:48 +03:00
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
print("(valid)")
|
|
|
|
|
|
|
|
def deploy(self):
|
|
|
|
print('\nDeploying template, feel free to take a nap...')
|
|
|
|
deployment = self.resource_client.deployments.create_or_update(self.config.resource_group,
|
|
|
|
self.config.deployment_name,
|
|
|
|
self.config.deployment_properties)
|
|
|
|
""":type : msrestazure.azure_operation.AzureOperationPoller"""
|
|
|
|
started = time.time()
|
|
|
|
while not deployment.done():
|
|
|
|
print('... after {} still "{}" ...'.format(self.elapsed(started), deployment.status()))
|
|
|
|
deployment.wait(60)
|
|
|
|
print("WAKE UP! After {} we finally got status {}.".format(self.elapsed(started), deployment.status()))
|
|
|
|
|
|
|
|
print("Checking deployment response...")
|
|
|
|
properties = deployment.result(0).properties
|
2018-04-30 04:03:26 +03:00
|
|
|
if properties.provisioning_state != 'Succeeded':
|
2018-04-27 07:17:48 +03:00
|
|
|
print("*** DEPLOY FAILED ***")
|
|
|
|
print('Provisioning state: ' + properties.provisioning_state)
|
|
|
|
sys.exit(1)
|
|
|
|
self.load_deployment_outputs(properties.outputs)
|
|
|
|
print("(success)")
|
|
|
|
|
|
|
|
def load_deployment_outputs(self, outputs):
|
|
|
|
self.deployment = {}
|
|
|
|
for key, value in outputs.items():
|
|
|
|
self.deployment[key] = value['value']
|
|
|
|
print("- Found: " + key)
|
|
|
|
|
|
|
|
def moodle_smoke_test(self):
|
2018-05-03 08:47:08 +03:00
|
|
|
print("\nMoodle Smoke Test...")
|
2018-04-30 04:03:26 +03:00
|
|
|
url = 'https://' + self.deployment['siteURL']
|
|
|
|
curl = Curl()
|
|
|
|
curl.setopt(pycurl.URL, url)
|
|
|
|
curl.setopt(pycurl.SSL_VERIFYPEER, False)
|
|
|
|
curl.setopt(pycurl.WRITEFUNCTION, lambda x: None)
|
|
|
|
curl.perform()
|
|
|
|
status = curl.getinfo(pycurl.HTTP_CODE)
|
|
|
|
if status != 200:
|
|
|
|
print("*** DEPLOY FAILED ***")
|
|
|
|
print('HTTP Status Code: ' + status)
|
|
|
|
sys.exit(1)
|
|
|
|
print('(ok: {})'.format(status))
|
2018-05-03 08:47:08 +03:00
|
|
|
|
|
|
|
def moodle_admin_login(self):
|
|
|
|
print("\nLogging in into Moodle as 'admin'...")
|
|
|
|
response = self.moodle_admin_login_curl()
|
|
|
|
if 'Admin User' not in response:
|
|
|
|
print("*** FAILED: 'Admin User' keyword not found ***")
|
|
|
|
sys.exit(1)
|
|
|
|
print('(it worked)')
|
|
|
|
|
|
|
|
def moodle_admin_login_curl(self):
|
|
|
|
fd, path = tempfile.mkstemp()
|
|
|
|
try:
|
|
|
|
response = BytesIO()
|
|
|
|
url = 'https://' + self.deployment['siteURL'] + '/login/index.php'
|
|
|
|
curl = Curl()
|
|
|
|
curl.setopt(pycurl.URL, url)
|
|
|
|
curl.setopt(pycurl.SSL_VERIFYPEER, False)
|
|
|
|
curl.setopt(pycurl.WRITEFUNCTION, response.write)
|
|
|
|
curl.setopt(pycurl.POST, True)
|
|
|
|
curl.setopt(pycurl.COOKIEJAR, path)
|
|
|
|
curl.setopt(pycurl.COOKIEFILE, path)
|
|
|
|
post = urllib.parse.urlencode({'username': 'admin', 'password': self.deployment['moodleAdminPassword']})
|
|
|
|
curl.setopt(pycurl.POSTFIELDS, post)
|
|
|
|
curl.setopt(pycurl.FOLLOWLOCATION, True)
|
|
|
|
curl.perform()
|
|
|
|
status = curl.getinfo(pycurl.HTTP_CODE)
|
|
|
|
if status != 200:
|
|
|
|
print("*** FAILED: {} ***".format(status))
|
|
|
|
sys.exit(1)
|
|
|
|
response = response.getvalue().decode('utf-8')
|
|
|
|
finally:
|
|
|
|
os.remove(path)
|
|
|
|
return response
|