Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #761 expand pvc_name outside of init #820

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 20 additions & 17 deletions kubespawner/spawner.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,7 @@ def __init__(self, *args, **kwargs):
self.dns_name = self.dns_name_template.format(
namespace=self.namespace, name=self.pod_name
)
self.secret_name = self._expand_user_properties(self.secret_name_template)

self.pvc_name = self._expand_user_properties(self.pvc_name_template)
if self.working_dir:
self.working_dir = self._expand_user_properties(self.working_dir)
if self.port == 0:
Expand Down Expand Up @@ -1946,7 +1944,7 @@ def _get_pod_url(self, pod):
self.port,
)

async def get_pod_manifest(self):
async def get_pod_manifest(self, secret_name):
"""
Make a pod manifest that will spawn current user's notebook pod.
"""
Expand Down Expand Up @@ -2039,12 +2037,12 @@ async def get_pod_manifest(self):
pod_anti_affinity_preferred=self.pod_anti_affinity_preferred,
pod_anti_affinity_required=self.pod_anti_affinity_required,
priority_class_name=self.priority_class_name,
ssl_secret_name=self.secret_name if self.internal_ssl else None,
ssl_secret_name=secret_name if self.internal_ssl else None,
ssl_secret_mount_path=self.secret_mount_path,
logger=self.log,
)

def get_secret_manifest(self, owner_reference):
def get_secret_manifest(self, owner_reference, secret_name):
"""
Make a secret manifest that contains the ssl certificates.
"""
Expand All @@ -2055,7 +2053,7 @@ def get_secret_manifest(self, owner_reference):
)

return make_secret(
name=self.secret_name,
name=secret_name,
username=self.user.name,
cert_paths=self.cert_paths,
hub_ca=self.internal_trust_bundles['hub-ca'],
Expand Down Expand Up @@ -2085,7 +2083,7 @@ def get_service_manifest(self, owner_reference):
annotations=annotations,
)

def get_pvc_manifest(self):
def get_pvc_manifest(self, pvc_name):
"""
Make a pvc manifest that will spawn current user's pvc.
"""
Expand All @@ -2099,7 +2097,7 @@ def get_pvc_manifest(self):
storage_selector = self._expand_all(self.storage_selector)

return make_pvc(
name=self.pvc_name,
name=pvc_name,
storage_class=self.storage_class,
access_modes=self.storage_access_modes,
selector=storage_selector,
Expand Down Expand Up @@ -2581,7 +2579,7 @@ async def _make_create_pvc_request(self, pvc, request_timeout):

self.log.info(
"PVC "
+ self.pvc_name
+ pvc_name
+ " already exists, possibly have reached quota though."
)
return True
Expand Down Expand Up @@ -2662,6 +2660,8 @@ async def _make_create_resource_request(self, kind, manifest):

async def _start(self):
"""Start the user's pod"""
pvc_name = self._expand_user_properties(self.pvc_name_template)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been looking at this in #744, and pvc_name should actually be one of the things persisted in Spawner state, because the pvc name should probably be preserved to avoid data loss even if it. Resolving the template here would ensure the new template is used and the old pvc is orphaned. But that's intended when overrides are used as in #761.

Should we:

  1. not try to track existing pvcs (status quo, this PR), or
  2. try not to lose data (what I'm trying to do in add 'safe' slug scheme #744)

If we should try not to lose data, how do we distinguish between a changed pvc for a profile (should change) vs config (should not change if prior pvc already created)?

secret_name = self._expand_user_properties(self.secret_name_template)

# load user options (including profile)
await self.load_user_options()
Expand Down Expand Up @@ -2700,22 +2700,22 @@ async def _start(self):
self._last_event = events[-1]["metadata"]["uid"]

if self.storage_pvc_ensure:
pvc = self.get_pvc_manifest()
pvc = self.get_pvc_manifest(pvc_name)

# If there's a timeout, just let it propagate
await exponential_backoff(
partial(
self._make_create_pvc_request, pvc, self.k8s_api_request_timeout
),
f'Could not create PVC {self.pvc_name}',
f'Could not create PVC {pvc_name}',
# Each req should be given k8s_api_request_timeout seconds.
timeout=self.k8s_api_request_retry_timeout,
)

# If we run into a 409 Conflict error, it means a pod with the
# same name already exists. We stop it, wait for it to stop, and
# try again. We try 4 times, and if it still fails we give up.
pod = await self.get_pod_manifest()
pod = await self.get_pod_manifest(secret_name)
if self.modify_pod_hook:
self.log.info('Pod is being modified via modify_pod_hook')
pod = await maybe_future(self.modify_pod_hook(self, pod))
Expand Down Expand Up @@ -2746,7 +2746,9 @@ async def _start(self):

if self.internal_ssl:
# internal ssl, create secret object
secret_manifest = self.get_secret_manifest(owner_reference)
secret_manifest = self.get_secret_manifest(
owner_reference, secret_name
)
await exponential_backoff(
partial(
self._ensure_not_exists,
Expand Down Expand Up @@ -3371,24 +3373,25 @@ async def delete_forever(self):
if self.name:
log_name = f"{log_name}/{self.name}"

pvc_name = self._expand_user_properties(self.pvc_name_template)
if not self.delete_pvc:
self.log.info(f"Not deleting pvc for {log_name}: {self.pvc_name}")
self.log.info(f"Not deleting pvc for {log_name}: {pvc_name}")
return

if self.name and '{servername}' not in self.pvc_name_template:
# named server has the same PVC as the default server
# don't delete the default server's PVC!
self.log.info(
f"Not deleting shared pvc for named server {log_name}: {self.pvc_name}"
f"Not deleting shared pvc for named server {log_name}: {pvc_name}"
)
return

await exponential_backoff(
partial(
self._make_delete_pvc_request,
self.pvc_name,
pvc_name,
self.k8s_api_request_timeout,
),
f'Could not delete pvc {self.pvc_name}',
f'Could not delete pvc {pvc_name}',
timeout=self.k8s_api_request_retry_timeout,
)
Loading