Пример #1
0
def test_events_for_additional_population(registry):
    e1 = RawEvent(type=None, object=RawBody(metadata={'name': 'ns1'}))
    e2 = RawEvent(type=None, object=RawBody(metadata={'name': 'ns2'}))
    insights = Insights()
    revise_namespaces(insights=insights, namespaces=['ns*'], raw_events=[e1])
    revise_namespaces(insights=insights, namespaces=['ns*'], raw_events=[e2])
    assert insights.namespaces == {'ns1', 'ns2'}
Пример #2
0
def test_events_for_deletion_via_event_type(registry):
    e1 = RawEvent(type=None, object=RawBody(metadata={'name': 'ns1'}))
    e2 = RawEvent(type='DELETED', object=RawBody(metadata={'name': 'ns1'}))
    insights = Insights()
    revise_namespaces(insights=insights, namespaces=['ns*'], raw_events=[e1])
    revise_namespaces(insights=insights, namespaces=['ns*'], raw_events=[e2])
    assert not insights.namespaces
Пример #3
0
def test_bodies_for_deletion_via_timestamp(registry):
    b1 = RawBody(metadata={'name': 'ns1'})
    b2 = RawBody(metadata={'name': 'ns1', 'deletionTimestamp': '...'})
    insights = Insights()
    revise_namespaces(insights=insights, namespaces=['ns*'], raw_bodies=[b1])
    revise_namespaces(insights=insights, namespaces=['ns*'], raw_bodies=[b2])
    assert not insights.namespaces
Пример #4
0
def test_bodies_for_additional_population(registry):
    b1 = RawBody(metadata={'name': 'ns1'})
    b2 = RawBody(metadata={'name': 'ns2'})
    insights = Insights()
    revise_namespaces(insights=insights, namespaces=['ns*'], raw_bodies=[b1])
    revise_namespaces(insights=insights, namespaces=['ns*'], raw_bodies=[b2])
    assert insights.namespaces == {'ns1', 'ns2'}
Пример #5
0
    def _build_key(
        self,
        raw_body: bodies.RawBody,
    ) -> str:
        """
        Construct an immutable persistent key of a resource.

        Generally, a uid is sufficient, as it is unique within the cluster.
        But it can be e.g. plural/namespace/name triplet, or anything else,
        even of different types (as long as it satisfies the type checkers).

        But it must be consistent within a single process lifetime.
        """
        return raw_body.get('metadata', {}).get('uid') or ''
Пример #6
0
async def test_followups_for_addition(timer, etype):
    insights = Insights()
    e1 = RawEvent(type=etype, object=RawBody(metadata={'name': 'ns1'}))

    async def delayed_injection(delay: float):
        await asyncio.sleep(delay)
        await process_discovered_namespace_event(insights=insights,
                                                 raw_event=e1,
                                                 namespaces=['ns*'],
                                                 replenished=asyncio.Event())

    task = asyncio.create_task(delayed_injection(0.1))
    async with timer, async_timeout.timeout(1):
        async with insights.revised:
            await insights.revised.wait()
    await task
    assert 0.1 < timer.seconds < 0.11
    assert insights.namespaces == {'ns1'}
Пример #7
0
async def test_backbone_is_filled(registry, core_mock, corev1_mock, timer,
                                  etype):
    e1 = RawEvent(type=etype, object=RawBody(spec={'group': ''}))
    insights = Insights()

    async def delayed_injection(delay: float):
        await asyncio.sleep(delay)
        await process_discovered_resource_event(insights=insights,
                                                raw_event=e1,
                                                registry=registry)

    task = asyncio.create_task(delayed_injection(0.1))
    async with timer, async_timeout.timeout(1.0):
        await insights.backbone.wait_for(NAMESPACES)
    await task
    assert 0.1 < timer.seconds < 1.0
    assert NAMESPACES in insights.backbone
    assert core_mock.called
    assert corev1_mock.called
Пример #8
0
async def test_initial_listing_is_ignored():
    insights = Insights()
    e1 = RawEvent(type=None, object=RawBody(metadata={'name': 'ns1'}))

    async def delayed_injection(delay: float):
        await asyncio.sleep(delay)
        await process_discovered_namespace_event(insights=insights,
                                                 raw_event=e1,
                                                 namespaces=['ns*'],
                                                 replenished=asyncio.Event())

    task = asyncio.create_task(delayed_injection(0))
    with pytest.raises(asyncio.TimeoutError):
        async with async_timeout.timeout(0.1) as timeout:
            async with insights.revised:
                await insights.revised.wait()
    await task
    assert timeout.expired
    assert not insights.namespaces
