コード例 #1
0
ファイル: users.py プロジェクト: illfelder/mash
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()
コード例 #2
0
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.'
    )
コード例 #3
0
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']
            )
        )
コード例 #4
0
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)
コード例 #5
0
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)
コード例 #6
0
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'
コード例 #7
0
ファイル: gce.py プロジェクト: illfelder/mash
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
コード例 #8
0
ファイル: users.py プロジェクト: illfelder/mash
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)
コード例 #9
0
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'
コード例 #10
0
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'
コード例 #11
0
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'
コード例 #12
0
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
コード例 #13
0
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'
コード例 #14
0
ファイル: main_test.py プロジェクト: illfelder/mash
 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)
コード例 #15
0
ファイル: main_test.py プロジェクト: illfelder/mash
 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)