Example #1
0
File: api.py Project: 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()
Example #2
0
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()
Example #3
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')
Example #4
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')