Skip to content

Commit

Permalink
Replace zalando.org with kopf.dev for peering
Browse files Browse the repository at this point in the history
The peering selectors are modified so that they only select by name (plural name in this case), ignoring the group. As such, both `zalando.org` and `kopf.dev` peerings will be supported (so as any other domains, actually; but the resource name itself implies Kopf, not some other frameworks).

This relies on an assumption that *either* `zalando.org` *or* `kopf.dev` peering resources are installed in the cluster, *not both*. It is assumed that both resources cannot co-exist because they share the same names and would cause a conflict anyway.

*Compatibility*: The newly configured clusters will use `kopf.dev`, and all is fine. The existing cluster can continue using `zalando.org`, and it will work too (unless reconfigured).

*For transitioning*, the old CRD must be removed, and a new CRD must be created. This will wipe all existing peering CRs too, so they must be re-created with the new domain (`kopf.dev`). Applying them with the old domain will fail, as after such a transition, those resources will not exist.
  • Loading branch information
nolar committed Jan 16, 2021
1 parent 3734eb5 commit 597cec0
Show file tree
Hide file tree
Showing 13 changed files with 144 additions and 121 deletions.
3 changes: 2 additions & 1 deletion docs/continuity.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ All information is retrieved and stored via Kubernetes API.
Specifically:

* The cross-operator exchange is performed via peering objects of type
``KopfPeering`` or ``ClusterKopfPeering`` (API version: ``zalando.org/v1``).
``KopfPeering`` or ``ClusterKopfPeering``
(API versions: either ``kopf.dev/v1`` or ``zalando.org/v1``).
See :doc:`peering` for more info.
* The last handled state of the object is stored in ``metadata.annotations``
(the ``kopf.zalando.org/last-handled-configuration`` annotation).
Expand Down
4 changes: 2 additions & 2 deletions docs/deployment-rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ metadata:
rules:

# Framework: knowing which other operators are running (i.e. peering).
- apiGroups: [zalando.org]
- apiGroups: [kopf.dev]
resources: [clusterkopfpeerings]
verbs: [list, watch, patch, get]

Expand All @@ -37,7 +37,7 @@ metadata:
rules:

# Framework: knowing which other operators are running (i.e. peering).
- apiGroups: [zalando.org]
- apiGroups: [kopf.dev]
resources: [kopfpeerings]
verbs: [list, watch, patch, get]

Expand Down
18 changes: 14 additions & 4 deletions docs/peering.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ Create the peering objects as needed with one of:

.. code-block:: yaml
apiVersion: zalando.org/v1
apiVersion: kopf.dev/v1
kind: ClusterKopfPeering
metadata:
name: example
.. code-block:: yaml
apiVersion: zalando.org/v1
apiVersion: kopf.dev/v1
kind: KopfPeering
metadata:
namespace: default
Expand All @@ -69,11 +69,21 @@ Create the peering objects as needed with one of:
.. note::

