Skip to content

Commit

Permalink
FIX: ownerReference cross ns deprecation on v1.20
Browse files Browse the repository at this point in the history
  • Loading branch information
angelbarrera92 committed Apr 26, 2021
1 parent d01dc6c commit dcdf93b
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 29 deletions.
21 changes: 14 additions & 7 deletions k8spin_common/k8spin_common/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,16 @@ def org(self) -> Organization:
@property
def tenant_namespace(self) -> Namespace:
namespaces = Namespace.objects(self.api).filter(
selector={"k8spin.cloud/org": self.org.name, "k8spin.cloud/type": "tenant"})
selector={
"k8spin.cloud/org": self.org.name,
"k8spin.cloud/tenant": self.name,
"k8spin.cloud/type": "tenant"
})
matched_ns = list()
for namespace in namespaces:
if any([owner.get("name") == self.name
for owner in namespace.metadata.get("ownerReferences", list())]):
return namespace
matched_ns.append(namespace)
if len(matched_ns) == 1:
return matched_ns[0]
# TODO CHANGE WITH K8SPIN EXCEPTIONS
raise Exception("Tenant namespace not found")

Expand Down Expand Up @@ -92,11 +97,13 @@ def space_namespace(self) -> Namespace:
namespaces = Namespace.objects(self.api).filter(
selector={"k8spin.cloud/org": self.org.name,
"k8spin.cloud/tenant": self.tenant.name,
"k8spin.cloud/space": self.name,
"k8spin.cloud/type": "space"})
matched_ns = list()
for namespace in namespaces:
if any([owner.get("name") == self.name
for owner in namespace.metadata.get("ownerReferences", list())]):
return namespace
matched_ns.append(namespace)
if len(matched_ns) == 1:
return matched_ns[0]
# TODO CHANGE WITH K8SPIN EXCEPTIONS
raise Exception("Space namespace not found")

Expand Down
3 changes: 2 additions & 1 deletion k8spin_common/k8spin_common/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ def _get_kube_api():

def ensure(resource: APIObject, owner: APIObject):
if not resource.exists():
resource = adopt(owner, resource)
if owner.namespace == resource.namespace:
resource = adopt(owner, resource)
resource.create()
else:
resource.update()
Expand Down
5 changes: 2 additions & 3 deletions k8spin_common/k8spin_common/resources/space.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import pykube

import k8spin_common
import pykube
from k8spin_common.helper import adopt, ensure, kubernetes_api
from k8spin_common.resources.namespace import create_namespace
from k8spin_common.resources.network_policies import create_network_policy
from k8spin_common.resources.quotas import (create_limit_range,
create_resource_quota)
from k8spin_common.resources.network_policies import create_network_policy
from k8spin_common.resources.rbac import (create_cluster_role_binding,
create_role_binding)
from k8spin_common.resources.tenant import tenant_namespacename_generator
Expand Down
20 changes: 19 additions & 1 deletion k8spin_operator/k8spin_operator/handlers/organization.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
import kopf

from k8spin_common.resources import organization
from pykube.exceptions import ObjectDoesNotExist


@kopf.on.create("k8spin.cloud", "v1", "organizations")
@kopf.on.update("k8spin.cloud", "v1", "organizations")
def create_organization(name, **kwargs): # pylint: disable=W0613
organization.ensure_organization_resources(organization_name=name)


@kopf.on.delete("k8spin.cloud", "v1", "organizations")
def delete_organization(name, **kwargs): # pylint: disable=W0613
try:
org = organization.get_organization(name) # pylint: disable=E1120
tenants = org.tenants
for tenant in tenants:
spaces = tenant.spaces
for space in spaces:
space_namespace = space.space_namespace
space_namespace.delete()
tenant_namespace = tenant.tenant_namespace
tenant_namespace.delete()
organization_namespace = org.organization_namespace
organization_namespace.delete()
except ObjectDoesNotExist:
pass
8 changes: 0 additions & 8 deletions k8spin_operator/k8spin_operator/handlers/reconcile.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,6 @@
RECONCILIATION_INTERVAL = int(getenv("RECONCILIATION_INTERVAL_SECONDS", "10"))


@kopf.on.delete("k8spin.cloud", "v1", "organizations")
def delete():
# Needed to fix a problem in the bellow reconciler.
# Seems like reconciler does not remove the object from its cache if its not
# explicitly declared this deletion handler.
pass


