Skip to content

Commit 82084cd

Browse files
committed
add create_configuraiton support for SH hosting to orders and subs
1 parent c9df445 commit 82084cd

File tree

10 files changed

+261
-38
lines changed

10 files changed

+261
-38
lines changed

docs/cli/cli-orders.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,19 @@ planet orders request \
239239
--collection_id ba8f7274-aacc-425e-8a38-e21517bfbeff
240240
```
241241

242+
```
243+
planet orders request \
244+
--item-type PSScene \
245+
--bundle analytic_sr_udm2 \
246+
--name 'My First Order' \
247+
20220605_124027_64_242b \
248+
--hosting sentinel_hub \
249+
--create_configuration
250+
```
251+
242252
- The --hosting option is optional and currently supports sentinel_hub as its only value.
243253
- The --collection_id is also optional. If you decide to use this, ensure that the order request and the collection have matching bands. If you're unsure, allow the system to create a new collection for you by omitting the --collection_id option. This will ensure the newly set-up collection is configured correctly, and you can subsequently add items to this collection as needed.
254+
- The --create_configuration option will create a new [layer configuration](https://apps.sentinel-hub.com/dashboard/#/configurations) in Sentinel Hub on your behalf. This option cannot be used with --collection_id.
244255

245256
For more information on Sentinel Hub hosting, see the [Orders API documentation](https://developers.planet.com/apis/orders/delivery/#delivery-to-sentinel-hub-collection) and the [Linking Planet User to Sentinel Hub User
246257
](https://support.planet.com/hc/en-us/articles/16550358397469-Linking-Planet-User-to-Sentinel-Hub-User) support post.
@@ -307,14 +318,20 @@ if you run that command again it will create a second order).
307318

308319
#### Sentinel Hub Hosting
309320

310-
For convenience, `planet orders create` accepts the same `--hosting` and `--collection_id` options that [`planet orders request`](#sentinel-hub-hosting) does.
321+
For convenience, `planet orders create` accepts the same `--hosting`, `--collection_id`, and `--create_configuration` options that [`planet orders request`](#sentinel-hub-hosting) does.
311322

312323
```sh
313324
planet orders create request-1.json \
314325
--hosting sentinel_hub \
315326
--collection_id ba8f7274-aacc-425e-8a38-e21517bfbeff
316327
```
317328

329+
```sh
330+
planet orders create request-1.json \
331+
--hosting sentinel_hub \
332+
--create_configuration
333+
```
334+
318335
### Create Request and Order in One Call
319336

320337
Using a unix command called a 'pipe', which looks like `|`, you can skip the step of saving to disk,

docs/cli/cli-subscriptions.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,10 +538,11 @@ planet subscriptions request \
538538

539539
#### Sentinel Hub Hosting
540540

541-
When creating a new subscription, you can include hosting options directly using the --hosting and --collection-id flags.
541+
When creating a new subscription, you can include hosting options directly using the --hosting, --collection-id, and --create-configuration flags.
542542

543543
- The --hosting option is optional and currently supports sentinel_hub as its only value.
544544
- The --collection_id is also optional. If you decide to use this, ensure that the subscription request and the collection have matching bands. If you're unsure, allow the system to create a new collection for you by omitting the --collection_id option. This will ensure the newly set-up collection is configured correctly, and you can subsequently add items to this collection as needed.
545+
- The --create_configuration option will create a new [layer configuration](https://apps.sentinel-hub.com/dashboard/#/configurations) in Sentinel Hub on your behalf. This option cannot be used with --collection_id.
545546
- You may also input --hosting as a JSON file. The file should be formatted:
546547

547548
```sh

