Esempio n. 1
0
def test_create(monkeypatch, popen, version, parameters, region,
                disable_rollback, dry_run, tags):
    mock_named_tempfile = MagicMock()
    mock_tempfile = MagicMock()
    mock_tempfile.name = 'filename'
    mock_named_tempfile.__enter__.return_value = mock_tempfile
    mock_named_tempfile.return_value = mock_named_tempfile
    monkeypatch.setattr('tempfile.NamedTemporaryFile', mock_named_tempfile)
    lizzy_version_tag = 'LizzyVersion={}'.format(VERSION)

    region = region or 'region'
    senza = Senza(region)
    senza.logger = MagicMock()
    senza.create('yaml: yaml', version, parameters, disable_rollback, dry_run,
                 tags)

    mock_named_tempfile.assert_called_with()
    mock_tempfile.write.assert_called_with(b'yaml: yaml')

    expected_disabled_rollback = ['--disable-rollback'
                                  ] if disable_rollback else []
    expected_dry_run = ['--dry-run'] if dry_run else []

    cli_tags = ['-t', lizzy_version_tag]
    for tag in tags:
        cli_tags.extend(['-t', tag])

    popen.assert_called_with(
        ['senza', 'create', '--region', region, '--force'] +
        expected_disabled_rollback + expected_dry_run +
        ['--stacktrace-visible'] + cli_tags + ['filename', version] +
        parameters,
        stdout=-1,
        stderr=-2)
    assert not senza.logger.error.called
Esempio n. 2
0
def delete_stack(stack_id: str, delete_options: dict) -> dict:
    """
    DELETE /stacks/{id}

    Delete a stack
    """
    sentry_client.capture_breadcrumb(data={
        'stack_id': stack_id,
        'delete_options': delete_options,
    })
    dry_run = delete_options.get('dry_run', False)
    force = delete_options.get('force', False)
    region = delete_options.get('region', config.region)  # type: Optional[str]

    senza = Senza(region)

    logger.info("Removing stack %s...", stack_id)

    running_time = MeasureRunningTime('delete_stack.success')
    output = senza.remove(stack_id,
                          dry_run=dry_run, force=force)
    running_time.finish()

    logger.info("Stack %s removed.", stack_id)
    return '', 204, _make_headers(output=output)
Esempio n. 3
0
File: api.py Progetto: zalando/lizzy
def delete_stack(stack_id: str, delete_options: dict) -> dict:
    """
    DELETE /stacks/{id}

    Delete a stack
    """
    sentry_client.capture_breadcrumb(data={
        'stack_id': stack_id,
        'delete_options': delete_options,
    })
    dry_run = delete_options.get('dry_run', False)
    force = delete_options.get('force', False)
    region = delete_options.get('region', config.region)  # type: Optional[str]

    senza = Senza(region)

    logger.info("Removing stack %s...", stack_id)

    running_time = MeasureRunningTime('delete_stack.success')
    output = senza.remove(stack_id,
                          dry_run=dry_run, force=force)
    running_time.finish()

    logger.info("Stack %s removed.", stack_id)
    return '', 204, _make_headers(output=output)
Esempio n. 4
0
def test_remove_error(popen, stack_id, dry_run, force):
    senza = Senza('region')
    senza.logger = MagicMock()
    popen.returncode = 1

    with pytest.raises(ExecutionError):
        senza.remove(stack_id, dry_run=dry_run, force=force)
Esempio n. 5
0
def get_stack_traffic(stack_id: str,
                      region: str = None) -> Tuple[dict, int, dict]:
    """
    GET /stacks/{id}/traffic

    Update traffic and Taupage image
    """
    sentry_client.capture_breadcrumb(data={
        'stack_id': stack_id,
        'region': region,
    })
    stack_name, stack_version = stack_id.rsplit('-', 1)
    senza = Senza(region or config.region)
    running_time = MeasureRunningTime('get_stack_traffic.success')

    traffic_info = senza.traffic(stack_name=stack_name)
    if traffic_info:
        for stack_traffic_info in traffic_info:
            if stack_traffic_info['identifier'] == stack_id:
                return {
                    'weight': float(stack_traffic_info['weight%'])
                }, 200, _make_headers()

    running_time.finish()
    return connexion.problem(404,
                             'Not Found',
                             'Stack not found: {}'.format(stack_id),
                             headers=_make_headers())
