Skip to content

Commit 21fd270

Browse files
committed
add subs suspend/reactivate support
1 parent 7e8ffcc commit 21fd270

File tree

6 files changed

+840
-6
lines changed

6 files changed

+840
-6
lines changed

docs/cli/cli-subscriptions.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ To list currently active subscriptions:
157157
planet subscriptions list --status running
158158
```
159159

160+
To list suspended subscriptions:
161+
```sh
162+
planet subscriptions list --status suspended
163+
```
164+
160165
To list subscriptions with the `catalog` source type:
161166
```sh
162167
planet subscriptions list --source-type catalog
@@ -313,6 +318,102 @@ planet subscriptions cancel cb817760-1f07-4ee7-bba6-bcac5346343f
313318
That will stop the subscription from producing any more results, but it will stay in the system so you can
314319
continue to list and get it.
315320

321+
### Suspend Subscription
322+
323+
You can temporarily pause a subscription without canceling it. This is useful when you want to stop processing
324+
and delivery for a period of time but plan to resume later. Suspended subscriptions can be reactivated at any time.
325+
326+
To suspend a single subscription:
327+
328+
```sh
329+
planet subscriptions suspend cb817760-1f07-4ee7-bba6-bcac5346343f
330+
```
331+
332+
You can optionally include details explaining why the subscription is being suspended:
333+
334+
```sh
335+
planet subscriptions suspend cb817760-1f07-4ee7-bba6-bcac5346343f \
336+
--details "Pausing during maintenance window"
337+
```
338+
339+
The suspend command returns the updated subscription JSON, showing the new status.
340+
341+
### Bulk Suspend Subscriptions
342+
343+
The `bulk-suspend` command provides flexible options for suspending multiple subscriptions at once.
344+
345+
To suspend all of your subscriptions (default behavior):
346+
347+
```sh
348+
planet subscriptions bulk-suspend
349+
```
350+
351+
To suspend specific subscriptions:
352+
353+
```sh
354+
planet subscriptions bulk-suspend \
355+
--subscription-ids cb817760-1f07-4ee7-bba6-bcac5346343f,a1b2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6
356+
```
357+
358+
To suspend all subscriptions across your organization (requires organization admin permissions):
359+
360+
```sh
361+
planet subscriptions bulk-suspend --all
362+
```
363+
364+
You can include details explaining the reason for suspension:
365+
366+
```sh
367+
planet subscriptions bulk-suspend --details "System maintenance scheduled"
368+
```
369+
370+
Or combine with specific subscription IDs:
371+
372+
```sh
373+
planet subscriptions bulk-suspend \
374+
--subscription-ids cb817760-1f07-4ee7-bba6-bcac5346343f,a1b2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6 \
375+
--details "Pausing during data migration"
376+
```
377+
378+
**Note:** The `--subscription-ids` and `--all` flags are mutually exclusive. If neither flag is provided,
379+
all of your subscriptions will be suspended.
380+
381+
### Reactivate Subscription
382+
383+
To resume a suspended subscription, use the reactivate command:
384+
385+
```sh
386+
planet subscriptions reactivate cb817760-1f07-4ee7-bba6-bcac5346343f
387+
```
388+
389+
The subscription will resume processing and delivering imagery based on its original configuration.
390+
391+
### Bulk Reactivate Subscriptions
392+
393+
The `bulk-reactivate` command provides flexible options for reactivating multiple suspended subscriptions.
394+
395+
To reactivate all of your suspended subscriptions (default behavior):
396+
397+
```sh
398+
planet subscriptions bulk-reactivate
399+
```
400+
401+
To reactivate specific subscriptions:
402+
403+
```sh
404+
planet subscriptions bulk-reactivate \
405+
--subscription-ids cb817760-1f07-4ee7-bba6-bcac5346343f,a1b2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6
406+
```
407+
408+
To reactivate all suspended subscriptions across your organization (requires organization admin permissions):
409+
410+
```sh
411+
planet subscriptions bulk-reactivate --all
412+
```
413+
414+
**Note:** The `--subscription-ids` and `--all` flags are mutually exclusive. If neither flag is provided,
415+
all of your suspended subscriptions will be reactivated.
416+
316417
## Subscription Request Conveniences
317418

318419
There are a couple of commands that can assist in creating the subscription JSON, used for creation and updates.

planet/cli/subscriptions.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,91 @@ async def cancel_subscription_cmd(ctx, subscription_id, pretty):
280280
_ = await client.cancel_subscription(subscription_id)
281281

282282

