eodag 3.9.1__py3-none-any.whl → 4.0.0a1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- eodag/api/core.py +378 -419
- eodag/api/product/__init__.py +3 -3
- eodag/api/product/_product.py +68 -40
- eodag/api/product/drivers/__init__.py +3 -5
- eodag/api/product/drivers/base.py +1 -18
- eodag/api/product/metadata_mapping.py +151 -215
- eodag/api/search_result.py +13 -7
- eodag/cli.py +72 -395
- eodag/config.py +46 -50
- eodag/plugins/apis/base.py +2 -2
- eodag/plugins/apis/ecmwf.py +20 -21
- eodag/plugins/apis/usgs.py +37 -33
- eodag/plugins/authentication/aws_auth.py +36 -1
- eodag/plugins/authentication/base.py +18 -3
- eodag/plugins/authentication/sas_auth.py +15 -0
- eodag/plugins/crunch/filter_date.py +3 -3
- eodag/plugins/crunch/filter_latest_intersect.py +2 -2
- eodag/plugins/crunch/filter_latest_tpl_name.py +1 -1
- eodag/plugins/download/aws.py +45 -41
- eodag/plugins/download/base.py +13 -14
- eodag/plugins/download/http.py +65 -65
- eodag/plugins/manager.py +28 -29
- eodag/plugins/search/__init__.py +3 -4
- eodag/plugins/search/base.py +128 -77
- eodag/plugins/search/build_search_result.py +105 -107
- eodag/plugins/search/cop_marine.py +44 -47
- eodag/plugins/search/csw.py +33 -33
- eodag/plugins/search/qssearch.py +335 -354
- eodag/plugins/search/stac_list_assets.py +1 -1
- eodag/plugins/search/static_stac_search.py +31 -31
- eodag/resources/{product_types.yml → collections.yml} +2353 -2429
- eodag/resources/ext_collections.json +1 -0
- eodag/resources/ext_product_types.json +1 -1
- eodag/resources/providers.yml +2432 -2714
- eodag/resources/stac_provider.yml +46 -90
- eodag/types/queryables.py +55 -91
- eodag/types/search_args.py +1 -1
- eodag/utils/__init__.py +94 -21
- eodag/utils/exceptions.py +6 -6
- eodag/utils/free_text_search.py +3 -3
- {eodag-3.9.1.dist-info → eodag-4.0.0a1.dist-info}/METADATA +11 -88
- eodag-4.0.0a1.dist-info/RECORD +92 -0
- {eodag-3.9.1.dist-info → eodag-4.0.0a1.dist-info}/entry_points.txt +0 -4
- eodag/plugins/authentication/oauth.py +0 -60
- eodag/plugins/download/creodias_s3.py +0 -64
- eodag/plugins/download/s3rest.py +0 -351
- eodag/plugins/search/data_request_search.py +0 -565
- eodag/resources/stac.yml +0 -294
- eodag/resources/stac_api.yml +0 -2105
- eodag/rest/__init__.py +0 -24
- eodag/rest/cache.py +0 -70
- eodag/rest/config.py +0 -67
- eodag/rest/constants.py +0 -26
- eodag/rest/core.py +0 -764
- eodag/rest/errors.py +0 -210
- eodag/rest/server.py +0 -604
- eodag/rest/server.wsgi +0 -6
- eodag/rest/stac.py +0 -1032
- eodag/rest/templates/README +0 -1
- eodag/rest/types/__init__.py +0 -18
- eodag/rest/types/collections_search.py +0 -44
- eodag/rest/types/eodag_search.py +0 -386
- eodag/rest/types/queryables.py +0 -174
- eodag/rest/types/stac_search.py +0 -272
- eodag/rest/utils/__init__.py +0 -207
- eodag/rest/utils/cql_evaluate.py +0 -119
- eodag/rest/utils/rfc3339.py +0 -64
- eodag-3.9.1.dist-info/RECORD +0 -115
- {eodag-3.9.1.dist-info → eodag-4.0.0a1.dist-info}/WHEEL +0 -0
- {eodag-3.9.1.dist-info → eodag-4.0.0a1.dist-info}/licenses/LICENSE +0 -0
- {eodag-3.9.1.dist-info → eodag-4.0.0a1.dist-info}/top_level.txt +0 -0
eodag/cli.py
CHANGED
|
@@ -28,13 +28,10 @@ Options:
|
|
|
28
28
|
--help Show this message and exit.
|
|
29
29
|
|
|
30
30
|
Commands:
|
|
31
|
-
|
|
32
|
-
providers...
|
|
33
|
-
discover Fetch providers to discover product types
|
|
31
|
+
discover Fetch providers to discover collections
|
|
34
32
|
download Download a list of products from a serialized search...
|
|
35
|
-
list List supported
|
|
36
|
-
search Search satellite images by their
|
|
37
|
-
serve-rest Start eodag HTTP server
|
|
33
|
+
list List supported collections
|
|
34
|
+
search Search satellite images by their collections,...
|
|
38
35
|
version Print eodag version and exit
|
|
39
36
|
|
|
40
37
|
noqa: D103
|
|
@@ -44,8 +41,6 @@ from __future__ import annotations
|
|
|
44
41
|
|
|
45
42
|
import functools
|
|
46
43
|
import json
|
|
47
|
-
import os
|
|
48
|
-
import shutil
|
|
49
44
|
import sys
|
|
50
45
|
import textwrap
|
|
51
46
|
from importlib.metadata import metadata
|
|
@@ -56,14 +51,9 @@ import click
|
|
|
56
51
|
|
|
57
52
|
from eodag.api.core import EODataAccessGateway, SearchResult
|
|
58
53
|
from eodag.utils import DEFAULT_ITEMS_PER_PAGE, DEFAULT_PAGE
|
|
59
|
-
from eodag.utils.exceptions import
|
|
54
|
+
from eodag.utils.exceptions import NoMatchingCollection, UnsupportedProvider
|
|
60
55
|
from eodag.utils.logging import setup_logging
|
|
61
56
|
|
|
62
|
-
try:
|
|
63
|
-
from eodag.rest.utils import LIVENESS_PROBE_PATH
|
|
64
|
-
except ImportError:
|
|
65
|
-
pass
|
|
66
|
-
|
|
67
57
|
if TYPE_CHECKING:
|
|
68
58
|
from click import Context
|
|
69
59
|
|
|
@@ -77,18 +67,6 @@ CRUNCHERS = [
|
|
|
77
67
|
]
|
|
78
68
|
|
|
79
69
|
|
|
80
|
-
class LivenessFilter:
|
|
81
|
-
"""
|
|
82
|
-
Filter out requests to the liveness probe endpoint
|
|
83
|
-
"""
|
|
84
|
-
|
|
85
|
-
def filter(self, record):
|
|
86
|
-
"""
|
|
87
|
-
Filter method required by the Python logging API.
|
|
88
|
-
"""
|
|
89
|
-
return LIVENESS_PROBE_PATH not in record.getMessage()
|
|
90
|
-
|
|
91
|
-
|
|
92
70
|
class MutuallyExclusiveOption(click.Option):
|
|
93
71
|
"""Mutually Exclusive Options for Click
|
|
94
72
|
from https://gist.github.com/jacobtolar/fb80d5552a9a9dfc32b12a829fa21c0c
|
|
@@ -164,7 +142,7 @@ def version() -> None:
|
|
|
164
142
|
|
|
165
143
|
@eodag.command(
|
|
166
144
|
name="search",
|
|
167
|
-
help="Search satellite images by their
|
|
145
|
+
help="Search satellite images by their collections, instrument, platform, "
|
|
168
146
|
"platform identifier, processing level or sensor type. It is mandatory to provide "
|
|
169
147
|
"at least one of the previous criteria for eodag to perform a search. "
|
|
170
148
|
"Optionally crunch the search results before storing them in a geojson file",
|
|
@@ -181,6 +159,7 @@ def version() -> None:
|
|
|
181
159
|
help="File path to the user locations configuration file, default is ~/.config/eodag/locations.yml",
|
|
182
160
|
type=click.Path(exists=True),
|
|
183
161
|
)
|
|
162
|
+
@click.option("-p", "--provider", help="Search on this provider")
|
|
184
163
|
@click.option(
|
|
185
164
|
"-b",
|
|
186
165
|
"--box",
|
|
@@ -210,25 +189,18 @@ def version() -> None:
|
|
|
210
189
|
type=click.DateTime(),
|
|
211
190
|
help="End sensing time in ISO8601 format (e.g. '1990-11-26', '1990-11-26T14:30:10'). UTC is assumed",
|
|
212
191
|
)
|
|
192
|
+
@click.option("-c", "--collection", help="The collection to search")
|
|
193
|
+
@click.option("--instruments", help="Search for products matching these instruments")
|
|
194
|
+
@click.option("--platform", help="Search for products matching this platform")
|
|
195
|
+
@click.option("--constellation", help="Search for products matching this constellation")
|
|
213
196
|
@click.option(
|
|
214
|
-
"-
|
|
215
|
-
"--cloudCover",
|
|
216
|
-
type=click.IntRange(0, 100),
|
|
217
|
-
help="Maximum cloud cover percentage needed for the product",
|
|
218
|
-
)
|
|
219
|
-
@click.option("-p", "--productType", help="The product type to search")
|
|
220
|
-
@click.option("-i", "--instrument", help="Search for products matching this instrument")
|
|
221
|
-
@click.option("-P", "--platform", help="Search for products matching this platform")
|
|
222
|
-
@click.option(
|
|
223
|
-
"-t",
|
|
224
|
-
"--platformSerialIdentifier",
|
|
225
|
-
help="Search for products originating from the satellite identified by this keyword",
|
|
197
|
+
"--processing-level", help="Search for products matching this processing level"
|
|
226
198
|
)
|
|
199
|
+
@click.option("--sensor-type", help="Search for products matching this type of sensor")
|
|
227
200
|
@click.option(
|
|
228
|
-
"-
|
|
229
|
-
)
|
|
230
|
-
|
|
231
|
-
"-S", "--sensorType", help="Search for products matching this type of sensor"
|
|
201
|
+
"--cloud-cover",
|
|
202
|
+
type=click.IntRange(0, 100),
|
|
203
|
+
help="Maximum cloud cover percentage needed for the product",
|
|
232
204
|
)
|
|
233
205
|
@click.option("--id", help="Search for the product identified by this id")
|
|
234
206
|
@click.option(
|
|
@@ -299,23 +271,24 @@ def version() -> None:
|
|
|
299
271
|
)
|
|
300
272
|
@click.pass_context
|
|
301
273
|
def search_crunch(ctx: Context, **kwargs: Any) -> None:
|
|
302
|
-
"""Search
|
|
274
|
+
"""Search collections and optionnaly apply crunchers to search results"""
|
|
303
275
|
# Process inputs for search
|
|
304
|
-
|
|
305
|
-
|
|
276
|
+
provider = kwargs.pop("provider")
|
|
277
|
+
collection = kwargs.pop("collection")
|
|
278
|
+
instruments = kwargs.pop("instruments")
|
|
306
279
|
platform = kwargs.pop("platform")
|
|
307
|
-
|
|
308
|
-
processing_level = kwargs.pop("
|
|
309
|
-
sensor_type = kwargs.pop("
|
|
280
|
+
constellation = kwargs.pop("constellation")
|
|
281
|
+
processing_level = kwargs.pop("processing_level")
|
|
282
|
+
sensor_type = kwargs.pop("sensor_type")
|
|
310
283
|
id_ = kwargs.pop("id")
|
|
311
284
|
locations_qs = kwargs.pop("locations")
|
|
312
285
|
custom = kwargs.pop("query")
|
|
313
286
|
if not any(
|
|
314
287
|
[
|
|
315
|
-
|
|
316
|
-
|
|
288
|
+
collection,
|
|
289
|
+
instruments,
|
|
317
290
|
platform,
|
|
318
|
-
|
|
291
|
+
constellation,
|
|
319
292
|
processing_level,
|
|
320
293
|
sensor_type,
|
|
321
294
|
id_,
|
|
@@ -342,16 +315,17 @@ def search_crunch(ctx: Context, **kwargs: Any) -> None:
|
|
|
342
315
|
start_date = kwargs.pop("start")
|
|
343
316
|
stop_date = kwargs.pop("end")
|
|
344
317
|
criteria = {
|
|
318
|
+
"provider": provider,
|
|
345
319
|
"geometry": footprint,
|
|
346
|
-
"
|
|
347
|
-
"
|
|
348
|
-
"
|
|
349
|
-
"
|
|
350
|
-
"
|
|
320
|
+
"start_datetime": None,
|
|
321
|
+
"end_datetime": None,
|
|
322
|
+
"eo:cloud_cover": kwargs.pop("cloud_cover"),
|
|
323
|
+
"collection": collection,
|
|
324
|
+
"instruments": instruments,
|
|
325
|
+
"constellation": constellation,
|
|
351
326
|
"platform": platform,
|
|
352
|
-
"
|
|
353
|
-
"
|
|
354
|
-
"sensorType": sensor_type,
|
|
327
|
+
"processing:level": processing_level,
|
|
328
|
+
"eodag:sensor_type": sensor_type,
|
|
355
329
|
"id": id_,
|
|
356
330
|
}
|
|
357
331
|
if custom:
|
|
@@ -367,9 +341,9 @@ def search_crunch(ctx: Context, **kwargs: Any) -> None:
|
|
|
367
341
|
locations = None
|
|
368
342
|
criteria["locations"] = locations
|
|
369
343
|
if start_date:
|
|
370
|
-
criteria["
|
|
344
|
+
criteria["start_datetime"] = start_date.isoformat()
|
|
371
345
|
if stop_date:
|
|
372
|
-
criteria["
|
|
346
|
+
criteria["end_datetime"] = stop_date.isoformat()
|
|
373
347
|
conf_file = kwargs.pop("conf")
|
|
374
348
|
if conf_file:
|
|
375
349
|
conf_file = click.format_filename(conf_file)
|
|
@@ -431,54 +405,48 @@ def search_crunch(ctx: Context, **kwargs: Any) -> None:
|
|
|
431
405
|
ctx.obj["search_results"] = results
|
|
432
406
|
|
|
433
407
|
|
|
434
|
-
@eodag.command(name="list", help="List supported
|
|
435
|
-
@click.option("-p", "--provider", help="List
|
|
436
|
-
@click.option(
|
|
437
|
-
"-i", "--instrument", help="List product types originating from this instrument"
|
|
438
|
-
)
|
|
408
|
+
@eodag.command(name="list", help="List supported collections")
|
|
409
|
+
@click.option("-p", "--provider", help="List collections supported by this provider")
|
|
439
410
|
@click.option(
|
|
440
|
-
"
|
|
411
|
+
"--instruments", help="List collections originating from these instruments"
|
|
441
412
|
)
|
|
413
|
+
@click.option("--platform", help="List collections originating from this platform")
|
|
442
414
|
@click.option(
|
|
443
|
-
"
|
|
444
|
-
"
|
|
445
|
-
help="List product types originating from the satellite identified by this keyword",
|
|
415
|
+
"--constellation",
|
|
416
|
+
help="List collections originating from this constellation",
|
|
446
417
|
)
|
|
447
|
-
@click.option("-
|
|
418
|
+
@click.option("--processing-level", help="List collections of processing level")
|
|
448
419
|
@click.option(
|
|
449
|
-
"-
|
|
420
|
+
"--sensor-type", help="List collections originating from this type of sensor"
|
|
450
421
|
)
|
|
451
422
|
@click.option(
|
|
452
|
-
"--no-fetch", is_flag=True, help="Do not fetch providers for new
|
|
423
|
+
"--no-fetch", is_flag=True, help="Do not fetch providers for new collections"
|
|
453
424
|
)
|
|
454
425
|
@click.pass_context
|
|
455
426
|
def list_pt(ctx: Context, **kwargs: Any) -> None:
|
|
456
|
-
"""Print the list of supported
|
|
427
|
+
"""Print the list of supported collections"""
|
|
457
428
|
setup_logging(verbose=ctx.obj["verbosity"])
|
|
458
429
|
dag = EODataAccessGateway()
|
|
459
430
|
provider = kwargs.pop("provider")
|
|
460
431
|
fetch_providers = not kwargs.pop("no_fetch")
|
|
461
432
|
text_wrapper = textwrap.TextWrapper()
|
|
462
|
-
|
|
433
|
+
guessed_collections = []
|
|
463
434
|
try:
|
|
464
|
-
|
|
465
|
-
platformSerialIdentifier=kwargs.get("platformserialidentifier"),
|
|
466
|
-
processingLevel=kwargs.get("processinglevel"),
|
|
467
|
-
sensorType=kwargs.get("sensortype"),
|
|
435
|
+
guessed_collections = dag.guess_collection(
|
|
468
436
|
**kwargs,
|
|
469
437
|
)
|
|
470
|
-
except
|
|
438
|
+
except NoMatchingCollection:
|
|
471
439
|
if any(
|
|
472
440
|
kwargs[arg]
|
|
473
441
|
for arg in [
|
|
474
|
-
"
|
|
442
|
+
"instruments",
|
|
443
|
+
"constellation",
|
|
475
444
|
"platform",
|
|
476
|
-
"
|
|
477
|
-
"
|
|
478
|
-
"sensortype",
|
|
445
|
+
"processing_level",
|
|
446
|
+
"sensor_type",
|
|
479
447
|
]
|
|
480
448
|
):
|
|
481
|
-
click.echo("No
|
|
449
|
+
click.echo("No collection match the following criteria you provided:")
|
|
482
450
|
click.echo(
|
|
483
451
|
"\n".join(
|
|
484
452
|
"-{param}={value}".format(**locals())
|
|
@@ -488,22 +456,22 @@ def list_pt(ctx: Context, **kwargs: Any) -> None:
|
|
|
488
456
|
)
|
|
489
457
|
sys.exit(1)
|
|
490
458
|
try:
|
|
491
|
-
if
|
|
492
|
-
|
|
459
|
+
if guessed_collections:
|
|
460
|
+
collections = [
|
|
493
461
|
pt
|
|
494
|
-
for pt in dag.
|
|
462
|
+
for pt in dag.list_collections(
|
|
495
463
|
provider=provider, fetch_providers=fetch_providers
|
|
496
464
|
)
|
|
497
|
-
if pt["ID"] in
|
|
465
|
+
if pt["ID"] in guessed_collections
|
|
498
466
|
]
|
|
499
467
|
else:
|
|
500
|
-
|
|
468
|
+
collections = dag.list_collections(
|
|
501
469
|
provider=provider, fetch_providers=fetch_providers
|
|
502
470
|
)
|
|
503
|
-
click.echo("Listing available
|
|
504
|
-
for
|
|
505
|
-
click.echo("\n* {}: ".format(
|
|
506
|
-
for prop, value in
|
|
471
|
+
click.echo("Listing available collections:")
|
|
472
|
+
for collection in collections:
|
|
473
|
+
click.echo("\n* {}: ".format(collection["ID"]))
|
|
474
|
+
for prop, value in collection.items():
|
|
507
475
|
if prop != "ID":
|
|
508
476
|
text_wrapper.initial_indent = " - {}: ".format(prop)
|
|
509
477
|
text_wrapper.subsequent_indent = " " * len(
|
|
@@ -519,34 +487,34 @@ def list_pt(ctx: Context, **kwargs: Any) -> None:
|
|
|
519
487
|
sys.exit(1)
|
|
520
488
|
|
|
521
489
|
|
|
522
|
-
@eodag.command(name="discover", help="Fetch providers to discover
|
|
490
|
+
@eodag.command(name="discover", help="Fetch providers to discover collections")
|
|
523
491
|
@click.option("-p", "--provider", help="Fetch only the given provider")
|
|
524
492
|
@click.option(
|
|
525
493
|
"--storage",
|
|
526
494
|
type=click.Path(dir_okay=False, writable=True, readable=False),
|
|
527
|
-
default="
|
|
528
|
-
help="Path to the file where to store external
|
|
495
|
+
default="ext_collections.json",
|
|
496
|
+
help="Path to the file where to store external collections configuration "
|
|
529
497
|
"(.json extension will be automatically appended to the filename). "
|
|
530
|
-
"DEFAULT:
|
|
498
|
+
"DEFAULT: ext_collections.json",
|
|
531
499
|
)
|
|
532
500
|
@click.pass_context
|
|
533
501
|
def discover_pt(ctx: Context, **kwargs: Any) -> None:
|
|
534
|
-
"""Fetch external
|
|
502
|
+
"""Fetch external collections configuration and save result"""
|
|
535
503
|
setup_logging(verbose=ctx.obj["verbosity"])
|
|
536
504
|
dag = EODataAccessGateway()
|
|
537
505
|
provider = kwargs.pop("provider")
|
|
538
506
|
|
|
539
|
-
|
|
540
|
-
dag.
|
|
507
|
+
ext_collections_conf = (
|
|
508
|
+
dag.discover_collections(provider=provider)
|
|
541
509
|
if provider
|
|
542
|
-
else dag.
|
|
510
|
+
else dag.discover_collections()
|
|
543
511
|
)
|
|
544
512
|
|
|
545
513
|
storage_filepath = kwargs.pop("storage")
|
|
546
514
|
if not storage_filepath.endswith(".json"):
|
|
547
515
|
storage_filepath += ".json"
|
|
548
516
|
with open(storage_filepath, "w") as f:
|
|
549
|
-
json.dump(
|
|
517
|
+
json.dump(ext_collections_conf, f)
|
|
550
518
|
click.echo("Results stored at '{}'".format(storage_filepath))
|
|
551
519
|
|
|
552
520
|
|
|
@@ -647,296 +615,5 @@ def download(ctx: Context, **kwargs: Any) -> None:
|
|
|
647
615
|
)
|
|
648
616
|
|
|
649
617
|
|
|
650
|
-
@eodag.command(
|
|
651
|
-
help="(deprecated) Start eodag HTTP server\n\n"
|
|
652
|
-
+ (
|
|
653
|
-
click.style(
|
|
654
|
-
"Running a web server from the CLI is deprecated and will be removed in a future version.\n"
|
|
655
|
-
"This feature has been moved to its own repository: https://github.com/CS-SI/stac-fastapi-eodag\n\n",
|
|
656
|
-
fg="yellow",
|
|
657
|
-
bold=True,
|
|
658
|
-
)
|
|
659
|
-
+ "Set EODAG_CORS_ALLOWED_ORIGINS environment variable to configure Cross-Origin Resource Sharing allowed "
|
|
660
|
-
"origins as comma-separated URLs (e.g. 'http://somewhere,http://somewhere.else')."
|
|
661
|
-
)
|
|
662
|
-
)
|
|
663
|
-
@click.option(
|
|
664
|
-
"-f",
|
|
665
|
-
"--config",
|
|
666
|
-
type=click.Path(exists=True, resolve_path=True),
|
|
667
|
-
help="File path to the user configuration file with its credentials, default is ~/.config/eodag/eodag.yml",
|
|
668
|
-
)
|
|
669
|
-
@click.option(
|
|
670
|
-
"-l",
|
|
671
|
-
"--locs",
|
|
672
|
-
type=click.Path(exists=True, resolve_path=True),
|
|
673
|
-
required=False,
|
|
674
|
-
help="File path to the location shapefiles configuration file",
|
|
675
|
-
)
|
|
676
|
-
@click.option(
|
|
677
|
-
"-d", "--daemon", is_flag=True, show_default=True, help="run in daemon mode"
|
|
678
|
-
)
|
|
679
|
-
@click.option(
|
|
680
|
-
"-w",
|
|
681
|
-
"--world",
|
|
682
|
-
is_flag=True,
|
|
683
|
-
show_default=True,
|
|
684
|
-
help=(
|
|
685
|
-
"run uvicorn using IPv4 0.0.0.0 (all network interfaces), "
|
|
686
|
-
"otherwise bind to 127.0.0.1 (localhost). "
|
|
687
|
-
),
|
|
688
|
-
)
|
|
689
|
-
@click.option(
|
|
690
|
-
"-p",
|
|
691
|
-
"--port",
|
|
692
|
-
type=int,
|
|
693
|
-
default=5000,
|
|
694
|
-
show_default=True,
|
|
695
|
-
help="The port on which to listen",
|
|
696
|
-
)
|
|
697
|
-
@click.option(
|
|
698
|
-
"--debug",
|
|
699
|
-
is_flag=True,
|
|
700
|
-
show_default=True,
|
|
701
|
-
help="Run in debug mode (for development purpose)",
|
|
702
|
-
)
|
|
703
|
-
@click.pass_context
|
|
704
|
-
@_deprecated_cli(
|
|
705
|
-
message=(
|
|
706
|
-
"Running a web server from the CLI is deprecated and will be removed in a future version. "
|
|
707
|
-
"This feature has been moved to its own repository: https://github.com/CS-SI/stac-fastapi-eodag"
|
|
708
|
-
),
|
|
709
|
-
version="3.9.0",
|
|
710
|
-
)
|
|
711
|
-
def serve_rest(
|
|
712
|
-
ctx: Context,
|
|
713
|
-
daemon: bool,
|
|
714
|
-
world: bool,
|
|
715
|
-
port: int,
|
|
716
|
-
config: str,
|
|
717
|
-
locs: str,
|
|
718
|
-
debug: bool,
|
|
719
|
-
) -> None:
|
|
720
|
-
"""Serve EODAG functionalities through a WEB interface"""
|
|
721
|
-
setup_logging(verbose=ctx.obj["verbosity"])
|
|
722
|
-
try:
|
|
723
|
-
import uvicorn
|
|
724
|
-
import uvicorn.config
|
|
725
|
-
except ImportError:
|
|
726
|
-
raise ImportError(
|
|
727
|
-
"Feature not available, please install eodag[server] or eodag[all]"
|
|
728
|
-
)
|
|
729
|
-
|
|
730
|
-
# Set the settings of the app
|
|
731
|
-
# IMPORTANT: the order of imports counts here (first we override the settings,
|
|
732
|
-
# then we import the app so that the updated settings is taken into account in
|
|
733
|
-
# the app initialization)
|
|
734
|
-
if config:
|
|
735
|
-
os.environ["EODAG_CFG_FILE"] = config
|
|
736
|
-
|
|
737
|
-
if locs:
|
|
738
|
-
os.environ["EODAG_LOCS_CFG_FILE"] = locs
|
|
739
|
-
|
|
740
|
-
bind_host = "127.0.0.1"
|
|
741
|
-
if world:
|
|
742
|
-
bind_host = "0.0.0.0"
|
|
743
|
-
if daemon:
|
|
744
|
-
try:
|
|
745
|
-
pid = os.fork()
|
|
746
|
-
except OSError as e:
|
|
747
|
-
raise Exception(
|
|
748
|
-
"%s [%d]" % (e.strerror, e.errno) if e.errno is not None else e.strerror
|
|
749
|
-
)
|
|
750
|
-
|
|
751
|
-
if pid == 0:
|
|
752
|
-
os.setsid()
|
|
753
|
-
uvicorn.run("eodag.rest.server:app", host=bind_host, port=port)
|
|
754
|
-
else:
|
|
755
|
-
sys.exit(0)
|
|
756
|
-
else:
|
|
757
|
-
import logging
|
|
758
|
-
|
|
759
|
-
logging_config = uvicorn.config.LOGGING_CONFIG
|
|
760
|
-
uvicorn_fmt = "%(asctime)-15s %(name)-32s [%(levelname)-8s] %(message)s"
|
|
761
|
-
logging_config["filters"] = {"liveness": {"()": LivenessFilter}}
|
|
762
|
-
logging_config["formatters"]["access"]["fmt"] = uvicorn_fmt
|
|
763
|
-
logging_config["formatters"]["default"]["fmt"] = uvicorn_fmt
|
|
764
|
-
logging_config["loggers"]["uvicorn.access"]["filters"] = ["liveness"]
|
|
765
|
-
|
|
766
|
-
eodag_formatter = logging.Formatter(
|
|
767
|
-
"%(asctime)-15s %(name)-32s [%(levelname)-8s] (tid=%(thread)d) %(message)s"
|
|
768
|
-
)
|
|
769
|
-
logging.getLogger("eodag").handlers[0].setFormatter(eodag_formatter)
|
|
770
|
-
|
|
771
|
-
if ctx.obj["verbosity"] <= 1:
|
|
772
|
-
logging_config["handlers"]["null"] = {
|
|
773
|
-
"level": "DEBUG",
|
|
774
|
-
"class": "logging.NullHandler",
|
|
775
|
-
}
|
|
776
|
-
logging_config["loggers"]["uvicorn"]["handlers"] = ["null"]
|
|
777
|
-
logging_config["loggers"]["uvicorn.error"]["handlers"] = ["null"]
|
|
778
|
-
logging_config["loggers"]["uvicorn.access"]["handlers"] = ["null"]
|
|
779
|
-
else:
|
|
780
|
-
log_level = "INFO" if ctx.obj["verbosity"] == 2 else "DEBUG"
|
|
781
|
-
logging_config["loggers"]["uvicorn"]["level"] = log_level
|
|
782
|
-
logging_config["loggers"]["uvicorn.error"]["level"] = log_level
|
|
783
|
-
logging_config["loggers"]["uvicorn.access"]["level"] = log_level
|
|
784
|
-
|
|
785
|
-
uvicorn.run(
|
|
786
|
-
"eodag.rest.server:app",
|
|
787
|
-
host=bind_host,
|
|
788
|
-
port=port,
|
|
789
|
-
reload=debug,
|
|
790
|
-
log_config=logging_config,
|
|
791
|
-
)
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
@eodag.command(
|
|
795
|
-
help="Configure the settings of the HTTP web app (the providers credential "
|
|
796
|
-
"files essentially) and copy the web app source directory into the "
|
|
797
|
-
"specified directory"
|
|
798
|
-
)
|
|
799
|
-
@click.option(
|
|
800
|
-
"--root",
|
|
801
|
-
type=click.Path(exists=True, resolve_path=True),
|
|
802
|
-
default="/var/www/",
|
|
803
|
-
show_default=True,
|
|
804
|
-
help="The directory where to deploy the webapp (a subdirectory with the name "
|
|
805
|
-
"from --name option will be created there)",
|
|
806
|
-
)
|
|
807
|
-
@click.option(
|
|
808
|
-
"-f",
|
|
809
|
-
"--config",
|
|
810
|
-
type=click.Path(exists=True, resolve_path=True),
|
|
811
|
-
required=True,
|
|
812
|
-
help="File path to the user configuration file with its credentials",
|
|
813
|
-
)
|
|
814
|
-
@click.option(
|
|
815
|
-
"--webserver",
|
|
816
|
-
type=click.Choice(["apache"]),
|
|
817
|
-
default="apache",
|
|
818
|
-
show_default=True,
|
|
819
|
-
help="The webserver for which to generate sample configuration",
|
|
820
|
-
)
|
|
821
|
-
@click.option(
|
|
822
|
-
"--threads",
|
|
823
|
-
type=int,
|
|
824
|
-
default=5,
|
|
825
|
-
show_default=True,
|
|
826
|
-
help="Number of threads for apache webserver config (ignored if not apache "
|
|
827
|
-
"webserver)",
|
|
828
|
-
)
|
|
829
|
-
@click.option(
|
|
830
|
-
"--user",
|
|
831
|
-
type=str,
|
|
832
|
-
default="www-data",
|
|
833
|
-
show_default=True,
|
|
834
|
-
help="The user of the webserver",
|
|
835
|
-
)
|
|
836
|
-
@click.option(
|
|
837
|
-
"--group",
|
|
838
|
-
type=str,
|
|
839
|
-
default="www-data",
|
|
840
|
-
show_default=True,
|
|
841
|
-
help="The group of the webserver",
|
|
842
|
-
)
|
|
843
|
-
@click.option(
|
|
844
|
-
"--server-name",
|
|
845
|
-
type=str,
|
|
846
|
-
default="localhost",
|
|
847
|
-
show_default=True,
|
|
848
|
-
help="The name to give to the server",
|
|
849
|
-
)
|
|
850
|
-
@click.option(
|
|
851
|
-
"--wsgi-process-group",
|
|
852
|
-
type=str,
|
|
853
|
-
default="eodag-server",
|
|
854
|
-
show_default=True,
|
|
855
|
-
help="The name of the wsgi process group (ignored if not apache webserver",
|
|
856
|
-
)
|
|
857
|
-
@click.option(
|
|
858
|
-
"--wsgi-daemon-process",
|
|
859
|
-
type=str,
|
|
860
|
-
default="eodag-server",
|
|
861
|
-
show_default=True,
|
|
862
|
-
help="The name of the wsgi daemon process (ignored if not apache webserver",
|
|
863
|
-
)
|
|
864
|
-
@click.option(
|
|
865
|
-
"--name",
|
|
866
|
-
type=str,
|
|
867
|
-
default="eodag_server",
|
|
868
|
-
show_default=True,
|
|
869
|
-
help="The name of the directory that will be created in the webserver root "
|
|
870
|
-
"directory to host the WSGI app",
|
|
871
|
-
)
|
|
872
|
-
@click.pass_context
|
|
873
|
-
def deploy_wsgi_app(
|
|
874
|
-
ctx: Context,
|
|
875
|
-
root: str,
|
|
876
|
-
config: str,
|
|
877
|
-
webserver: str,
|
|
878
|
-
threads: int,
|
|
879
|
-
user: str,
|
|
880
|
-
group: str,
|
|
881
|
-
server_name: str,
|
|
882
|
-
wsgi_process_group: str,
|
|
883
|
-
wsgi_daemon_process: str,
|
|
884
|
-
name: str,
|
|
885
|
-
) -> None:
|
|
886
|
-
"""Deploy the WEB interface of eodag behind a web server"""
|
|
887
|
-
setup_logging(verbose=ctx.obj["verbosity"])
|
|
888
|
-
import eodag as eodag_package
|
|
889
|
-
|
|
890
|
-
server_config = {"EODAG_CFG_FILE": config}
|
|
891
|
-
eodag_package_path = eodag_package.__path__[0]
|
|
892
|
-
webapp_src_path = os.path.join(eodag_package_path, "rest")
|
|
893
|
-
webapp_dst_path = os.path.join(root, name)
|
|
894
|
-
if not os.path.exists(webapp_dst_path):
|
|
895
|
-
os.mkdir(webapp_dst_path)
|
|
896
|
-
wsgi_path = os.path.join(webapp_dst_path, "server.wsgi")
|
|
897
|
-
click.echo(
|
|
898
|
-
"Moving eodag HTTP web app from {} to {}".format(
|
|
899
|
-
webapp_src_path, webapp_dst_path
|
|
900
|
-
)
|
|
901
|
-
)
|
|
902
|
-
shutil.copy(os.path.join(webapp_src_path, "server.wsgi"), wsgi_path)
|
|
903
|
-
|
|
904
|
-
click.echo(
|
|
905
|
-
"Overriding eodag HTTP server config with values: {}".format(server_config)
|
|
906
|
-
)
|
|
907
|
-
with open(os.path.join(webapp_dst_path, "eodag_server_settings.json"), "w") as fd:
|
|
908
|
-
json.dump(server_config, fd)
|
|
909
|
-
|
|
910
|
-
click.echo("Finished ! The WSGI file is in {}".format(wsgi_path))
|
|
911
|
-
if webserver == "apache":
|
|
912
|
-
application_group = "%{GLOBAL}"
|
|
913
|
-
apache_config_sample = (
|
|
914
|
-
"""
|
|
915
|
-
<VirtualHost *>
|
|
916
|
-
ServerName %(server_name)s
|
|
917
|
-
|
|
918
|
-
WSGIDaemonProcess %(wsgi_daemon_process)s user=%(user)s group=%(group)s \
|
|
919
|
-
threads=%(threads)s
|
|
920
|
-
WSGIScriptAlias / %(wsgi_path)s
|
|
921
|
-
|
|
922
|
-
<Directory %(webapp_dst_path)s>
|
|
923
|
-
WSGIProcessGroup %(wsgi_process_group)s
|
|
924
|
-
WSGIApplicationGroup %(application_group)s
|
|
925
|
-
<IfVersion < 2.4>
|
|
926
|
-
Order allow,deny
|
|
927
|
-
Allow from all
|
|
928
|
-
</IfVersion>
|
|
929
|
-
<IfVersion >= 2.4>
|
|
930
|
-
Require all granted
|
|
931
|
-
</IfVersion>
|
|
932
|
-
</Directory>
|
|
933
|
-
</VirtualHost>
|
|
934
|
-
"""
|
|
935
|
-
% locals()
|
|
936
|
-
)
|
|
937
|
-
click.echo("Sample Apache2 config to add in a your virtual host:")
|
|
938
|
-
click.echo(apache_config_sample)
|
|
939
|
-
|
|
940
|
-
|
|
941
618
|
if __name__ == "__main__":
|
|
942
619
|
eodag(obj={})
|