Пример #1
0
async def test_does_resource_exist(patch, story, resource, async_mock,
                                   res_code):
    resp = MagicMock()
    resp.code = res_code
    patch.object(Kubernetes,
                 'make_k8s_call',
                 new=async_mock(return_value=resp))

    if res_code == 500 or resource == 'foo':
        with pytest.raises(Exception):
            await Kubernetes._does_resource_exist(story.app, resource, 'name')
        return

    ret = await Kubernetes._does_resource_exist(story.app, resource, 'name')

    if res_code == 200:
        assert ret is True
    else:
        assert ret is False

    expected_path = Kubernetes._get_api_path_prefix(resource) + \
        f'/{story.app.app_id}/{resource}/name'
    Kubernetes.make_k8s_call.mock.assert_called_with(story.app.config,
                                                     story.app.logger,
                                                     expected_path)
Пример #2
0
async def test_delete_resource(patch, story, async_mock, first_res, resource):
    story.app.app_id = 'my_app'
    api_responses = [
        _create_response(first_res),
        _create_response(200),
        _create_response(200),
        _create_response(404),
    ]
    patch.object(Kubernetes, 'make_k8s_call',
                 new=async_mock(side_effect=api_responses))
    patch.object(asyncio, 'sleep', new=async_mock())
    if resource == 'unknown':
        with pytest.raises(Exception):
            await Kubernetes._delete_resource(story.app, resource, 'foo')
        return
    else:
        await Kubernetes._delete_resource(story.app, resource, 'foo')

    if first_res == 404:
        assert Kubernetes.make_k8s_call.mock.call_count == 1
        return

    prefix = Kubernetes._get_api_path_prefix(resource)

    assert Kubernetes.make_k8s_call.mock.mock_calls == [
        mock.call(story.app,
                  f'{prefix}/my_app/{resource}/foo'
                  f'?gracePeriodSeconds=0',
                  method='delete'),
        mock.call(story.app, f'{prefix}/my_app/{resource}/foo'),
        mock.call(story.app, f'{prefix}/my_app/{resource}/foo'),
        mock.call(story.app, f'{prefix}/my_app/{resource}/foo'),
    ]
Пример #3
0
async def test_check_for_image_errors(patch, app, async_mock):

    container_name = 'my_container'
    app.app_id = 'my_app'

    patch.object(Kubernetes,
                 'make_k8s_call',
                 new=async_mock(side_effect=[
                     _create_response(
                         200, {
                             'items': [{
                                 'status': {
                                     'containerStatuses': [{
                                         'image': 'test',
                                         'state': {
                                             'waiting': {
                                                 'reason': 'ContainerCreating'
                                             }
                                         }
                                     }]
                                 }
                             }]
                         }),
                     _create_response(
                         200, {
                             'items': [{
                                 'status': {
                                     'containerStatuses': [{
                                         'image': 'test',
                                         'state': {
                                             'waiting': {
                                                 'reason': 'ImagePullBackOff'
                                             }
                                         }
                                     }]
                                 }
                             }]
                         }),
                 ]))

    await Kubernetes.check_for_image_errors(app, container_name)
    with pytest.raises(K8sError) as exc:
        await Kubernetes.check_for_image_errors(app, container_name)
    assert exc.value.message == 'ImagePullBackOff - Failed to pull image test'

    prefix = Kubernetes._get_api_path_prefix('pods')
    qs = urllib.parse.urlencode({'labelSelector': f'app={container_name}'})
    Kubernetes.make_k8s_call.mock.assert_called()
    Kubernetes.make_k8s_call.mock.assert_called_with(
        app.config, app.logger, f'{prefix}/{app.app_id}'
        f'/pods?{qs}')
Пример #4
0
async def test_create_ingress(patch, app, async_mock, resource_exists,
                              k8s_api_returned_2xx):
    if resource_exists and not k8s_api_returned_2xx:
        # Invalid combination, since if the ing resource exists already,
        # no additional call to the k8s API is made.
        return

    app.app_id = 'my_app_id'
    app.config.INGRESS_GLOBAL_STATIC_IP_NAME = 'ip-static-name-global'
    ingress_name = 'my_ingress_name'
    hostname = 'my_ingress_hostname'
    container_name = 'my_container_name'
    expose = Expose(service='service',
                    service_expose_name='expose_name',
                    http_path='expose_path')

    http_conf = {'path': '/my_app', 'port': 6000}

    app.services = {
        expose.service: {
            ServiceConstants.config: {
                KEY_EXPOSE: {
                    expose.service_expose_name: {
                        'http': http_conf
                    }
                }
            }
        }
    }

    app.config.APP_DOMAIN = 'foo.com'

    patch.object(Kubernetes,
                 '_does_resource_exist',
                 new=async_mock(return_value=resource_exists))

    expected_payload = {
        'apiVersion': 'extensions/v1beta1',
        'kind': 'Ingress',
        'metadata': {
            'name': ingress_name,
            'annotations': {
                'kubernetes.io/ingress.class': 'nginx',
                'kubernetes.io/ingress.global-static-ip-name':
                app.config.INGRESS_GLOBAL_STATIC_IP_NAME,
                'ingress.kubernetes.io/rewrite-target': expose.http_path,
                'nginx.ingress.kubernetes.io/proxy-body-size': '1m',
                'nginx.ingress.kubernetes.io/proxy-read-timeout': '120'
            }
        },
        'spec': {
            'tls': [{
                'hosts': [f'{hostname}.'
                          f'{app.config.APP_DOMAIN}']
            }],
            'rules': [{
                'host': f'{hostname}.{app.config.APP_DOMAIN}',
                'http': {
                    'paths': [{
                        'path': http_conf['path'],
                        'backend': {
                            'serviceName': container_name,
                            'servicePort': http_conf['port']
                        }
                    }]
                }
            }]
        }
    }

    patch.object(Kubernetes, 'make_k8s_call', new=async_mock(return_value=314))
    patch.object(Kubernetes, 'is_2xx', return_value=k8s_api_returned_2xx)

    if k8s_api_returned_2xx:
        await Kubernetes.create_ingress(ingress_name, app, expose,
                                        container_name, hostname)
    else:
        with pytest.raises(K8sError):
            await Kubernetes.create_ingress(ingress_name, app, expose,
                                            container_name, hostname)
        return

    if resource_exists:
        Kubernetes.make_k8s_call.mock.assert_not_called()
    else:
        prefix = Kubernetes._get_api_path_prefix('ingresses')
        prefix = f'{prefix}/{app.app_id}/ingresses'
        Kubernetes.make_k8s_call.mock.assert_called_with(
            app.config, app.logger, prefix, payload=expected_payload)

        Kubernetes.is_2xx.assert_called_with(314)