283+
@subscriptions.command(name='suspend') # type: ignore
284+
@click.argument('subscription_id')
285+
@click.option('--details',
286+
help='Optional details explaining suspension reason')
287+
@pretty
288+
@click.pass_context
289+
@translate_exceptions
290+
@coro
291+
async def suspend_subscription_cmd(ctx, subscription_id, details, pretty):
292+
"""Suspends a subscription and prints the suspended subscription."""
293+
async with subscriptions_client(ctx) as client:
294+
sub = await client.suspend_subscription(subscription_id, details)
295+
echo_json(sub, pretty)
296+
297+
298+
@subscriptions.command(name='reactivate') # type: ignore
299+
@click.argument('subscription_id')
300+
@pretty
301+
@click.pass_context
302+
@translate_exceptions
303+
@coro
304+
async def reactivate_subscription_cmd(ctx, subscription_id, pretty):
305+
"""Reactivates a subscription."""
306+
async with subscriptions_client(ctx) as client:
307+
_ = await client.reactivate_subscription(subscription_id)
308+
309+
310+
@subscriptions.command(name='bulk-suspend') # type: ignore
311+
@click.option('--subscription-ids',
312+
type=types.CommaSeparatedString(),
313+
help='Comma-separated list of subscription IDs to suspend')
314+
@click.option('--all',
315+
'all_flag',
316+
is_flag=True,
317+
help='Suspend all organization subscriptions (admin only)')
318+
@click.option('--details',
319+
help='Optional details explaining suspension reason')
320+
@pretty
321+
@click.pass_context
322+
@translate_exceptions
323+
@coro
324+
async def bulk_suspend_subscriptions_cmd(ctx,
325+
subscription_ids,
326+
all_flag,
327+
details,
328+
pretty):
329+
"""Suspends multiple subscriptions.
330+
331+
By default (no flags), suspends all of the user's subscriptions.
332+
Use --subscription-ids to suspend specific subscriptions.
333+
Use --all to suspend all organization subscriptions (requires admin).
334+
"""
335+
async with subscriptions_client(ctx) as client:
336+
_ = await client.bulk_suspend_subscriptions(subscription_ids,
337+
details,
338+
all_flag)
339+
340+
341+
@subscriptions.command(name='bulk-reactivate') # type: ignore
342+
@click.option('--subscription-ids',
343+
type=types.CommaSeparatedString(),
344+
help='Comma-separated list of subscription IDs to reactivate')
345+
@click.option('--all',
346+
'all_flag',
347+
is_flag=True,
348+
help='Reactivate all organization subscriptions (admin only)')
349+
@pretty
350+
@click.pass_context
351+
@translate_exceptions
352+
@coro
353+
async def bulk_reactivate_subscriptions_cmd(ctx,
354+
subscription_ids,
355+
all_flag,
356+
pretty):
357+
"""Reactivates multiple subscriptions.
358+
359+
By default (no flags), reactivates all of the user's subscriptions.
360+
Use --subscription-ids to reactivate specific subscriptions.
361+
Use --all to reactivate all organization subscriptions (requires admin).
362+
"""
363+
async with subscriptions_client(ctx) as client:
364+
_ = await client.bulk_reactivate_subscriptions(subscription_ids,
365+
all_flag)
366+
367+
283368
@subscriptions.command(name='update') # type: ignore
284369
@click.argument('subscription_id')
285370
@click.argument('request', type=types.JSON())

planet/clients/subscriptions.py

Lines changed: 158 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,11 +257,167 @@ async def cancel_subscription(self, subscription_id: str) -> None:
257257
except ClientError: # pragma: no cover
258258
raise
259259