Esempio n. 6
0
def test_remove_error(popen, stack_id, dry_run, force):
    senza = Senza('region')
    senza.logger = MagicMock()
    popen.returncode = 1

    with pytest.raises(ExecutionError):
        senza.remove(stack_id, dry_run=dry_run, force=force)
Esempio n. 7
0
def test_render_definition(monkeypatch, popen):
    senza = Senza('region')
    senza.logger = MagicMock()

    mock_named_tempfile = MagicMock()
    mock_tempfile = MagicMock()
    mock_tempfile.name = 'lizzy.yaml'
    mock_named_tempfile.__enter__.return_value = mock_tempfile
    mock_named_tempfile.return_value = mock_named_tempfile
    monkeypatch.setattr('tempfile.NamedTemporaryFile', mock_named_tempfile)

    senza.render_definition('yaml content', 'version42', 'imgversion22',
                            ['Param1=app', 'SecondParam=3'])

    cmd = 'senza print --region region -o json --force lizzy.yaml version42 ' \
          'imgversion22 Param1=app SecondParam=3'

    popen.assert_called_with(cmd.split(" "), stdout=-1, stderr=-1)
    assert not senza.logger.error.called

    senza.render_definition('yaml content', None, 'imgversion22',
                            ['Param1=app', 'SecondParam=3'])
    assert not senza.logger.error.called

    # test error case
    popen.side_effect = ExecutionError('', '')

    with pytest.raises(SenzaRenderError):
        senza.render_definition('yaml content', 'version42', 'imgversion22',
                                ['Param1=app', 'SecondParam=3'])
Esempio n. 8
0
def test_render_definition(monkeypatch, popen):
    senza = Senza('region')
    senza.logger = MagicMock()

    mock_named_tempfile = MagicMock()
    mock_tempfile = MagicMock()
    mock_tempfile.name = 'lizzy.yaml'
    mock_named_tempfile.__enter__.return_value = mock_tempfile
    mock_named_tempfile.return_value = mock_named_tempfile
    monkeypatch.setattr('tempfile.NamedTemporaryFile', mock_named_tempfile)

    senza.render_definition('yaml content', 'version42', 'imgversion22',
                            ['Param1=app', 'SecondParam=3'])

    cmd = 'senza print --region region -o json --force lizzy.yaml version42 ' \
          'imgversion22 Param1=app SecondParam=3'

    popen.assert_called_with(cmd.split(" "), stdout=-1, stderr=-1)
    assert not senza.logger.error.called

    senza.render_definition('yaml content', None, 'imgversion22',
                            ['Param1=app', 'SecondParam=3'])
    assert not senza.logger.error.called

    # test error case
    popen.side_effect = ExecutionError('', '')

    with pytest.raises(SenzaRenderError):
        senza.render_definition('yaml content', 'version42', 'imgversion22',
                                ['Param1=app', 'SecondParam=3'])
Esempio n. 9
0
def test_create_error(monkeypatch, popen):
    mock_named_tempfile = MagicMock()
    mock_tempfile = MagicMock()
    mock_tempfile.name = 'filename'
    mock_named_tempfile.__enter__.return_value = mock_tempfile
    mock_named_tempfile.return_value = mock_named_tempfile
    monkeypatch.setattr('tempfile.NamedTemporaryFile', mock_named_tempfile)

    senza = Senza('region')
    senza.logger = MagicMock()
    popen.returncode = 1

    with pytest.raises(ExecutionError):
        senza.create('yaml: yaml', '10', ['param1', 'param2'], False, False, {})
