|
3 | 3 | import kubernetes |
4 | 4 | import base64 |
5 | 5 | import github |
| 6 | +from datetime import datetime, timezone |
6 | 7 | from cryptography.hazmat.primitives import serialization |
7 | 8 | from cryptography.hazmat.primitives.asymmetric import rsa |
8 | 9 | from cryptography.hazmat.backends import default_backend |
@@ -372,22 +373,33 @@ def delete_deploy_key(spec, meta, status, logger, **kwargs): |
372 | 373 |
|
373 | 374 | logger.info(f"Secret {meta['name']}-private-key will be deleted by garbage collection") |
374 | 375 |
|
375 | | -@kopf.timer('github.com', 'v1alpha1', 'githubdeploykeys', interval=60.0) |
| 376 | +@kopf.timer('github.com', 'v1alpha1', 'githubdeploykeys', interval=60.0, initial_delay=60.0) |
376 | 377 | def reconcile_deploy_key(spec, status, logger, patch, **kwargs): |
377 | 378 | """Periodically reconcile the deploy key to ensure it exists.""" |
378 | 379 | github_manager = GitHubKeyManager(logger) |
379 | | - |
| 380 | + |
380 | 381 | try: |
381 | 382 | repo = github_manager.get_repository(spec['repository']) |
382 | 383 | key_id = status.get('keyId') if status else None |
383 | 384 | base_title = spec.get('title', 'Kubernetes-managed deploy key') |
384 | 385 | managed_title = f"k8s-operator:{base_title}" |
385 | | - |
| 386 | + |
386 | 387 | # Note: We no longer delete "stale" keys here. This caused a race condition where |
387 | 388 | # a newly created key (not yet in status) would be deleted as stale. |
388 | 389 | # Key cleanup is handled by create_deploy_key via delete_keys_by_title. |
389 | 390 |
|
390 | 391 | if not key_id: |
| 392 | + # Check if CR was recently created - if so, let on.create handle it |
| 393 | + # This prevents a race condition where both on.create and reconcile timer |
| 394 | + # fire simultaneously on new CRs before status is patched |
| 395 | + creation_time_str = kwargs['body']['metadata']['creationTimestamp'] |
| 396 | + creation_time = datetime.fromisoformat(creation_time_str.replace('Z', '+00:00')) |
| 397 | + age_seconds = (datetime.now(timezone.utc) - creation_time).total_seconds() |
| 398 | + |
| 399 | + if age_seconds < 90: |
| 400 | + logger.info(f"CR created {age_seconds:.0f}s ago with no keyId - letting on.create handle it") |
| 401 | + return |
| 402 | + |
391 | 403 | logger.info("No key ID in status, recreating deploy key") |
392 | 404 | create_deploy_key(spec, status, logger, patch, force=True, **kwargs) |
393 | 405 | return |
|
0 commit comments