In ``kopf<0.11`` (until May'2019), ``KopfPeering`` was the only CRD,
and it was cluster-scoped. In ``kopf>=0.11,<0.29`` (until Oct'2020),
and it was cluster-scoped. In ``kopf>=0.11,<1.29`` (until Dec'2020),
this mode was deprecated but supported if the old CRD existed.
Since ``kopf>=0.29`` (Nov'2020), it is not supported anymore.
Since ``kopf>=1.29`` (Jan'2021), it is not supported anymore.
To upgrade, delete and re-create the peering CRDs to the new ones.

.. note::

In ``kopf<1.29``, all peering CRDs used the API group ``kopf.zalando.org``.
Since ``kopf>=1.29`` (Jan'2021), they belong to the API group ``kopf.dev``.

At runtime, both API groups are supported. However, these resources
of different API groups are mutually exclusive and cannot co-exist
in the same cluster since they use the same names. Whenever possible,
re-create them with the new API group after the operator/framework upgrade.


Custom peering
==============
Expand Down
6 changes: 4 additions & 2 deletions kopf/structs/references.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,12 +355,14 @@ def select(self, resources: Collection[Resource]) -> Collection[Resource]:
# Some predefined API endpoints that we use in the framework itself (not exposed to the operators).
# Note: the CRDs are versionless: we do not look into its ``spec`` stanza, we only watch for
# the fact of changes, so the schema does not matter, any cluster-preferred API version would work.
# Note: the peering resources are either zalando.org/v1 or kopf.dev/v1; both cannot co-exist because
# they would share the names, so K8s will not let this. It is done for domain name transitioning.
CRDS = Selector('apiextensions.k8s.io', 'customresourcedefinitions')
EVENTS = Selector('v1', 'events')
EVENTS_K8S = Selector('events.k8s.io', 'events') # only for exclusion from EVERYTHING
NAMESPACES = Selector('v1', 'namespaces')
CLUSTER_PEERINGS = Selector('zalando.org/v1', 'clusterkopfpeerings')
NAMESPACED_PEERINGS = Selector('zalando.org/v1', 'kopfpeerings')
CLUSTER_PEERINGS = Selector('clusterkopfpeerings')
NAMESPACED_PEERINGS = Selector('kopfpeerings')


class Backbone(Mapping[Selector, Resource]):
Expand Down
12 changes: 6 additions & 6 deletions peering-v1beta1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: clusterkopfpeerings.zalando.org
name: clusterkopfpeerings.kopf.dev
spec:
scope: Cluster
group: zalando.org
group: kopf.dev
names:
kind: ClusterKopfPeering
plural: clusterkopfpeerings
Expand All @@ -20,10 +20,10 @@ spec:
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: kopfpeerings.zalando.org
name: kopfpeerings.kopf.dev
spec:
scope: Namespaced
group: zalando.org
group: kopf.dev
names:
kind: KopfPeering
plural: kopfpeerings
Expand All @@ -33,12 +33,12 @@ spec:
served: true
storage: true
---
apiVersion: zalando.org/v1
apiVersion: kopf.dev/v1
kind: ClusterKopfPeering
metadata:
name: default
---
apiVersion: zalando.org/v1
apiVersion: kopf.dev/v1
kind: KopfPeering
metadata:
namespace: default
Expand Down
12 changes: 6 additions & 6 deletions peering.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: clusterkopfpeerings.zalando.org
name: clusterkopfpeerings.kopf.dev
spec:
scope: Cluster
group: zalando.org
group: kopf.dev
names:
kind: ClusterKopfPeering
plural: clusterkopfpeerings
Expand All @@ -27,10 +27,10 @@ spec:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: kopfpeerings.zalando.org
name: kopfpeerings.kopf.dev
spec:
scope: Namespaced
group: zalando.org
group: kopf.dev
names:
kind: KopfPeering
plural: kopfpeerings
Expand All @@ -47,12 +47,12 @@ spec:
type: object
x-kubernetes-preserve-unknown-fields: true
---
apiVersion: zalando.org/v1
apiVersion: kopf.dev/v1
kind: ClusterKopfPeering
metadata:
name: default
---
apiVersion: zalando.org/v1
apiVersion: kopf.dev/v1
kind: KopfPeering
metadata:
namespace: default
Expand Down
31 changes: 31 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,32 @@ def enforce_asyncio_mocker(pytestconfig):
assert fixture.mock_module is asynctest, "Mock replacement failed!"


@pytest.fixture(params=[
('kopf.dev', 'v1', 'clusterkopfpeerings'),
('zalando.org', 'v1', 'clusterkopfpeerings'),
], ids=['kopf-dev-namespaced', 'zalando-org-namespaced'])
def namespaced_peering_resource(request):
return Resource(*request.param[:3], namespaced=True)


@pytest.fixture(params=[
('kopf.dev', 'v1', 'kopfpeerings'),
('zalando.org', 'v1', 'kopfpeerings'),
], ids=['kopf-dev-cluster', 'zalando-org-cluster'])
def cluster_peering_resource(request):
return Resource(*request.param[:3], namespaced=False)


@pytest.fixture(params=[
('kopf.dev', 'v1', 'clusterkopfpeerings', False),
('zalando.org', 'v1', 'clusterkopfpeerings', False),
('kopf.dev', 'v1', 'kopfpeerings', True),
('zalando.org', 'v1', 'kopfpeerings', True),
], ids=['kopf-dev-cluster', 'zalando-org-cluster', 'kopf-dev-namespaced', 'zalando-org-namespaced'])
def peering_resource(request):
return Resource(*request.param[:3], namespaced=request.param[3])


@pytest.fixture()
def namespaced_resource():
""" The resource used in the tests. Usually mocked, so it does not matter. """
Expand All @@ -115,6 +141,11 @@ def selector(resource):
return Selector(group=resource.group, version=resource.version, plural=resource.plural)


@pytest.fixture()
def peering_namespace(peering_resource):
return 'ns' if peering_resource.namespaced else None


@pytest.fixture()
def namespace(resource):
return 'ns' if resource.namespaced else None
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ def no_crd():

@pytest.fixture()
def no_peering():
subprocess.run("kubectl delete customresourcedefinition kopfpeerings.zalando.org",
subprocess.run("kubectl delete customresourcedefinition kopfpeerings.kopf.dev",
shell=True, check=True, timeout=10, capture_output=True)
14 changes: 4 additions & 10 deletions tests/orchestration/test_task_adjustments.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ async def processor(*, raw_event: bodies.RawEvent, replenished: asyncio.Event) -
pass



@dataclasses.dataclass(frozen=True, eq=False)
class K8sMocks:
patch_obj: Mock
Expand All @@ -29,15 +28,6 @@ def k8s_mocked(mocker, resp_mocker):
)


@pytest.fixture(params=[
(False, 'clusterkopfpeerings'),
(True, 'kopfpeerings'),
], ids=['cluster-peering', 'namespaced-peering'])
def peering_resource(request, settings):
settings.peering.namespaced = request.param[0]
return Resource('zalando.org', 'v1', request.param[1], namespaced=request.param[0])


@pytest.fixture()
async def insights(settings, peering_resource):
insights = Insights()
Expand Down Expand Up @@ -77,6 +67,7 @@ async def test_empty_insights_cause_no_adjustments(

async def test_new_resources_and_namespaces_spawn_new_tasks(
settings, ensemble: Ensemble, insights: Insights, peering_resource):
settings.peering.namespaced = peering_resource.namespaced

r1 = Resource(group='group1', version='version1', plural='plural1', namespaced=True)
r2 = Resource(group='group2', version='version2', plural='plural2', namespaced=True)
Expand Down Expand Up @@ -107,6 +98,7 @@ async def test_new_resources_and_namespaces_spawn_new_tasks(

async def test_gone_resources_and_namespaces_stop_running_tasks(
settings, ensemble: Ensemble, insights: Insights, peering_resource):
settings.peering.namespaced = peering_resource.namespaced

r1 = Resource(group='group1', version='version1', plural='plural1', namespaced=True)
r2 = Resource(group='group2', version='version2', plural='plural2', namespaced=True)
Expand Down Expand Up @@ -154,6 +146,7 @@ async def test_gone_resources_and_namespaces_stop_running_tasks(

async def test_cluster_tasks_continue_running_on_namespace_deletion(
settings, ensemble: Ensemble, insights: Insights, peering_resource):
settings.peering.namespaced = peering_resource.namespaced

r1 = Resource(group='group1', version='version1', plural='plural1', namespaced=True)
r2 = Resource(group='group2', version='version2', plural='plural2', namespaced=True)
Expand Down Expand Up @@ -242,6 +235,7 @@ async def test_frozen_with_mandatory_peering_but_absent_peering_resource(

async def test_unfrozen_with_mandatory_peering_and_existing_peering_resource(
settings, ensemble: Ensemble, insights: Insights, peering_resource):
settings.peering.namespaced = peering_resource.namespaced

await ensemble.freeze_blocker.turn_to(True) # prerequisite
assert ensemble.freeze_blocker.is_on() # prerequisite
Expand Down
Loading

0 comments on commit 597cec0

Please sign in to comment.