planet/cli/orders.py

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,12 @@ async def download(ctx, order_id, overwrite, directory, checksum):
268268
default=None,
269269
help='Collection ID for Sentinel Hub hosting. '
270270
'If omitted, a new collection will be created.')
271+
@click.option(
272+
'--create_configuration',
273+
is_flag=True,
274+
default=False,
275+
help='Automatically create a layer configuration for your collection.'
276+
'If omitted, no configuration will be created.')
271277
@pretty
272278
async def create(ctx, request, pretty, **kwargs):
273279
"""Create an order.
@@ -278,17 +284,21 @@ async def create(ctx, request, pretty, **kwargs):
278284
REQUEST is the full description of the order to be created. It must be JSON
279285
and can be specified a json string, filename, or '-' for stdin.
280286
281-
Other flag options are hosting and collection_id. The hosting flag
282-
specifies the hosting type, and the collection_id flag specifies the
283-
collection ID for Sentinel Hub. If the collection_id is omitted, a new
284-
collection will be created.
287+
Other flag options are hosting, collection_id, and create_configuration.
288+
The hosting flag specifies the hosting type, the collection_id flag specifies the
289+
collection ID for Sentinel Hub, and the create_configuration flag specifies
290+
whether or not to create a layer configuration for your collection. If the
291+
collection_id is omitted, a new collection will be created. If the
292+
create_configuration flag is omitted, no configuration will be created. The
293+
collection_id flag and create_configuration flag cannot be used together.
285294
"""
286295

287296
hosting = kwargs.get('hosting')
288297
collection_id = kwargs.get('collection_id')
298+
create_configuration = bool(kwargs.get('create_configuration', False))
289299

290300
if hosting == "sentinel_hub":
291-
request["hosting"] = sentinel_hub(collection_id)
301+
request["hosting"] = sentinel_hub(collection_id, create_configuration)
292302