@kopf.timer("k8spin.cloud", "v1", "organizations", interval=RECONCILIATION_INTERVAL, idle=10)
def reconciler(name, **kwargs): # pylint: disable=W0613
organization.ensure_organization_resources(organization_name=name)
Expand Down
18 changes: 14 additions & 4 deletions k8spin_operator/k8spin_operator/handlers/space.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import kopf
import pykube

from k8spin_common.helper import kubernetes_api
from k8spin_common.resources import space, tenant
from pykube.exceptions import ObjectDoesNotExist


@kubernetes_api
def lives_in_tenant_namespace(api, namespace, **_):
parent_namespace = pykube.Namespace.objects(api).get(name=namespace)
# pylint: disable=E1120
if parent_namespace.labels.get("k8spin.cloud/type", "") == "tenant" and any(
[owner.get('kind') == 'Tenant'
for owner in parent_namespace.metadata.get('ownerReferences', list())]):
if parent_namespace.labels.get("k8spin.cloud/type", "") == "tenant":
return True
return False

Expand All @@ -25,3 +23,15 @@ def create_space(name, namespace, **kwargs): # pylint: disable=W0613
parent_organization = parent_tenant.org
space.ensure_space_resources(
organization=parent_organization, tenant=parent_tenant, space_name=name)


@kopf.on.delete("k8spin.cloud", "v1", "spaces")
def delete_space(name, meta, **kwargs): # pylint: disable=W0613
try:
# pylint: disable=E1120
tenant_space = space.get_space(name, meta.labels.get(
"k8spin.cloud/tenant", None), meta.labels.get("k8spin.cloud/org", None))
space_namespace = tenant_space.space_namespace
space_namespace.delete()
except ObjectDoesNotExist:
pass
22 changes: 18 additions & 4 deletions k8spin_operator/k8spin_operator/handlers/tenant.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import kopf
import pykube

from k8spin_common.helper import kubernetes_api
from k8spin_common.resources import organization, tenant
from pykube.exceptions import ObjectDoesNotExist


@kubernetes_api
def lives_in_org_namespace(api, namespace, **_):
parent_namespace = pykube.Namespace.objects(api).get(name=namespace)
# pylint: disable=E1120
if parent_namespace.labels.get("k8spin.cloud/type", "") == "organization" and any(
[owner.get('kind') == 'Organization'
for owner in parent_namespace.metadata.get('ownerReferences', list())]):
if parent_namespace.labels.get("k8spin.cloud/type", "") == "organization":
return True
return False

Expand All @@ -24,3 +22,19 @@ def create_tenant(name, meta, **kwargs): # pylint: disable=W0613
organization_name=meta.labels.get("k8spin.cloud/org", None))
tenant.ensure_tenant_resources(
organization=parent_organization, tenant_name=name)


@kopf.on.delete("k8spin.cloud", "v1", "tenants")
def delete_tenant(name, meta, **kwargs): # pylint: disable=W0613
try:
# pylint: disable=E1120
org_tenant = tenant.get_tenant(
name, meta.labels.get("k8spin.cloud/org", None))
spaces = org_tenant.spaces
for space in spaces:
space_namespace = space.space_namespace
space_namespace.delete()
tenant_namespace = org_tenant.tenant_namespace
tenant_namespace.delete()
except ObjectDoesNotExist:
pass
10 changes: 9 additions & 1 deletion k8spin_webhook/app.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import logging
from os import getenv

from flask import Flask
from flask import Flask, jsonify
from healthcheck import HealthCheck
from pykube.exceptions import ObjectDoesNotExist

import mutator # pylint: disable=E0401
import validator # pylint: disable=E0401
Expand All @@ -17,6 +18,13 @@
app.register_blueprint(validator.blueprint)
app.register_blueprint(mutator.blueprint)


@app.errorhandler(ObjectDoesNotExist)
def object_does_not_exist(error):
logger.warning('Not found error: %s. Pass', error)
return jsonify({"response": {"allowed": True}})


if __name__ == '__main__':
app.run(host='0.0.0.0', port=443,
ssl_context=("/certs/tls.crt", "/certs/tls.key"))

0 comments on commit dcdf93b

Please sign in to comment.