260+
async def suspend_subscription(self,
261+
subscription_id: str,
262+
details: Optional[str] = None) -> dict:
263+
"""Suspend a Subscription.
264+
265+
Args:
266+
subscription_id (str): id of subscription to suspend.
267+
details (str): optional details explaining the reason
268+
for suspension.
269+
270+
Returns:
271+
dict: the suspended subscription.
272+
273+
Raises:
274+
APIError: on an API server error.
275+
ClientError: on a client error.
276+
"""
277+
url = f'{self._base_url}/{subscription_id}/suspend'
278+
json_body = {'details': details} if details is not None else None
279+
280+
try:
281+
resp = await self._session.request(method='POST',
282+
url=url,
283+
json=json_body)
284+
except APIError:
285+
raise
286+
except ClientError: # pragma: no cover
287+
raise
288+
else:
289+
return resp.json()
290+
291+
async def reactivate_subscription(self, subscription_id: str) -> None:
292+
"""Reactivate a Subscription.
293+
294+
Args:
295+
subscription_id (str): id of subscription to reactivate.
296+
297+
Returns:
298+
None
299+
300+
Raises:
301+
APIError: on an API server error.
302+
ClientError: on a client error.
303+
"""
304+
url = f'{self._base_url}/{subscription_id}/reactivate'
305+
306+
try:
307+
_ = await self._session.request(method='POST', url=url)
308+
except APIError:
309+
raise
310+
except ClientError: # pragma: no cover
311+
raise
312+
313+
async def bulk_suspend_subscriptions(
314+
self,
315+
subscription_ids: Optional[List[str]] = None,
316+
details: Optional[str] = None,
317+
all_subscriptions: bool = False) -> None:
318+
"""Suspend multiple Subscriptions.
319+
320+
This method supports three modes of operation:
321+
322+
1. Suspend specific subscriptions: provide subscription_ids
323+
2. Suspend all user's subscriptions: call with no parameters
324+
3. Suspend all organization subscriptions: set all_subscriptions=True
325+
(organization admin only)
326+
327+
Args:
328+
subscription_ids (List[str]): list of subscription ids
329+
to suspend. If not provided and all_subscriptions is False,
330+
suspends all of the user's subscriptions.
331+
details (str): optional details explaining the reason
332+
for suspension.
333+
all_subscriptions (bool): if True, suspend all
334+
subscriptions for the organization (requires organization
335+
admin permissions). Mutually exclusive with subscription_ids.
336+
337+
Returns:
338+
None
339+
340+
Raises:
341+
ClientError: if both subscription_ids and all_subscriptions are
342+
provided.
343+
APIError: on an API server error.
344+
"""
345+
if subscription_ids and all_subscriptions:
346+
raise ClientError(
347+
'Cannot specify both subscription_ids and all_subscriptions')
348+
349+
url = f'{self._base_url}/suspend'
350+
params = {'user_id': 'all'} if all_subscriptions else None
351+
json_body: Dict[str, Any] = {}
352+
if subscription_ids is not None:
353+
json_body['subscription_ids'] = subscription_ids
354+
if details is not None:
355+
json_body['details'] = details
356+
357+
try:
358+
_ = await self._session.request(method='POST',
359+
url=url,
360+
json=json_body,
361+
params=params)
362+
except APIError:
363+
raise
364+
except ClientError: # pragma: no cover
365+
raise
366+
367+
async def bulk_reactivate_subscriptions(
368+
self,
369+
subscription_ids: Optional[List[str]] = None,
370+
all_subscriptions: bool = False) -> None:
371+
"""Reactivate multiple Subscriptions.
372+
373+
This method supports three modes of operation:
374+
375+
1. Reactivate specific subscriptions: provide subscription_ids
376+
2. Reactivate all user's subscriptions: call with no parameters
377+
3. Reactivate all organization subscriptions: set all_subscriptions=True
378+
(organization admin only)
379+
380+
Args:
381+
subscription_ids (List[str]): list of subscription ids
382+
to reactivate. If not provided and all_subscriptions is False,
383+
reactivates all of the user's subscriptions.
384+
all_subscriptions (bool): if True, reactivate all
385+
subscriptions for the organization (requires organization
386+
admin permissions). Mutually exclusive with subscription_ids.
387+
388+
Returns:
389+
None
390+
391+
Raises:
392+
ClientError: if both subscription_ids and all_subscriptions are
393+
provided.
394+
APIError: on an API server error.
395+
"""
396+
if subscription_ids and all_subscriptions:
397+
raise ClientError(
398+
'Cannot specify both subscription_ids and all_subscriptions')
399+
400+
url = f'{self._base_url}/reactivate'
401+
params = {'user_id': 'all'} if all_subscriptions else None
402+
json_body = {
403+
'subscription_ids': subscription_ids
404+
} if subscription_ids else None
405+
406+
try:
407+
_ = await self._session.request(method='POST',
408+
url=url,
409+
json=json_body,
410+
params=params)
411+
except APIError:
412+
raise
413+
except ClientError: # pragma: no cover
414+
raise
415+
260416
async def update_subscription(self, subscription_id: str,
261417
request: dict) -> dict:
262418
"""Update (edit) a Subscription via PUT.
263419
264-
Args
420+
Args:
265421
subscription_id (str): id of the subscription to update.
266422
request (dict): subscription content for update, full
267423
payload is required.
@@ -293,7 +449,7 @@ async def patch_subscription(self, subscription_id: str,
293449
request: dict) -> dict:
294450
"""Update (edit) a Subscription via PATCH.
295451
296-
Args
452+
Args:
297453
subscription_id (str): id of the subscription to update.
298454
request (dict): subscription content for update, only
299455
attributes to update are required.

0 commit comments

Comments
 (0)