293303
async with orders_client(ctx) as cl:
294304
order = await cl.create_order(request)
@@ -363,6 +373,11 @@ async def create(ctx, request, pretty, **kwargs):
363373
@click.option('--collection_id',
364374
help='Collection ID for Sentinel Hub hosting. '
365375
'If omitted, a new collection will be created.')
376+
@click.option(
377+
'--create_configuration',
378+
is_flag=True,
379+
help='Automatically create a layer configuration for your collection.'
380+
'If omitted, no configuration will be created.')
366381
@pretty
367382
async def request(ctx,
368383
item_type,
@@ -379,6 +394,7 @@ async def request(ctx,
379394
stac,
380395
hosting,
381396
collection_id,
397+
create_configuration,
382398
pretty):
383399
"""Generate an order request.
384400
@@ -416,13 +432,15 @@ async def request(ctx,
416432
else:
417433
stac_json = {}
418434

419-
request = planet.order_request.build_request(name,
420-
products=[product],
421-
delivery=delivery,
422-
notifications=notifications,
423-
tools=tools,
424-
stac=stac_json,
425-
hosting=hosting,
426-
collection_id=collection_id)
435+
request = planet.order_request.build_request(
436+
name,
437+
products=[product],
438+
delivery=delivery,
439+
notifications=notifications,
440+
tools=tools,
441+
stac=stac_json,
442+
hosting=hosting,
443+
collection_id=collection_id,
444+
create_configuration=create_configuration)
427445

428446
echo_json(request, pretty)

planet/cli/subscriptions.py

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,11 @@ async def list_subscriptions_cmd(ctx,
165165
default=None,
166166
help='Collection ID for Sentinel Hub hosting. '
167167
'If omitted, a new collection will be created.')
168+
@click.option(
169+
'--create_configuration',
170+
is_flag=True,
171+
help='Automatically create a layer configuration for your collection.'
172+
'If omitted, no configuration will be created.')
168173
@pretty
169174
@click.pass_context
170175
@translate_exceptions
@@ -178,17 +183,21 @@ async def create_subscription_cmd(ctx, request, pretty, **kwargs):
178183
REQUEST is the full description of the subscription to be created. It must
179184
be JSON and can be specified a json string, filename, or '-' for stdin.
180185
181-
Other flag options are hosting and collection_id. The hosting flag
182-
specifies the hosting type, and the collection_id flag specifies the
183-
collection ID for Sentinel Hub. If the collection_id is omitted, a new
184-
collection will be created.
186+
Other flag options are hosting, collection_id, and create_configuration.
187+
The hosting flag specifies the hosting type, the collection_id flag specifies the
188+
collection ID for Sentinel Hub, and the create_configuration flag specifies
189+
whether or not to create a layer configuration for your collection. If the
190+
collection_id is omitted, a new collection will be created. If the
191+
create_configuration flag is omitted, no configuration will be created. The
192+
collection_id flag and create_configuration flag cannot be used together.
185193
"""
186194

187195
hosting = kwargs.get("hosting", None)
188196
collection_id = kwargs.get("collection_id", None)
197+
create_configuration = kwargs.get('create_configuration', False)
189198

190199
if hosting == "sentinel_hub":
191-
hosting_info = sentinel_hub(collection_id)
200+
hosting_info = sentinel_hub(collection_id, create_configuration)
192201
request["hosting"] = hosting_info
193202

194203
async with subscriptions_client(ctx) as client:
@@ -366,6 +375,12 @@ async def list_subscription_results_cmd(ctx,
366375
default=None,
367376
help='Collection ID for Sentinel Hub hosting. '
368377
'If omitted, a new collection will be created.')
378+
@click.option(
379+
'--create_configuration',
380+
is_flag=True,
381+
default=False,
382+
help='Automatically create a layer configuration for your collection.'
383+
'If omitted, no configuration will be created.')
369384
@pretty
370385
def request(name,
371386
source,
@@ -374,6 +389,7 @@ def request(name,
374389
tools,
375390
hosting,
376391
collection_id,
392+
create_configuration,
377393
clip_to_source,
378394
pretty):
379395
"""Generate a subscriptions request.
@@ -384,14 +400,16 @@ def request(name,
384400
default behavior.
385401
"""
386402

387-
res = subscription_request.build_request(name,
388-
source,
389-
delivery,
390-
notifications=notifications,
391-
tools=tools,
392-
hosting=hosting,
393-
collection_id=collection_id,
394-
clip_to_source=clip_to_source)
403+
res = subscription_request.build_request(
404+
name,
405+
source,
406+
delivery,
407+
notifications=notifications,
408+
tools=tools,
409+
hosting=hosting,
410+
collection_id=collection_id,
411+
create_configuration=create_configuration,
412+
clip_to_source=clip_to_source)
395413
echo_json(res, pretty)
396414

397415

planet/order_request.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ def build_request(name: str,
3232
tools: Optional[List[dict]] = None,
3333
stac: Optional[dict] = None,
3434
hosting: Optional[str] = None,
35-
collection_id: Optional[str] = None) -> dict:
35+
collection_id: Optional[str] = None,
36+
create_configuration: Optional[bool] = False) -> dict:
3637
"""Prepare an order request.
3738
3839
```python
@@ -70,6 +71,7 @@ def build_request(name: str,
7071
stac: Include STAC metadata.
7172
hosting: A hosting destination (e.g. Sentinel Hub).
7273
collection_id: A Sentinel Hub collection ID.
74+
create_configuration: Automatically create a layer configuration for your collection.
7375
7476
Raises:
7577
planet.specs.SpecificationException: If order_type is not a valid
@@ -97,7 +99,7 @@ def build_request(name: str,
9799
details['metadata'] = stac
98100

99101
if hosting == 'sentinel_hub':
100-
details['hosting'] = sentinel_hub(collection_id)
102+
details['hosting'] = sentinel_hub(collection_id, create_configuration)
101103

102104
return details
103105

@@ -598,9 +600,12 @@ def band_math_tool(b1: str,
598600
return _tool('bandmath', parameters)
599601

600602

601-
def sentinel_hub(collection_id: Optional[str] = None) -> dict:
603+
def sentinel_hub(collection_id: Optional[str] = None,
604+
create_configuration: Optional[bool] = False) -> dict:
602605
"""Specify a Sentinel Hub hosting destination."""
603606
params = {}
604607
if collection_id:
605608
params['collection_id'] = collection_id
609+
if create_configuration:
610+
params['create_configuration'] = create_configuration
606611
return {'sentinel_hub': params}

planet/subscription_request.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ def build_request(name: str,
5454
tools: Optional[List[Mapping]] = None,
5555
hosting: Optional[Union[Mapping, str]] = None,
5656
collection_id: Optional[str] = None,
57+
create_configuration: Optional[bool] = False,
5758
clip_to_source: Optional[bool] = False) -> dict:
5859
"""Construct a Subscriptions API request.
5960
@@ -68,6 +69,8 @@ def build_request(name: str,
6869
tools: Tools to apply to the products. The order of operation
6970
is determined by the service.
7071
hosting: A hosting destination e.g. Sentinel Hub.
72+
collection_id: A Sentinel Hub collection ID.
73+
create_configuration: Automatically create a layer configuration for your collection.
7174
clip_to_source: whether to clip to the source geometry or not
7275
(the default). If True a clip configuration will be added to
7376
the list of requested tools unless an existing clip tool
@@ -155,6 +158,9 @@ def build_request(name: str,
155158
}
156159
if collection_id:
157160
hosting_info["parameters"]["collection_id"] = collection_id
161+
if create_configuration:
162+
hosting_info["parameters"][
163+
"create_configuration"] = create_configuration
158164
details['hosting'] = hosting_info
159165
elif isinstance(hosting, dict):
160166
details['hosting'] = hosting
@@ -769,18 +775,24 @@ def _hosting(type: str, parameters: dict) -> dict:
769775
return {"type": type, "parameters": parameters}
770776

771777

772-
def sentinel_hub(collection_id: Optional[str]) -> dict:
778+
def sentinel_hub(collection_id: Optional[str],
779+
create_configuration: Optional[bool] = False) -> dict:
773780
"""Specify a Sentinel Hub hosting destination.
774781
775782
Requires the user to have a Sentinel Hub account linked with their Planet
776-
account. Subscriptions API will create a new collection to deliver data to
777-
if collection_id is omitted from the request.
783+
account. Subscriptions API will create a new collection to deliver data to
784+
if collection_id is omitted from the request. Will also create a new layer
785+
configuration for the collection if create_configuration is True.
786+
collection_id and create_configuration are mutually exclusive in the API.
778787
779788
Parameters:
780789
collection_id: Sentinel Hub collection
790+
create_configuration: Automatically create a layer configuration for your collection.
781791
"""
782792

783793
parameters = {}
784794
if collection_id:
785795
parameters['collection_id'] = collection_id
796+
if create_configuration:
797+
parameters['create_configuration'] = create_configuration
786798
return _hosting("sentinel_hub", parameters)

tests/integration/test_orders_cli.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,3 +846,70 @@ def test_cli_orders_request_hosting_sentinel_hub_collection_id(
846846
}
847847
}
848848
assert order_request == json.loads(result.output)
849+
850+
851+
@respx.mock
852+
def test_cli_orders_request_hosting_sentinel_hub_create_configuration(
853+
invoke, stac_json):
854+
855+
result = invoke([
856+
'request',
857+
'--item-type=PSScene',
858+
'--bundle=visual',
859+
'--name=test',
860+
'20220325_131639_20_2402',
861+
'--hosting=sentinel_hub',
862+
'--create_configuration'
863+
])
864+
865+
order_request = {
866+
"name":
867+
"test",
868+
"products": [{
869+
"item_ids": ["20220325_131639_20_2402"],
870+
"item_type": "PSScene",
871+
"product_bundle": "visual",
872+
}],
873+
"metadata":
874+
stac_json,
875+
"hosting": {
876+
"sentinel_hub": {
877+
"create_configuration": True
878+
}
879+
}
880+
}
881+
assert order_request == json.loads(result.output)
882+
883+
884+
@respx.mock
885+
def test_cli_orders_request_hosting_sentinel_hub_collection_configuration(
886+
invoke, stac_json):
887+
# Note, this behavior will be rejected by the API, but it is valid in building a request
888+
result = invoke([
889+
'request',
890+
'--item-type=PSScene',
891+
'--bundle=visual',
892+
'--name=test',
893+
'20220325_131639_20_2402',
894+
'--hosting=sentinel_hub',
895+
'--collection_id=1234',
896+
'--create_configuration'
897+
])
898+
899+
order_request = {
900+
"name":
901+
"test",
902+
"products": [{
903+
"item_ids": ["20220325_131639_20_2402"],
904+
"item_type": "PSScene",
905+
"product_bundle": "visual",
906+
}],
907+
"metadata":
908+
stac_json,
909+
"hosting": {
910+
"sentinel_hub": {
911+
"collection_id": "1234", "create_configuration": True
912+
}
913+
}
914+
}
915+
assert order_request == json.loads(result.output)

0 commit comments

Comments
 (0)