Esempio n. 10
0
File: api.py Progetto: zalando/lizzy
def patch_stack(stack_id: str, stack_patch: dict) -> dict:
    """
    PATCH /stacks/{id}

    Update scale, traffic and Taupage image
    """
    sentry_client.capture_breadcrumb(data={
        'stack_id': stack_id,
        'stack_patch': stack_patch,
    })

    stack_patch = filter_empty_values(stack_patch)

    stack_name, stack_version = stack_id.rsplit('-', 1)
    use_region = stack_patch.get('region', config.region)
    senza = Senza(use_region)
    log_info = {'stack_id': stack_id,
                'stack_name': stack_name}
    running_time = MeasureRunningTime('patch_stack.success')

    if 'new_scale' in stack_patch:
        new_scale = stack_patch['new_scale']
        senza.scale(stack_name, stack_version, new_scale)

    if 'new_ami_image' in stack_patch:
        # Change the AMI image of the Auto Scaling Group (ASG) and respawn the
        # instances to use new image.
        new_ami_image = stack_patch['new_ami_image']
        senza.patch(stack_name, stack_version, new_ami_image)
        senza.respawn_instances(stack_name, stack_version)

    if 'new_traffic' in stack_patch:
        new_traffic = stack_patch['new_traffic']
        domains = senza.domains(stack_name)
        if domains:
            logger.info("Switching app traffic to stack.",
                        extra=log_info)
            senza.traffic(stack_name=stack_name,
                          stack_version=stack_version,
                          percentage=new_traffic)
        else:
            logger.info("App does not have a domain so traffic will not be switched.",
                        extra=log_info)
            raise TrafficNotUpdated("App does not have a domain.")

    # refresh the dict
    stack_dict = Stack.get(stack_name, stack_version, region=use_region)

    running_time.finish()
    return stack_dict, 202, _make_headers()
Esempio n. 11
0
def test_create_error(monkeypatch, popen):
    mock_named_tempfile = MagicMock()
    mock_tempfile = MagicMock()
    mock_tempfile.name = 'filename'
    mock_named_tempfile.__enter__.return_value = mock_tempfile
    mock_named_tempfile.return_value = mock_named_tempfile
    monkeypatch.setattr('tempfile.NamedTemporaryFile', mock_named_tempfile)

    senza = Senza('region')
    senza.logger = MagicMock()
    popen.returncode = 1

    with pytest.raises(ExecutionError):
        senza.create('yaml: yaml', '10', ['param1', 'param2'], False, False,
                     {})
Esempio n. 12
0
def test_remove(popen, stack_id, region, dry_run, force):
    senza = Senza(region)
    senza.logger = MagicMock()
    senza.remove(stack_id, dry_run=dry_run, force=force)

    dry_run_flag = ['--dry-run'] if dry_run else []
    force_flag = ['--force'] if force else []

    stack_name, stack_ver = stack_id.rsplit("-", 1)

    popen.assert_called_with(['senza', 'delete'] + ['--region', region] +
                             dry_run_flag + force_flag +
                             [stack_name, stack_ver],
                             stdout=-1,
                             stderr=-2)

    assert not senza.logger.error.called
    assert not senza.logger.exception.called
Esempio n. 13
0
def test_remove(popen, stack_id, region, dry_run, force):
    senza = Senza(region)
    senza.logger = MagicMock()
    senza.remove(stack_id, dry_run=dry_run, force=force)

    dry_run_flag = ['--dry-run'] if dry_run else []
    force_flag = ['--force'] if force else []

    stack_name, stack_ver = stack_id.rsplit("-", 1)

    popen.assert_called_with(['senza', 'delete']
                             + ['--region', region]
                             + dry_run_flag
                             + force_flag
                             + [stack_name, stack_ver],
                             stdout=-1, stderr=-2)

    assert not senza.logger.error.called
    assert not senza.logger.exception.called
Esempio n. 14
0
def test_list(monkeypatch, popen):
    popen.communicate.return_value = b'["item1", "item2"]', b'stderr'
    senza = Senza('region')
    senza.logger = MagicMock()
    list = senza.list()

    cmd = 'senza list --region region -o json'
    senza.logger.debug.assert_called_with('Executing %s.', 'senza', extra={'command': cmd})
    assert not senza.logger.error.called
    assert not senza.logger.exception.called

    popen.assert_called_with(['senza', 'list', '--region', 'region', '-o', 'json'], stdout=-1, stderr=-1)

    assert list == ["item1", "item2"]

    # Test invalid json
    popen.communicate.return_value = b'"', b'stderr'
    with pytest.raises(ExecutionError):
        senza.list()
