Skip to content

Commit

Permalink
add delete_forever hook to cleanup user's PVC on user deletion
Browse files Browse the repository at this point in the history
  • Loading branch information
nsshah1288 committed May 11, 2021
1 parent c82b354 commit e22f8f2
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 0 deletions.
25 changes: 25 additions & 0 deletions kubespawner/spawner.py
Original file line number Diff line number Diff line change
Expand Up @@ -2779,3 +2779,28 @@ async def _ensure_namespace(self):
# It's fine if it already exists
self.log.exception("Failed to create namespace %s", self.namespace)
raise

async def delete_forever(self):
"""Called when a user is deleted.
This can do things like request removal of resources such as persistent storage.
Only called on stopped spawners, and is likely the last action ever taken for the user.
This will only be called once on the user's default Spawner.
Supported by JupyterHub 1.4.0+.
"""
try:
self.api.read_namespaced_persistent_volume_claim(
self.pvc_name, self.namespace
)
except ApiException as e:
if e.status == 404:
self.log.warning(
"Could not delete %s. This PVC does not exist.", self.pvc_name
)
else:
raise
else:
self.api.delete_namespaced_persistent_volume_claim(
self.pvc_name, self.namespace
)
50 changes: 50 additions & 0 deletions tests/test_spawner.py
Original file line number Diff line number Diff line change
Expand Up @@ -627,3 +627,53 @@ async def test_url_changed(kube_ns, kube_client, config, hub_pod, hub):
assert spawner.db.commit.call_count == previous_commit_count

await spawner.stop()


@pytest.mark.asyncio
async def test_delete_pvc(kube_ns, kube_client, hub, config):
config.KubeSpawner.storage_pvc_ensure = True
config.KubeSpawner.storage_capacity = '1M'

spawner = KubeSpawner(
hub=hub,
user=MockUser(name="mockuser"),
config=config,
_mock=True,
)
spawner.api = kube_client

# start the spawner
await spawner.start()

# verify the pod exists
pod_name = "jupyter-%s" % spawner.user.name
pods = kube_client.list_namespaced_pod(kube_ns).items
pod_names = [p.metadata.name for p in pods]
assert pod_name in pod_names

# verify PVC is created
pvc_name = spawner.pvc_name
pvc_list = kube_client.list_namespaced_persistent_volume_claim(kube_ns).items
pvc_names = [s.metadata.name for s in pvc_list]
assert pvc_name in pvc_names

# stop the pod
await spawner.stop()

# verify pod is gone
pods = kube_client.list_namespaced_pod(kube_ns).items
pod_names = [p.metadata.name for p in pods]
assert "jupyter-%s" % spawner.user.name not in pod_names

# delete the PVC
await spawner.delete_forever()

# verify PVC is deleted, it may take a little while
for i in range(5):
pvc_list = kube_client.list_namespaced_persistent_volume_claim(kube_ns).items
pvc_names = [s.metadata.name for s in pvc_list]
if pvc_name in pvc_names:
time.sleep(1)
else:
break
assert pvc_name not in pvc_names

0 comments on commit e22f8f2

Please sign in to comment.