Moodle/etc/travis/DeploymentTester.py

166 строки
6.6 KiB
Python
Исходник Обычный вид История

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()
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()
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()
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:
print("*** VALIDATION FAILED ({}) ***".format(validation.error))
2018-04-27 04:33:54 +03:00
print(validation.error.message)
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