Esempio n. 15
0
def patch_stack(stack_id: str, stack_patch: dict) -> dict:
    """
    PATCH /stacks/{id}

    Update traffic and Taupage image
    """
    sentry_client.capture_breadcrumb(data={
        'stack_id': stack_id,
        'stack_patch': stack_patch,
    })

    stack_patch = filter_empty_values(stack_patch)

    stack_name, stack_version = stack_id.rsplit('-', 1)
    use_region = stack_patch.get('region', config.region)
    senza = Senza(use_region)
    log_info = {'stack_id': stack_id,
                'stack_name': stack_name}
    running_time = MeasureRunningTime('patch_stack.success')

    if 'new_ami_image' in stack_patch:
        # Change the AMI image of the Auto Scaling Group (ASG) and respawn the
        # instances to use new image.
        new_ami_image = stack_patch['new_ami_image']
        senza.patch(stack_name, stack_version, new_ami_image)
        senza.respawn_instances(stack_name, stack_version)

    if 'new_traffic' in stack_patch:
        new_traffic = stack_patch['new_traffic']
        domains = senza.domains(stack_name)
        if domains:
            logger.info("Switching app traffic to stack.",
                        extra=log_info)
            senza.traffic(stack_name=stack_name,
                          stack_version=stack_version,
                          percentage=new_traffic)
        else:
            logger.info("App does not have a domain so traffic will not be switched.",
                        extra=log_info)
            raise TrafficNotUpdated("App does not have a domain.")

    # refresh the dict
    stack_dict = Stack.get(stack_name, stack_version, region=use_region)

    running_time.finish()
    return stack_dict, 202, _make_headers()
Esempio n. 16
0
def test_traffic(monkeypatch, popen):
    senza = Senza('region')
    senza.logger = MagicMock()
    traffic = senza.traffic('lizzy', 'version42', 25)

    cmd = 'senza traffic --region region -o json lizzy version42 25'
    senza.logger.debug.assert_called_with('Executing %s.', 'senza', extra={'command': cmd})
    assert not senza.logger.error.called
    assert not senza.logger.exception.called

    popen.assert_called_with(['senza', 'traffic', '--region', 'region', '-o', 'json', 'lizzy', 'version42', '25'],
                             stdout=-1,
                             stderr=-1)

    assert traffic == {'stream': 'stdout'}

    # test error case
    popen.side_effect = ExecutionError('', '')

    with pytest.raises(SenzaTrafficError):
        senza.traffic('lizzy', 'version42', 25)

    # traffic listing
    popen.side_effect = None
    traffic = senza.traffic('lizzy', 'version42')

    popen.assert_called_with(['senza', 'traffic', '--region', 'region', '-o', 'json', 'lizzy', 'version42'],
                             stdout=-1,
                             stderr=-1)
    # returns the output result
    assert traffic == {'stream': 'stdout'}
Esempio n. 17
0
def test_create(monkeypatch, popen, version, parameters, region, disable_rollback, dry_run, tags):
    mock_named_tempfile = MagicMock()
    mock_tempfile = MagicMock()
    mock_tempfile.name = 'filename'
    mock_named_tempfile.__enter__.return_value = mock_tempfile
    mock_named_tempfile.return_value = mock_named_tempfile
    monkeypatch.setattr('tempfile.NamedTemporaryFile', mock_named_tempfile)
    lizzy_version_tag = 'LizzyVersion={}'.format(VERSION)

    region = region or 'region'
    senza = Senza(region)
    senza.logger = MagicMock()
    senza.create('yaml: yaml', version, parameters, disable_rollback,
                 dry_run, tags)

    mock_named_tempfile.assert_called_with()
    mock_tempfile.write.assert_called_with(b'yaml: yaml')

    expected_disabled_rollback = ['--disable-rollback'] if disable_rollback else []
    expected_dry_run = ['--dry-run'] if dry_run else []

    cli_tags = ['-t', lizzy_version_tag]
    for tag in tags:
        cli_tags.extend(['-t', tag])

    popen.assert_called_with(['senza', 'create',
                              '--region', region,
                              '--force']
                             + expected_disabled_rollback
                             + expected_dry_run
                             + ['--stacktrace-visible']
                             + cli_tags
                             + ['filename', version]
                             + parameters,
                             stdout=-1,
                             stderr=-2)
    assert not senza.logger.error.called
