Skip to content

Commit 48df26c

Browse files
gurghetclaude
andcommitted
fix: skip key creation for existing CRs on operator restart
When operator starts, kopf's on.create handler fires for all existing CRs (not just new ones). This caused duplicate key creation and spam. Now we check if the CR already has a keyId in status: - on.create: skip if keyId exists (let reconcile handle it) - reconcile/update: force=True to proceed even with existing keyId Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 28a02cb commit 48df26c

1 file changed

Lines changed: 16 additions & 7 deletions

File tree

operator.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,19 @@ def delete_secret_if_exists(self, name, namespace):
259259
return False
260260

261261
@kopf.on.create('github.com', 'v1alpha1', 'githubdeploykeys')
262-
def create_deploy_key(spec, logger, patch, **kwargs):
262+
def create_deploy_key(spec, status, logger, patch, force=True, **kwargs):
263+
"""Create a new deploy key. Called by kopf on CR creation and by reconcile when key is missing."""
264+
265+
# If called from on.create but CR already has a keyId, skip - let reconcile handle it
266+
# This prevents duplicate key creation when operator restarts and sees existing CRs
267+
# When called from reconcile (with force=True), always proceed
268+
if status and status.get('keyId') and not kwargs.get('force'):
269+
logger.info(f"CR already has keyId {status['keyId']}, skipping on.create - reconcile will handle it")
270+
return
271+
263272
github_manager = GitHubKeyManager(logger)
264273
secret_manager = KubernetesSecretManager(logger)
265-
274+
266275
try:
267276
# Get repository
268277
repo = github_manager.get_repository(spec['repository'])
@@ -329,7 +338,7 @@ def update_deploy_key(spec, status, logger, patch, old, **kwargs):
329338
return
330339

331340
logger.info("Detected changes in title or readOnly, recreating deploy key")
332-
create_deploy_key(spec, logger, patch, **kwargs)
341+
create_deploy_key(spec, status, logger, patch, force=True, **kwargs)
333342

334343
@kopf.on.delete('github.com', 'v1alpha1', 'githubdeploykeys')
335344
def delete_deploy_key(spec, meta, status, logger, **kwargs):
@@ -376,7 +385,7 @@ def reconcile_deploy_key(spec, status, logger, patch, **kwargs):
376385

377386
if not key_id:
378387
logger.info("No key ID in status, recreating deploy key")
379-
create_deploy_key(spec, logger, patch, **kwargs)
388+
create_deploy_key(spec, status, logger, patch, force=True, **kwargs)
380389
return
381390

382391
# Check if our key still exists
@@ -386,13 +395,13 @@ def reconcile_deploy_key(spec, status, logger, patch, **kwargs):
386395
logger.info(f"Deploy key {key_id} exists but title has changed, recreating")
387396
# Delete old key before creating new one
388397
github_manager.delete_key_by_id(repo, key_id)
389-
create_deploy_key(spec, logger, patch, **kwargs)
398+
create_deploy_key(spec, status, logger, patch, force=True, **kwargs)
390399
else:
391400
logger.info(f"Deploy key {key_id} exists and is correctly configured")
392401
except github.GithubException as e:
393402
if e.status == 404:
394403
logger.info(f"Deploy key {key_id} no longer exists, recreating")
395-
create_deploy_key(spec, logger, patch, **kwargs)
404+
create_deploy_key(spec, status, logger, patch, force=True, **kwargs)
396405
else:
397406
logger.error(f"Error checking deploy key {key_id}: {e}")
398407

@@ -415,7 +424,7 @@ def reconcile_deploy_key(spec, status, logger, patch, **kwargs):
415424
except kubernetes.client.exceptions.ApiException as e:
416425
if e.status == 404:
417426
logger.info(f"Secret {secret_name} is missing, recreating deploy key")
418-
create_deploy_key(spec, logger, patch, **kwargs)
427+
create_deploy_key(spec, status, logger, patch, force=True, **kwargs)
419428
else:
420429
logger.error(f"Error checking secret {secret_name}: {e}")
421430

0 commit comments

Comments
 (0)