@@ -72,11 +72,19 @@ def list_tokens(
7272
7373 data = []
7474 for token in tokens .items :
75+ # Handle None expiry_at (infinite duration tokens)
76+ if token .expiry_at is None :
77+ expiry_display = "No expiry (infinite)"
78+ time_remaining = "Never expires"
79+ else :
80+ expiry_display = convert_utc_to_offset (token .expiry_at , offset_str = offset )
81+ time_remaining = calculate_time_remaining (token .expiry_at )
82+
7583 data .append (
7684 [
7785 token .id ,
78- convert_utc_to_offset ( token . expiry_at , offset_str = offset ) ,
79- calculate_time_remaining ( token . expiry_at ) ,
86+ expiry_display ,
87+ time_remaining ,
8088 ]
8189 )
8290 tabulate_data (data , headers )
@@ -92,7 +100,7 @@ def list_tokens(
92100 help_options_color = Colors .GREEN ,
93101)
94102@click .argument ("account-name" , type = str )
95- @click .argument ("expiry-at" , type = str )
103+ @click .argument ("expiry-at" , type = str , required = False , default = None )
96104@click .option (
97105 "--owner" , "owner" , type = str , default = None , help = "Define owner for the token."
98106)
@@ -105,29 +113,48 @@ def list_tokens(
105113)
106114def create_token (
107115 account_name : str ,
108- expiry_at : str ,
116+ expiry_at : str | None ,
109117 owner : str ,
110118 offset : str ,
111119) -> None :
112120 """
113121 Create a token for a service account.
114122
115- Set expiry timestamp to set an expiry time of the token.
116- Expiry can be a relative time like '3 days' or an ISO 8601 timestamp.
123+ The EXPIRY-AT argument supports two formats:
124+
125+ 1. Custom expiry: Specify a relative time (e.g., '3 days', '2 hours')
126+ or an ISO 8601 timestamp (e.g., '2025-12-31T23:59:59+00:00')
127+
128+ 2. No expiry: Leave empty or omit the argument to create a token
129+ with infinite duration
117130 """
118131 try :
119132 client = new_v2_client ()
120133 iso_expiry_at = parse_human_readable_time_to_iso (expiry_at )
121- token_config = ServiceAccountToken (
122- expiry_at = iso_expiry_at ,
123- owner = owner ,
124- )
134+
135+ # Handle the three scenarios
136+ if iso_expiry_at is None :
137+ # Default expiry - let backend handle
138+ token_config = ServiceAccountToken (owner = owner )
139+ else :
140+ # Custom expiry or no expiry
141+ token_config = ServiceAccountToken (
142+ expiry_at = iso_expiry_at ,
143+ owner = owner ,
144+ )
125145
126146 token_obj = client .create_service_account_token (
127147 name = account_name , expiry_at = token_config
128148 )
149+
150+ # Handle display of expiry information
151+ if token_obj .expiry_at is None :
152+ expiry_msg = "no expiry (infinite duration)"
153+ else :
154+ expiry_msg = convert_utc_to_offset (token_obj .expiry_at , offset_str = offset )
155+
129156 click .secho (
130- f"{ Symbols .SUCCESS } Token Created with expiry at: { convert_utc_to_offset ( token_obj . expiry_at , offset_str = offset ) } " ,
157+ f"{ Symbols .SUCCESS } Token created with expiry at: { expiry_msg } " ,
131158 fg = Colors .GREEN ,
132159 )
133160 click .echo (token_obj .token )
@@ -144,7 +171,7 @@ def create_token(
144171)
145172@click .argument ("account-name" , type = str )
146173@click .argument ("id" , type = str )
147- @click .argument ("expiry-at" , type = str )
174+ @click .argument ("expiry-at" , type = str , required = False , default = None )
148175@click .option (
149176 "--offset" ,
150177 "offset" ,
@@ -155,28 +182,49 @@ def create_token(
155182def refresh_token (
156183 account_name : str ,
157184 id : str ,
158- expiry_at : str ,
185+ expiry_at : str | None ,
159186 offset : str ,
160187) -> None :
161188 """
162189 Refresh an existing token for a service account.
163190
164- Set expiry timestamp to set a new expiry time for the token.
165- Expiry can be a relative time like '3 days' or an ISO 8601 timestamp.
191+ The EXPIRY-AT argument supports two formats:
192+
193+ 1. Custom expiry: Specify a relative time (e.g., '3 days', '2 hours')
194+ or an ISO 8601 timestamp (e.g., '2025-12-31T23:59:59+00:00')
195+
196+ 2. No expiry: Leave empty or omit the argument to refresh the token
197+ with infinite duration
166198 """
167199 try :
168200 client = new_v2_client ()
169201 iso_expiry_at = parse_human_readable_time_to_iso (expiry_at )
170- token_config = ServiceAccountToken (
171- expiry_at = iso_expiry_at ,
172- )
202+
203+ # Handle the three scenarios
204+ if iso_expiry_at is None :
205+ # Default expiry - let backend handle
206+ token_config = ServiceAccountToken ()
207+ else :
208+ # Custom expiry or no expiry
209+ token_config = ServiceAccountToken (
210+ expiry_at = iso_expiry_at ,
211+ )
173212
174213 token_obj = client .refresh_service_account_token (
175214 name = account_name , token_id = id , expiry_at = token_config
176215 )
177216
217+ # Handle display of expiry information
218+ if token_obj .expiry_at is None :
219+ if expiry_at .strip () == "0" :
220+ expiry_msg = "no expiry (infinite duration)"
221+ else :
222+ expiry_msg = "default expiry (90 days)"
223+ else :
224+ expiry_msg = convert_utc_to_offset (token_obj .expiry_at , offset_str = offset )
225+
178226 click .secho (
179- f"{ Symbols .SUCCESS } Token refreshed with expiry at: { convert_utc_to_offset ( token_obj . expiry_at , offset_str = offset ) } " ,
227+ f"{ Symbols .SUCCESS } Token refreshed with expiry at: { expiry_msg } " ,
180228 fg = Colors .GREEN ,
181229 )
182230 click .echo (token_obj .token )
0 commit comments