Esempio n. 18
0
File: api.py Progetto: zalando/lizzy
def get_stack_traffic(stack_id: str, region: str=None) -> Tuple[dict, int, dict]:
    """
    GET /stacks/{id}/traffic

    Update traffic and Taupage image
    """
    sentry_client.capture_breadcrumb(data={
        'stack_id': stack_id,
        'region': region,
    })
    stack_name, stack_version = stack_id.rsplit('-', 1)
    senza = Senza(region or config.region)
    running_time = MeasureRunningTime('get_stack_traffic.success')

    traffic_info = senza.traffic(stack_name=stack_name)
    if traffic_info:
        for stack_traffic_info in traffic_info:
            if stack_traffic_info['identifier'] == stack_id:
                return {'weight': float(stack_traffic_info['weight%'])}, 200, _make_headers()

    running_time.finish()
    return connexion.problem(404, 'Not Found',
                             'Stack not found: {}'.format(stack_id),
                             headers=_make_headers())
Esempio n. 19
0
def get_app_status():
    status = 'OK'
    try:
        Senza(config.region).list()
    except ExecutionError:
        status = 'NOK'

    status_info = {
        'version': os.environ.get("APPLICATION_VERSION", ""),
        'status': status,
        'config': {
            name: getattr(config, name)
            for name in dir(config) if not name.startswith('__')
        }
    }
    return status_info, 200, _make_headers()
Esempio n. 20
0
def test_domain(monkeypatch, popen):
    senza = Senza('region')
    senza.logger = MagicMock()
    domains = senza.domains()

    cmd = 'senza domains --region region -o json'
    senza.logger.debug.assert_called_with('Executing %s.',
                                          'senza',
                                          extra={'command': cmd})
    assert not senza.logger.error.called
    assert not senza.logger.exception.called

    popen.assert_called_with(
        ['senza', 'domains', '--region', 'region', '-o', 'json'],
        stdout=-1,
        stderr=-1)

    assert domains == {'stream': 'stdout'}

    senza.logger.reset_mock()
    popen.reset_mock()

    popen.communicate.return_value = b'{"test": "domain2"}', b'stderr'
    domains = senza.domains('lizzy')

    cmd = 'senza domains --region region -o json lizzy'
    senza.logger.debug.assert_called_with('Executing %s.',
                                          'senza',
                                          extra={'command': cmd})
    assert not senza.logger.error.called
    assert not senza.logger.exception.called

    popen.assert_called_with(
        ['senza', 'domains', '--region', 'region', '-o', 'json', 'lizzy'],
        stdout=-1,
        stderr=-1)

    assert domains == {'test': 'domain2'}

    # test error case
    popen.side_effect = ExecutionError('', '')

    with pytest.raises(SenzaDomainsError):
        senza.domains()
Esempio n. 21
0
def test_traffic(monkeypatch, popen):
    senza = Senza('region')
    senza.logger = MagicMock()
    traffic = senza.traffic('lizzy', 'version42', 25)

    cmd = 'senza traffic --region region -o json lizzy version42 25'
    senza.logger.debug.assert_called_with('Executing %s.',
                                          'senza',
                                          extra={'command': cmd})
    assert not senza.logger.error.called
    assert not senza.logger.exception.called

    popen.assert_called_with([
        'senza', 'traffic', '--region', 'region', '-o', 'json', 'lizzy',
        'version42', '25'
    ],
                             stdout=-1,
                             stderr=-1)

    assert traffic == {'stream': 'stdout'}

    # test error case
    popen.side_effect = ExecutionError('', '')

    with pytest.raises(SenzaTrafficError):
        senza.traffic('lizzy', 'version42', 25)

    # traffic listing
    popen.side_effect = None
    traffic = senza.traffic('lizzy', 'version42')

    popen.assert_called_with([
        'senza', 'traffic', '--region', 'region', '-o', 'json', 'lizzy',
        'version42'
    ],
                             stdout=-1,
                             stderr=-1)
    # returns the output result
    assert traffic == {'stream': 'stdout'}