Пример #9
0
async def test_initial_listing_is_ignored(registry, apis_mock, group1_mock):
    insights = Insights()
    e1 = RawEvent(type=None, object=RawBody(spec={'group': 'group1'}))

    async def delayed_injection(delay: float):
        await asyncio.sleep(delay)
        await process_discovered_resource_event(insights=insights,
                                                raw_event=e1,
                                                registry=registry)

    task = asyncio.create_task(delayed_injection(0))
    with pytest.raises(asyncio.TimeoutError):
        async with async_timeout.timeout(0.1) as timeout:
            async with insights.revised:
                await insights.revised.wait()
    await task
    assert timeout.expired
    assert not insights.resources
    assert not apis_mock.called
    assert not group1_mock.called
Пример #10
0
async def test_followups_for_addition(registry, apis_mock, group1_mock, timer,
                                      etype):
    e1 = RawEvent(type=etype, object=RawBody(spec={'group': 'group1'}))
    r1 = Resource(group='group1', version='version1', plural='plural1')
    insights = Insights()

    async def delayed_injection(delay: float):
        await asyncio.sleep(delay)
        await process_discovered_resource_event(insights=insights,
                                                raw_event=e1,
                                                registry=registry)

    task = asyncio.create_task(delayed_injection(0.1))
    async with timer, async_timeout.timeout(1.0):
        async with insights.revised:
            await insights.revised.wait()
    await task
    assert 0.1 < timer.seconds < 1.0
    assert insights.resources == {r1}
    assert apis_mock.called
    assert group1_mock.called
Пример #11
0
from unittest.mock import Mock, call

import kopf
from kopf.structs.bodies import Body, RawBody, RawMeta

OWNER_API_VERSION = 'owner-api-version'
OWNER_NAMESPACE = 'owner-namespace'
OWNER_KIND = 'OwnerKind'
OWNER_NAME = 'owner-name'
OWNER_UID = 'owner-uid'
OWNER_LABELS = {'label-1': 'value-1', 'label-2': 'value-2'}
OWNER = RawBody(
    apiVersion=OWNER_API_VERSION,
    kind=OWNER_KIND,
    metadata=RawMeta(
        namespace=OWNER_NAMESPACE,
        name=OWNER_NAME,
        uid=OWNER_UID,
        labels=OWNER_LABELS,
    ),
)


def test_appending_to_dict():
    obj = {}

    kopf.append_owner_reference(obj, owner=Body(OWNER))

    assert 'metadata' in obj
    assert 'ownerReferences' in obj['metadata']
    assert isinstance(obj['metadata']['ownerReferences'], list)
    assert len(obj['metadata']['ownerReferences']) == 1
Пример #12
0
import asyncio

import aiohttp.web
import async_timeout
import pytest

import kopf
from kopf.reactor.observation import process_discovered_resource_event
from kopf.structs.bodies import RawBody, RawEvent
from kopf.structs.references import NAMESPACES, Insights, Resource

# Implementation awareness: the events only trigger the re-scan, so the fields can be reduced
# to only the group name which is being rescanned. Other fields are ignored in the events.
# The actual data is taken from the API. It is tested elsewhere, so we rely on its correctness here.
GROUP1_EVENT = RawBody(spec={'group': 'group1'})


@pytest.fixture()
def core_mock(resp_mocker, aresponses, hostname):
    mock = resp_mocker(
        return_value=aiohttp.web.json_response({'versions': ['v1']}))
    aresponses.add(hostname, '/api', 'get', mock)
    return mock


@pytest.fixture()
def apis_mock(resp_mocker, aresponses, hostname):
    mock = resp_mocker(return_value=aiohttp.web.json_response({
        'groups': [
            {
                'name': 'group1',
Пример #13
0
def test_events_ignored_for_mismatching(registry):
    e1 = RawEvent(type=None, object=RawBody(metadata={'name': 'def1'}))
    insights = Insights()
    revise_namespaces(insights=insights, namespaces=['ns*'], raw_events=[e1])
    assert not insights.namespaces
Пример #14
0
def test_bodies_ignored_for_mismatching(registry):
    b1 = RawBody(metadata={'name': 'def1'})
    insights = Insights()
    revise_namespaces(insights=insights, namespaces=['ns*'], raw_bodies=[b1])
    assert not insights.namespaces