Moodle/etc/travis/DeploymentTester.py

166 строки
6.6 KiB
Python

import os
import pycurl
import sys
import tempfile
import time
import urllib
from io import BytesIO
from pycurl import Curl
from azure.mgmt.resource import ResourceManagementClient
from azure.mgmt.subscription import SubscriptionClient
from msrestazure.azure_active_directory import ServicePrincipalCredentials
from travis.Configuration import Configuration
class DeploymentTester:
@staticmethod
def elapsed(since):
elapsed = int(time.time() - since)
elapsed = '{:02d}:{:02d}:{:02d}'.format(elapsed // 3600, (elapsed % 3600 // 60), elapsed % 60)
return elapsed
def __init__(self):
self.config = Configuration()
self.deployment = None
self.credentials = None
""":type : ServicePrincipalCredentials"""
self.resource_client = None
""":type : ResourceManagementClient"""
def run(self):
self.check_configuration()
self.login()
self.create_resource_group()
self.validate()
if not self.config.should_run_full_ci():
print('\n\nBasic CI tests successful.')
return
self.deploy()
self.moodle_smoke_test()
self.moodle_admin_login()
print('\n\nFull CI tests successful!')
def check_configuration(self):
print('\nChecking configuration...')
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()
artifacts_location = self.config.deployment_properties['parameters']['_artifactsLocation']
print('- Detected "_artifactsLocation": ' + artifacts_location['value'])
print("(all check)")
def login(self):
print('\nLogging in...')
self.credentials = ServicePrincipalCredentials(
client_id=self.config.client_id,
secret=self.config.secret,
tenant=self.config.tenant_id,
)
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)
print("(logged in)")
def create_resource_group(self):
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)')
def validate(self):
print('\nValidating template...')
validation = self.resource_client.deployments.validate(self.config.resource_group,
self.config.deployment_name,
self.config.deployment_properties)
if validation.error is not None:
print("*** VALIDATION FAILED ({}) ***".format(validation.error))
print(validation.error.message)
for detail in validation.error.details:
print("- {}:\n{}".format(detail.code, detail.message))
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
if properties.provisioning_state != 'Succeeded':
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):
print("\nMoodle Smoke Test...")
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))
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