Esempio n. 22
0
def test_patch(monkeypatch, popen):
    senza = Senza('region')
    senza.logger = MagicMock()
    senza.patch('lizzy', 'version42', 'latest')

    cmd = 'senza patch --region region -o json lizzy version42 --image=latest'
    senza.logger.debug.assert_called_with('Executing %s.', 'senza',
                                          extra={'command': cmd})
    assert not senza.logger.error.called
    assert not senza.logger.exception.called

    popen.assert_called_with(['senza', 'patch', '--region', 'region', '-o',
                             'json', 'lizzy', 'version42', '--image=latest'],
                             stdout=-1, stderr=-1)

    # test error case
    popen.side_effect = ExecutionError('', '')

    with pytest.raises(SenzaPatchError):
        senza.patch('lizzy', 'version42', 'latest')
Esempio n. 23
0
def test_respawn_instances(monkeypatch, popen):
    senza = Senza('region')
    senza.logger = MagicMock()
    senza.respawn_instances('lizzy', 'version42')

    cmd = 'senza respawn-instances --region region -o json lizzy version42'
    senza.logger.debug.assert_called_with('Executing %s.', 'senza',
                                          extra={'command': cmd})
    assert not senza.logger.error.called
    assert not senza.logger.exception.called

    popen.assert_called_with(['senza', 'respawn-instances', '--region',
                             'region', '-o', 'json', 'lizzy', 'version42'],
                             stdout=-1, stderr=-1)

    # test error case
    popen.side_effect = ExecutionError('', '')

    with pytest.raises(SenzaRespawnInstancesError):
        senza.respawn_instances('lizzy', 'version42')
Esempio n. 24
0
def test_scale(monkeypatch, popen):
    senza = Senza('region')
    senza.logger = MagicMock()
    senza.scale('lizzy', 'version42', 0)

    cmd = 'senza scale --region region lizzy version42 0 --force'
    senza.logger.debug.assert_called_with('Executing %s.', 'senza',
                                          extra={'command': cmd})
    assert not senza.logger.error.called
    assert not senza.logger.exception.called

    popen.assert_called_with(['senza', 'scale', '--region', 'region',
                              'lizzy', 'version42', '0', '--force'],
                             stdout=-1, stderr=-2)

    # test error case
    popen.side_effect = ExecutionError('', '')

    with pytest.raises(SenzaScaleError):
        senza.scale('lizzy', 'version42', 0)
Esempio n. 25
0
def test_respawn_instances(monkeypatch, popen):
    senza = Senza('region')
    senza.logger = MagicMock()
    senza.respawn_instances('lizzy', 'version42')

    cmd = 'senza respawn-instances --region region -o json lizzy version42'
    senza.logger.debug.assert_called_with('Executing %s.',
                                          'senza',
                                          extra={'command': cmd})
    assert not senza.logger.error.called
    assert not senza.logger.exception.called

    popen.assert_called_with([
        'senza', 'respawn-instances', '--region', 'region', '-o', 'json',
        'lizzy', 'version42'
    ],
                             stdout=-1,
                             stderr=-1)

    # test error case
    popen.side_effect = ExecutionError('', '')

    with pytest.raises(SenzaRespawnInstancesError):
        senza.respawn_instances('lizzy', 'version42')
Esempio n. 26
0
def test_patch(monkeypatch, popen):
    senza = Senza('region')
    senza.logger = MagicMock()
    senza.patch('lizzy', 'version42', 'latest')

    cmd = 'senza patch --region region -o json lizzy version42 --image=latest'
    senza.logger.debug.assert_called_with('Executing %s.',
                                          'senza',
                                          extra={'command': cmd})
    assert not senza.logger.error.called
    assert not senza.logger.exception.called

    popen.assert_called_with([
        'senza', 'patch', '--region', 'region', '-o', 'json', 'lizzy',
        'version42', '--image=latest'
    ],
                             stdout=-1,
                             stderr=-1)

    # test error case
    popen.side_effect = ExecutionError('', '')

    with pytest.raises(SenzaPatchError):
        senza.patch('lizzy', 'version42', 'latest')
