def add_user(email, password=None): """ Add new user to database and set password hash. If the user or email exists return None. If password is None, a random password is created, in effect creating an account that can only be used with oidc authentication. """ if password and len(password) < 8: raise MashException( 'Password too short. Minimum length is 8 characters.') if not email_in_whitelist(email): raise MashException( 'Cannot create a user with the provided email. Access denied.') response = handle_request(current_app.config['DATABASE_API_URL'], 'users/', 'post', job_data={ 'email': email, 'password': password }) return response.json()
def wait_on_operation( compute_driver, project, operation_name, timeout=600, wait_period=10 ): """ Wait for operation to be in DONE state. If operation does not reach the DONE state within the timeout period raise an exception. """ start = time.time() end = start + timeout while time.time() < end: time.sleep(wait_period) operation = compute_driver.globalOperations().get( project=project, operation=operation_name ).execute() if operation['status'] == 'DONE': return operation raise MashException( 'Operation did not finish in the allotted time.' )
def delete_gce_image(compute_driver, project, cloud_image_name): """ Delete the GCE framework image. And wait for operation to finish. """ response = compute_driver.images().delete( project=project, image=cloud_image_name ).execute() operation = wait_on_operation( compute_driver, project, response['name'] ) if 'error' in operation and operation['error'].get('errors'): error = operation['error']['errors'][0] raise MashException( 'Failed to delete image: {message}'.format( message=error['message'] ) )
def create_gce_image( compute_driver, project, cloud_image_name, cloud_image_description, blob_uri, family=None, guest_os_features=None, rollout=None ): """ Create a GCE framework image for the blob. Wait for create operation to finish and for image to be in READY state. """ kwargs = { 'name': cloud_image_name, 'family': family, 'description': cloud_image_description, 'rawDisk': {'source': blob_uri}, 'rolloutOverride': rollout } if guest_os_features: kwargs['guestOsFeatures'] = [ {'type': feature} for feature in guest_os_features ] response = compute_driver.images().insert( project=project, body=kwargs ).execute() operation = wait_on_operation( compute_driver, project, response['name'] ) if 'error' in operation and operation['error'].get('errors'): error = operation['error']['errors'][0] raise MashException( 'Failed to create image: {message}'.format( message=error['message'] ) ) wait_on_image_ready(compute_driver, project, cloud_image_name)
def wait_on_image_ready(compute_driver, project, cloud_image_name): """ Wait for image to be in READY state. If image ends up in FAILED state raise an exception. """ status = None while status != 'READY': image = get_gce_image(compute_driver, project, cloud_image_name) status = image.get('status', None) if status == 'FAILED': raise MashException('Image creation failed.') time.sleep(5)
def test_api_update_account_azure(mock_jwt_required, mock_jwt_identity, mock_handle_request, test_client): account = { 'id': '1', 'name': 'test', 'region': 'useast', 'source_container': 'container1', 'source_resource_group': 'group1', 'source_storage_account': 'account1' } response = Mock() response.json.return_value = account mock_handle_request.return_value = response mock_jwt_identity.return_value = 'user1' request = {'region': 'uswest'} result = test_client.post('/v1/accounts/azure/acnt1', content_type='application/json', data=json.dumps(request, sort_keys=True)) assert result.status_code == 200 assert result.json['name'] == 'test' # Account not found response.json.return_value = {} result = test_client.post('/v1/accounts/azure/acnt1', content_type='application/json', data=json.dumps(request, sort_keys=True)) assert result.status_code == 404 assert result.data == b'{"msg":"Azure account not found"}\n' # Mash Exception mock_handle_request.side_effect = MashException('Broken') result = test_client.post('/v1/accounts/azure/acnt1', content_type='application/json', data=json.dumps(request, sort_keys=True)) assert result.status_code == 400 assert result.data == b'{"msg":"Broken"}\n'
def get_gce_account(name, user_id): """ Get GCE account for given user. """ response = handle_request(current_app.config['DATABASE_API_URL'], 'gce_accounts/', 'get', job_data={ 'name': name, 'user_id': user_id }) account = response.json() if not account: raise MashException( 'GCE account {account} not found. '.format(account=name)) return account
def change_user_password(email, current_password, new_password): """ Change password for user if user exists and existing password matches. And reset the password to clean so the user can login again. """ if len(new_password) < 8: raise MashException( 'Password too short. Minimum length is 8 characters.') handle_request(current_app.config['DATABASE_API_URL'], 'users/password/change/{email}'.format(email=email), 'post', job_data={ 'current_password': current_password, 'new_password': new_password }) current_app.notification_class.send_notification( password_change_msg_template, '[MASH] Password Changed', email)
def test_api_update_account_ec2(mock_jwt_required, mock_jwt_identity, mock_handle_request, test_client): account = { 'id': '1', 'name': 'user1', 'partition': 'aws', 'region': 'us-east-1', 'subnet': None, 'additional_regions': None, 'group': None } response = Mock() response.json.return_value = account mock_handle_request.return_value = response mock_jwt_identity.return_value = 'user1' request = {'group': 'group1', 'region': 'us-east-1'} result = test_client.post('/v1/accounts/ec2/acnt1', content_type='application/json', data=json.dumps(request, sort_keys=True)) assert result.status_code == 200 # Account not found response.json.return_value = {} result = test_client.post('/v1/accounts/ec2/acnt1', content_type='application/json', data=json.dumps(request, sort_keys=True)) assert result.status_code == 404 assert result.data == b'{"msg":"EC2 account not found"}\n' # Mash Exception mock_handle_request.side_effect = MashException('Broken') result = test_client.post('/v1/accounts/ec2/acnt1', content_type='application/json', data=json.dumps(request, sort_keys=True)) assert result.status_code == 400 assert result.data == b'{"msg":"Broken"}\n'
def test_api_update_account_aliyun(mock_jwt_required, mock_jwt_identity, mock_handle_request, test_client): account = { 'id': '1', 'name': 'user1', 'bucket': 'images', 'region': 'cn-beijing', 'security_group_id': 'sg1', 'vswitch_id': 'vs1' } response = Mock() response.json.return_value = account mock_handle_request.return_value = response mock_jwt_identity.return_value = 'user1' request = {'bucket': 'bucket1', 'region': 'cn-beijing'} result = test_client.post('/v1/accounts/aliyun/acnt1', content_type='application/json', data=json.dumps(request, sort_keys=True)) assert result.status_code == 200 # Account not found response.json.return_value = {} result = test_client.post('/v1/accounts/aliyun/acnt1', content_type='application/json', data=json.dumps(request, sort_keys=True)) assert result.status_code == 404 assert result.data == b'{"msg":"Aliyun account not found"}\n' # Mash Exception mock_handle_request.side_effect = MashException('Broken') result = test_client.post('/v1/accounts/aliyun/acnt1', content_type='application/json', data=json.dumps(request, sort_keys=True)) assert result.status_code == 400 assert result.data == b'{"msg":"Broken"}\n'
def test_api_update_account_gce(mock_jwt_required, mock_jwt_identity, mock_handle_request, test_client): account = { 'id': '1', 'name': 'user1', 'bucket': 'images', 'region': 'us-east-1', 'testing_account': None, 'is_publishing_account': False } response = Mock() response.json.return_value = account mock_handle_request.return_value = response mock_jwt_identity.return_value = 'user1' request = {'bucket': 'bucket1', 'region': 'us-east-1'} result = test_client.post('/v1/accounts/gce/acnt1', content_type='application/json', data=json.dumps(request, sort_keys=True)) assert result.status_code == 200 # Account not found response.json.return_value = {} result = test_client.post('/v1/accounts/gce/acnt1', content_type='application/json', data=json.dumps(request, sort_keys=True)) assert result.status_code == 404 assert result.data == b'{"msg":"GCE account not found"}\n' # Mash Exception mock_handle_request.side_effect = MashException('Broken') result = test_client.post('/v1/accounts/gce/acnt1', content_type='application/json', data=json.dumps(request, sort_keys=True)) assert result.status_code == 400 assert result.data == b'{"msg":"Broken"}\n'
def handle_request(url, endpoint, method, job_data=None): """ Post request based on endpoint and data. If response is unsuccessful raise exception. """ request_method = getattr(requests, method) data = None if not job_data else JsonFormat.json_message(job_data) uri = ''.join([url, endpoint]) response = request_method(uri, data=data) if response.status_code not in (200, 201): try: msg = response.json()['msg'] except Exception: msg = 'Request to {uri} failed: {reason}'.format( uri=uri, reason=response.reason) raise MashException(msg) return response
def test_api_add_job_gce(mock_jwt_required, mock_jwt_identity, mock_get_account, mock_create_job, mock_get_user, test_client): job = { 'job_id': '12345678-1234-1234-1234-123456789012', 'last_service': 'test', 'utctime': 'now', 'image': 'test_image_oem', 'download_url': 'http://download.opensuse.org/repositories/Cloud:Tools/images', 'cloud_architecture': 'x86_64', 'profile': 'Server', 'start_time': '2011-11-11 11:11:11', 'state': 'pending', 'errors': [] } mock_create_job.return_value = job mock_jwt_identity.return_value = 'user1' account = { 'region': 'us-west1-a', 'name': 'test-gce', 'is_publishing_account': False } mock_get_account.return_value = account mock_get_user.return_value = {'email': '*****@*****.**'} with open('test/data/gce_job.json', 'r') as job_doc: data = json.load(job_doc) del data['requesting_user'] del data['job_id'] del data['cloud'] response = test_client.post('/v1/jobs/gce/', content_type='application/json', data=json.dumps(data, sort_keys=True)) assert response.status_code == 201 assert response.json['job_id'] == '12345678-1234-1234-1234-123456789012' assert response.json['last_service'] == 'test' assert response.json['utctime'] == 'now' assert response.json['image'] == 'test_image_oem' assert response.json[ 'download_url'] == 'http://download.opensuse.org/repositories/Cloud:Tools/images' assert response.json['cloud_architecture'] == 'x86_64' assert response.json['profile'] == 'Server' assert response.json['state'] == 'pending' assert response.json['start_time'] == '2011-11-11 11:11:11' # Dry run data['dry_run'] = True mock_create_job.return_value = None response = test_client.post('/v1/jobs/gce/', content_type='application/json', data=json.dumps(data, sort_keys=True)) assert response.status_code == 200 assert response.data == b'{"msg":"Job doc is valid!"}\n' # Exception mock_get_account.side_effect = Exception('Broken') response = test_client.post('/v1/jobs/gce/', content_type='application/json', data=json.dumps(data, sort_keys=True)) assert response.status_code == 400 assert response.data == b'{"msg":"Failed to start job"}\n' # Mash Exception mock_get_account.side_effect = MashException('Broken') response = test_client.post('/v1/jobs/gce/', content_type='application/json', data=json.dumps(data, sort_keys=True)) assert response.status_code == 400 assert response.data == b'{"msg":"Job failed: Broken"}\n'
def test_main_mash_error(self, mock_exit, mock_OBSImageBuildResultService, mock_conofig): mock_OBSImageBuildResultService.side_effect = MashException('error') main() mock_exit.assert_called_once_with(1)
def test_main_mash_error( self, mock_exit, mock_listener_service, mock_config ): mock_listener_service.side_effect = MashException('error') main() mock_exit.assert_called_once_with(1)