Skip to content
This repository was archived by the owner on Jan 23, 2026. It is now read-only.

Commit 1dd9558

Browse files
committed
simplify code
Signed-off-by: Benny Zlotnik <bzlotnik@redhat.com>
1 parent 5d21936 commit 1dd9558

File tree

3 files changed

+72
-41
lines changed

3 files changed

+72
-41
lines changed

packages/jumpstarter-cli-common/jumpstarter_cli_common/oidc.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ def get_token_remaining_seconds(token: str) -> float | None:
167167
return exp - time.time()
168168

169169

170+
# Token expiry warning threshold in seconds (5 minutes)
171+
TOKEN_EXPIRY_WARNING_SECONDS = 300
172+
173+
170174
def is_token_expired(token: str, buffer_seconds: int = 0) -> bool:
171175
"""Check if token is expired or will expire within buffer_seconds.
172176
@@ -182,3 +186,24 @@ def is_token_expired(token: str, buffer_seconds: int = 0) -> bool:
182186
if remaining is None:
183187
return False
184188
return remaining < buffer_seconds
189+
190+
191+
def format_duration(seconds: float) -> str:
192+
"""Format a duration in seconds as a human-readable string.
193+
194+
Args:
195+
seconds: Duration in seconds (can be negative for past times)
196+
197+
Returns:
198+
Formatted string like "2h 30m" or "5m 10s"
199+
"""
200+
abs_seconds = abs(seconds)
201+
hours = int(abs_seconds // 3600)
202+
mins = int((abs_seconds % 3600) // 60)
203+
secs = int(abs_seconds % 60)
204+
205+
if hours > 0:
206+
return f"{hours}h {mins}m"
207+
if mins > 0:
208+
return f"{mins}m {secs}s"
209+
return f"{secs}s"
Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,40 @@
1-
import time
21
from datetime import datetime, timezone
32

43
import click
54
from jumpstarter_cli_common.config import opt_config
6-
from jumpstarter_cli_common.oidc import decode_jwt
5+
from jumpstarter_cli_common.oidc import (
6+
TOKEN_EXPIRY_WARNING_SECONDS,
7+
decode_jwt,
8+
format_duration,
9+
get_token_remaining_seconds,
10+
)
711

812

913
@click.group()
1014
def auth():
11-
"""
12-
Authentication and token management commands
13-
"""
15+
"""Authentication and token management commands."""
16+
17+
18+
def _print_token_status(remaining: float) -> None:
19+
"""Print token status message based on remaining time."""
20+
duration = format_duration(remaining)
21+
22+
if remaining < 0:
23+
click.echo(click.style(f"Status: EXPIRED ({duration} ago)", fg="red", bold=True))
24+
click.echo(click.style("Run 'jmp login' to refresh your credentials.", fg="yellow"))
25+
elif remaining < TOKEN_EXPIRY_WARNING_SECONDS:
26+
click.echo(click.style(f"Status: EXPIRING SOON ({duration} remaining)", fg="red", bold=True))
27+
click.echo(click.style("Run 'jmp login' to refresh your credentials.", fg="yellow"))
28+
elif remaining < 3600:
29+
click.echo(click.style(f"Status: Valid ({duration} remaining)", fg="yellow"))
30+
else:
31+
click.echo(click.style(f"Status: Valid ({duration} remaining)", fg="green"))
1432

1533

1634
@auth.command(name="status")
1735
@opt_config(exporter=False)
1836
def token_status(config):
19-
"""
20-
Display token status and expiry information
21-
"""
37+
"""Display token status and expiry information."""
2238
token_str = getattr(config, "token", None)
2339

2440
if not token_str:
@@ -27,40 +43,25 @@ def token_status(config):
2743

2844
try:
2945
payload = decode_jwt(token_str)
30-
except Exception as e:
46+
except ValueError as e:
3147
click.echo(click.style(f"Failed to decode token: {e}", fg="red"))
3248
return
3349

34-
exp = payload.get("exp")
35-
if not exp:
50+
remaining = get_token_remaining_seconds(token_str)
51+
if remaining is None:
3652
click.echo(click.style("Token has no expiry claim", fg="yellow"))
3753
return
3854

39-
remaining = exp - time.time()
55+
exp = payload.get("exp")
4056
exp_dt = datetime.fromtimestamp(exp, tz=timezone.utc)
57+
click.echo(f"Token expiry: {exp_dt.strftime('%Y-%m-%d %H:%M:%S %Z')}")
4158

42-
click.echo(f"Token expiry: {exp_dt.strftime('%Y-%m-%d %H:%M:%S')}")
43-
44-
if remaining < 0:
45-
hours = int(abs(remaining) / 3600)
46-
mins = int((abs(remaining) % 3600) / 60)
47-
click.echo(click.style(f"Status: EXPIRED ({hours}h {mins}m ago)", fg="red", bold=True))
48-
click.echo(click.style("Run 'jmp login' to refresh your credentials.", fg="yellow"))
49-
elif remaining < 300: # Less than 5 minutes
50-
mins = int(remaining / 60)
51-
secs = int(remaining % 60)
52-
click.echo(click.style(f"Status: EXPIRING SOON ({mins}m {secs}s remaining)", fg="red", bold=True))
53-
click.echo(click.style("Run 'jmp login' to refresh your credentials.", fg="yellow"))
54-
elif remaining < 3600: # Less than 1 hour
55-
mins = int(remaining / 60)
56-
click.echo(click.style(f"Status: Valid ({mins}m remaining)", fg="yellow"))
57-
else:
58-
hours = int(remaining / 3600)
59-
mins = int((remaining % 3600) / 60)
60-
click.echo(click.style(f"Status: Valid ({hours}h {mins}m remaining)", fg="green"))
59+
_print_token_status(remaining)
6160

6261
# Show additional token info
63-
if payload.get("sub"):
64-
click.echo(f"Subject: {payload.get('sub')}")
65-
if payload.get("iss"):
66-
click.echo(f"Issuer: {payload.get('iss')}")
62+
sub = payload.get("sub")
63+
iss = payload.get("iss")
64+
if sub:
65+
click.echo(f"Subject: {sub}")
66+
if iss:
67+
click.echo(f"Issuer: {iss}")

packages/jumpstarter-cli/jumpstarter_cli/shell.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
from anyio import create_task_group, get_cancelled_exc_class
77
from jumpstarter_cli_common.config import opt_config
88
from jumpstarter_cli_common.exceptions import handle_exceptions_with_reauthentication
9-
from jumpstarter_cli_common.oidc import get_token_remaining_seconds
9+
from jumpstarter_cli_common.oidc import (
10+
TOKEN_EXPIRY_WARNING_SECONDS,
11+
format_duration,
12+
get_token_remaining_seconds,
13+
)
1014
from jumpstarter_cli_common.signal import signal_handler
1115

1216
from .common import opt_acquisition_timeout, opt_duration_partial, opt_selector
@@ -16,14 +20,14 @@
1620
from jumpstarter.config.exporter import ExporterConfigV1Alpha1
1721

1822

19-
def _warn_about_expired_token(lease_name: str, selector: str):
23+
def _warn_about_expired_token(lease_name: str, selector: str) -> None:
2024
"""Warn user that lease won't be cleaned up due to expired token."""
2125
click.echo(click.style("\nToken expired - lease cleanup will fail.", fg="yellow", bold=True))
2226
click.echo(click.style(f"Lease '{lease_name}' will remain active.", fg="yellow"))
2327
click.echo(click.style(f"To reconnect: JMP_LEASE={lease_name} jmp shell -s {selector}", fg="cyan"))
2428

2529

26-
async def _monitor_token_expiry(config, cancel_scope):
30+
async def _monitor_token_expiry(config, cancel_scope) -> None:
2731
"""Monitor token expiry and warn user."""
2832
token = getattr(config, "token", None)
2933
if not token:
@@ -40,11 +44,12 @@ async def _monitor_token_expiry(config, cancel_scope):
4044
click.echo(click.style("\nToken expired! Exiting shell.", fg="red", bold=True))
4145
cancel_scope.cancel()
4246
return
43-
elif remaining <= 300 and not warned: # 5 minutes
44-
mins, secs = int(remaining // 60), int(remaining % 60)
47+
48+
if remaining <= TOKEN_EXPIRY_WARNING_SECONDS and not warned:
49+
duration = format_duration(remaining)
4550
click.echo(
4651
click.style(
47-
f"\nToken expires in {mins}m {secs}s. Session will continue but cleanup may fail on exit.",
52+
f"\nToken expires in {duration}. Session will continue but cleanup may fail on exit.",
4853
fg="yellow",
4954
bold=True,
5055
)

0 commit comments

Comments
 (0)