Esempio n. 27
0
def test_scale(monkeypatch, popen):
    senza = Senza('region')
    senza.logger = MagicMock()
    senza.scale('lizzy', 'version42', 0)

    cmd = 'senza scale --region region lizzy version42 0 --force'
    senza.logger.debug.assert_called_with('Executing %s.',
                                          'senza',
                                          extra={'command': cmd})
    assert not senza.logger.error.called
    assert not senza.logger.exception.called

    popen.assert_called_with([
        'senza', 'scale', '--region', 'region', 'lizzy', 'version42', '0',
        '--force'
    ],
                             stdout=-1,
                             stderr=-2)

    # test error case
    popen.side_effect = ExecutionError('', '')

    with pytest.raises(SenzaScaleError):
        senza.scale('lizzy', 'version42', 0)
Esempio n. 28
0
def test_list(monkeypatch, popen):
    popen.communicate.return_value = b'["item1", "item2"]', b'stderr'
    senza = Senza('region')
    senza.logger = MagicMock()
    list = senza.list()

    cmd = 'senza list --region region -o json'
    senza.logger.debug.assert_called_with('Executing %s.',
                                          'senza',
                                          extra={'command': cmd})
    assert not senza.logger.error.called
    assert not senza.logger.exception.called

    popen.assert_called_with(
        ['senza', 'list', '--region', 'region', '-o', 'json'],
        stdout=-1,
        stderr=-1)

    assert list == ["item1", "item2"]

    # Test invalid json
    popen.communicate.return_value = b'"', b'stderr'
    with pytest.raises(ExecutionError):
        senza.list()
Esempio n. 29
0
def test_domain(monkeypatch, popen):
    senza = Senza('region')
    senza.logger = MagicMock()
    domains = senza.domains()

    cmd = 'senza domains --region region -o json'
    senza.logger.debug.assert_called_with('Executing %s.', 'senza', extra={'command': cmd})
    assert not senza.logger.error.called
    assert not senza.logger.exception.called

    popen.assert_called_with(['senza', 'domains', '--region', 'region', '-o', 'json'],
                             stdout=-1,
                             stderr=-1)

    assert domains == {'stream': 'stdout'}

    senza.logger.reset_mock()
    popen.reset_mock()

    popen.communicate.return_value = b'{"test": "domain2"}', b'stderr'
    domains = senza.domains('lizzy')

    cmd = 'senza domains --region region -o json lizzy'
    senza.logger.debug.assert_called_with('Executing %s.', 'senza', extra={'command': cmd})
    assert not senza.logger.error.called
    assert not senza.logger.exception.called

    popen.assert_called_with(['senza', 'domains', '--region', 'region', '-o', 'json', 'lizzy'], stdout=-1, stderr=-1)

    assert domains == {'test': 'domain2'}

    # test error case
    popen.side_effect = ExecutionError('', '')

    with pytest.raises(SenzaDomainsError):
        senza.domains()
Esempio n. 30
0
def health_check():
    Senza(config.region).list()
    return Response(status=200, headers=_make_headers())
Esempio n. 31
0
def create_stack(new_stack: dict) -> dict:
    """
    POST /stacks/

    :param new_stack: New stack
    """

    keep_stacks = new_stack['keep_stacks']  # type: int
    new_traffic = new_stack['new_traffic']  # type: int
    stack_version = new_stack['stack_version']  # type: str
    senza_yaml = new_stack['senza_yaml']  # type: str
    parameters = new_stack.get('parameters', [])
    disable_rollback = new_stack.get('disable_rollback', False)
    region = new_stack.get('region', config.region)  # type: Optional[str]
    dry_run = new_stack.get('dry_run', False)
    tags = new_stack.get('tags', [])
    running_time = MeasureRunningTime('create_stack.success')

    sentry_client.capture_breadcrumb(
        data={
            'keep_stacks': keep_stacks,
            'new_traffic': new_traffic,
            'stack_version': stack_version,
            'disable_rollback': disable_rollback,
        })

    try:
        senza_definition = yaml.load(senza_yaml)
    except yaml.YAMLError as exception:
        metrics.count('create_stack.invalid_senza_file')
        return connexion.problem(400,
                                 'Invalid senza yaml',
                                 exception.message,
                                 headers=_make_headers())

    try:
        stack_name = senza_definition['SenzaInfo']['StackName']
    except KeyError as exception:
        logger.error("Couldn't get stack name from definition.",
                     extra={'senza_yaml': repr(senza_yaml)})
        missing_property = str(exception)
        problem = connexion.problem(
            400,
            'Invalid senza yaml',
            "Missing property in senza yaml: {}".format(missing_property),
            headers=_make_headers())
        metrics.count('create_stack.missing_stack_name_prop')
        return problem

    # Create the Stack
    logger.info("Creating stack %s...", stack_name)

    senza = Senza(region)
    tags = [
        'LizzyKeepStacks={}'.format(keep_stacks),
        'LizzyTargetTraffic={}'.format(new_traffic), *tags
    ]

    output = senza.create(senza_yaml, stack_version, parameters,
                          disable_rollback, dry_run, tags)

    logger.info("Stack created.",
                extra={
                    'stack_name': stack_name,
                    'stack_version': stack_version,
                    'parameters': parameters
                })
    stack_dict = (Stack.get(stack_name, stack_version, region=region)
                  if not dry_run else {
                      'stack_name': stack_name,
                      'creation_time': '',
                      'description': '',
                      'status': 'DRY-RUN',
                      'version': stack_version
                  })

    running_time.finish()
    metrics.count('create_stack.region.{}'.format(region))

    return stack_dict, 201, _make_headers(output=output)
Esempio n. 32
0
File: api.py Progetto: zalando/lizzy
def create_stack(new_stack: dict) -> dict:
    """
    POST /stacks/

    :param new_stack: New stack
    """

    keep_stacks = new_stack['keep_stacks']  # type: int
    new_traffic = new_stack['new_traffic']  # type: int
    stack_version = new_stack['stack_version']  # type: str
    senza_yaml = new_stack['senza_yaml']  # type: str
    parameters = new_stack.get('parameters', [])
    disable_rollback = new_stack.get('disable_rollback', False)
    region = new_stack.get('region', config.region)  # type: Optional[str]
    dry_run = new_stack.get('dry_run', False)
    tags = new_stack.get('tags', [])
    running_time = MeasureRunningTime('create_stack.success')

    sentry_client.capture_breadcrumb(data={
        'keep_stacks': keep_stacks,
        'new_traffic': new_traffic,
        'stack_version': stack_version,
        'disable_rollback': disable_rollback,
    })

    try:
        senza_definition = yaml.load(senza_yaml)
    except yaml.YAMLError as exception:
        metrics.count('create_stack.invalid_senza_file')
        return connexion.problem(400,
                                 'Invalid senza yaml',
                                 exception.message,
                                 headers=_make_headers())

    try:
        stack_name = senza_definition['SenzaInfo']['StackName']
    except KeyError as exception:
        logger.error("Couldn't get stack name from definition.",
                     extra={'senza_yaml': repr(senza_yaml)})
        missing_property = str(exception)
        problem = connexion.problem(400,
                                    'Invalid senza yaml',
                                    "Missing property in senza yaml: {}".format(
                                        missing_property),
                                    headers=_make_headers())
        metrics.count('create_stack.missing_stack_name_prop')
        return problem

    # Create the Stack
    logger.info("Creating stack %s...", stack_name)

    senza = Senza(region)
    tags = ['LizzyKeepStacks={}'.format(keep_stacks),
            'LizzyTargetTraffic={}'.format(new_traffic),
            *tags]

    output = senza.create(senza_yaml, stack_version, parameters, disable_rollback,
                          dry_run, tags)

    logger.info("Stack created.", extra={'stack_name': stack_name,
                                         'stack_version': stack_version,
                                         'parameters': parameters})
    stack_dict = (Stack.get(stack_name, stack_version, region=region)
                  if not dry_run
                  else {'stack_name': stack_name,
                        'creation_time': '',
                        'description': '',
                        'status': 'DRY-RUN',
                        'version': stack_version})

    running_time.finish()
    metrics.count('create_stack.region.{}'.format(region))

    return stack_dict, 201, _make_headers(output=output)