Plugins#
EODAG uses a two-level plugin system. Plugin topics are abstract interfaces for a specific functionality of EODAG like Search or Download. EODAG providers are implementations of at least one plugin topic. The more plugin topics are implemented by a provider, the more functionality of eodag are available for this provider.
Plugin Management#
The plugin machinery is managed by one instance of PluginManager. The instance manager knows
how to discover plugins at runtime, using setuptools entry points mechanism.
Plugins Available#
EODAG currently advertises 5 types of plugins: Search, Download, Crunch, Authentication and Api.
The providers are implemented with a triplet of Search/Authentication/Download plugins or with an Api plugin:
Provider |
Search |
Authentication |
Download |
|---|---|---|---|
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|
||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
Creating Plugins#
EODAG plugins can be separated from the core eodag package. They live in your Python site-packages as standalone Python
packages or modules, with eodag’s specific entry points that will be looked at by the plugin manager to load plugins at
runtime. These entry points are: eodag.plugins.{topic}, with possible values for topic being api, search,
crunch, auth and download.
All you have to do to create eodag plugins is start a new Python project, add eodag as a dependancy to your project,
and then create the plugin type you want in Python module(s) by importing its base class from eodag.plugins.{topic}.base
and subclassing it. Here is an example for an Api plugin class located in a module
named your_package.your_module:
from eodag.plugins.apis.base import Api
class SampleApiPlugin(Api):
def query(self):
pass
def download(self):
pass
Then, in the configuration file of your Python project, add this:
[project.entry-points."eodag.plugins.api"]
SampleApiPlugin = "your_package.your_module:SampleApiPlugin"
setup(
# ...
entry_points={
'eodag.plugins.api': [
'SampleApiPlugin = your_package.your_module:SampleApiPlugin'
]
}
)
See what the PyPa explains to better understand this concept. In EODAG, the name you give to your plugin in the entry point doesn’t matter, but we prefer it to be the same as the class name of the plugin. What matters is that the entry point must be a class deriving from one of the 5 plugin topics supported. Be particularly careful with consistency between the entry point name and the super class of you plugin class. Here is a list of entry point names and the plugin topic to which they map:
eodag.plugins.api :
Apieodag.plugins.authentication :
Authenticationeodag.plugins.crunch :
Cruncheodag.plugins.download :
Downloadeodag.plugins.search :
Search
Read the A sample mock search plugin section to get an example of how to build a search plugin.
As an example of external plugin, you can have a look to eodag-sentinelsat (archived).
A sample mock search plugin#
In this section, we demonstrate the creation of custom search plugin. This plugin will return a list of mocked EOProducts on search requests.
Create a folder called eodag_search_mock. It will be the name of our package.
Make an empty __init.py__ file in the package folder.
Make a mock_search.py file and paste in it the following class definition.
It is our search plugin. The query() function is the one called by EODAG when searching for products.
# mock_search.py from typing import Any, List, Optional, Tuple from eodag.plugins.search import PreparedSearch from eodag.plugins.search.base import Search from eodag.api.product import EOProduct class MockSearch(Search): """Implement a Mock search plugin""" def query( self, prep: PreparedSearch = PreparedSearch(), **kwargs: Any, ) -> Tuple[List[EOProduct], Optional[int]]: """Generate EOProduct from the request""" return ([EOProduct( provider=self.provider, properties={ **{ "id": f"mock_{kwargs.get('productType')}_{i}" }, **kwargs } ) for i in range(0, prep.items_per_page)], prep.items_per_page if prep.count else None )
Create a pyproject.toml file in the package folder and paste in it the following content.
The projects.entry-points is crucial for EODAG to detect this new plugin.
[project] name = "eodag-search-mock" version = "0.0.1" description = "Mock Search plugin for EODAG" requires-python = ">=3.8" dependencies = [ "eodag" ] [project.entry-points."eodag.plugins.search"] MockSearch = "mock_search:MockSearch"
Your plugin is now ready. You need to install it for EODAG to be able to use it.
pip install eodag_search_mock
Plugin configuration#
- class eodag.config.PluginConfig[source]#
Representation of a plugin config.
This class variables describe available plugins configuration parameters.
- class Pagination[source]#
Search pagination configuration
-
total_items_nb_key_path:
str|JSONPath# Key path for the number of total items in the provider result
-
next_page_query_obj_key_path:
str|JSONPath# Key path for the next page POST request query-object (body)
-
count_tpl:
str# Template to add to
next_page_url_tplto enable count in search request
-
total_items_nb_key_path:
- class Sort[source]#
Configuration for sort during search
-
sort_by_tpl:
str# F-string template to add to
next_page_url_tplto sort search results
-
sort_param_mapping:
dict[str,str]# Mapping between eodag and provider query parameters used for sort
-
sort_by_tpl:
- class DiscoverMetadata[source]#
Configuration for metadata discovery (search result properties)
- class DiscoverProductTypes[source]#
Configuration for product types discovery
-
generic_product_type_parsable_metadata:
dict[str,str]# Mapping for product type metadata (e.g.
abstract,licence) which can be parsed from the provider result
-
generic_product_type_parsable_properties:
dict[str,str]# Mapping for product type properties which can be parsed from the result and are not product type metadata
-
generic_product_type_unparsable_properties:
dict[str,str]# Mapping for product type properties which cannot be parsed from the result and are not product type metadata
-
generic_product_type_parsable_metadata:
- class OrderStatusSuccess[source]#
Configuration to identify order status success during download
Order status response matching the following parameters are considered success At least one is required
- class OrderStatus[source]#
Configuration for order status during download
-
request:
OrderStatusRequest# Order status request configuration
-
success:
OrderStatusSuccess# Configuration to identify order status success during download
-
ordered:
OrderStatusOrdered# Configuration to identify order status ordered during download
-
on_success:
OrderStatusOnSuccess# Configuration for order status on-success during download
-
request:
- class MetadataPreMapping[source]#
Configuration which can be used to simplify further metadata extraction
-
retry_total:
int# PluginTopicurllib3.util.Retrytotalparameter, total number of retries to allow
-
retry_backoff_factor:
int# PluginTopicurllib3.util.Retrybackoff_factorparameter, backoff factor to apply between attempts after the second try
-
retry_status_forcelist:
list[int]# PluginTopicurllib3.util.Retrystatus_forcelistparameter, list of integer HTTP status codes that we should force a retry on
-
results_entry:
str# SearchKey in the provider search result that gives access to the result entries
-
pagination:
Pagination# SearchDict containing parameters for pagination
-
discover_metadata:
DiscoverMetadata# SearchConfiguration for the metadata auto-discovery
-
discover_product_types:
DiscoverProductTypes# SearchConfiguration for the product types auto-discovery
-
discover_queryables:
DiscoverQueryables# SearchConfiguration for the queryables auto-discovery
-
metadata_mapping:
dict[str,str|list[str]]# SearchThe mapping between eodag metadata and the plugin specific metadata
-
metadata_mapping_from_product:
str# Searchmetadata_mappinggot from the given product type
-
literal_search_params:
dict[str,str]# SearchParameters to be passed as is in the search url query string
-
dont_quote:
list[str]# QueryStringSearchCharacters that should not be quoted in the url params
-
asset_key_from_href:
bool# QueryStringSearchGuess assets keys using theirhref. Use their original key ifFalse
-
free_text_search_operations:
dict[str,Any]# ODataV4SearchDict describing free text search request build
-
per_product_metadata_query:
bool# ODataV4SearchSet toTrueif the metadata is not given in the search result and a two step search has to be performed
-
metadata_pre_mapping:
MetadataPreMapping# ODataV4SearchDict used to simplify further metadata extraction
-
merge_responses:
bool# PostJsonSearchWhether to merge responses or not (aws_eos specific)
-
collection:
list[str]# PostJsonSearchCollections names (aws_eos specific)
-
max_connections:
int# StaticStacSearchMaximum number of connections for concurrent HTTP requests
-
dates_required:
bool# ECMWFSearchif date parameters are mandatory in the request
-
end_date_excluded:
bool# ECMWFSearchWhether end date should be excluded from search request or not
-
remove_from_query:
list[str]# ECMWFSearchList of parameters used to parse metadata but that must not be included to the query
-
order_enabled:
bool# HTTPDownloadWhether the product has to be ordered to download it or not
-
order_method:
str# HTTPDownloadHTTP request method for the order request
-
order_headers:
dict[str,str]# HTTPDownloadHeaders to be added to the order request
-
order_on_response:
OrderOnResponse# HTTPDownloadDictionary containing the keymetadata_mappingwhich can be used to add new product properties based on the data in response to the order request
-
order_status:
OrderStatus# HTTPDownloadOrder status handling
-
no_auth_download:
bool# HTTPDownloadDo not authenticate the download request but only the order and order status ones
-
dl_url_params:
dict[str,str]# HTTPDownloadParameters to be added to the query params of the request
-
bucket_path_level:
int# AwsDownloadAt which level of the path part of the url the bucket can be found
-
s3_endpoint:
str# AwsDownloadS3 endpoint
-
credentials:
dict[str,str]# AuthenticationAuthentication credentials dictionary
-
auth_uri:
str# AuthenticationAuthentication URL
-
headers:
dict[str,str]# AuthenticationDictionary containing all keys/value pairs that should be added to the headers
-
retrieve_headers:
dict[str,str]# AuthenticationDictionary containing all keys/value pairs that should be added to the headers for token retrieve only
-
token_key:
str# AuthenticationThe key pointing to the token in the response from the token server
-
refresh_token_key:
str# AuthenticationKey to get the refresh token in the response from the token server
-
matching_url:
str# AuthenticationURL pattern to match with search plugin endpoint or download link
-
matching_conf:
dict[str,Any]# AuthenticationPart of the search or download plugin configuration that needs authentication
-
token_provision:
str# OIDCRefreshTokenBaseHow the token should be used in the request
-
client_id:
str# OIDCRefreshTokenBaseThe OIDC provider’s client ID
-
client_secret:
str# OIDCRefreshTokenBaseThe OIDC provider’s client secret
-
oidc_config_url:
str# OIDCRefreshTokenBaseThe OIDC provider’s.well-known/openid-configurationurl.
-
allowed_audiences:
list[str]# OIDCRefreshTokenBaseThe OIDC token audiences
-
user_consent_needed:
str# OIDCAuthorizationCodeFlowAuthWhether a user consent is needed during the authentication or not
-
authentication_uri_source:
str# OIDCAuthorizationCodeFlowAuthWhere to look for theauthorization_uri
-
authentication_uri:
str# OIDCAuthorizationCodeFlowAuthThe callback url that will handle the code given by the OIDC provider
-
redirect_uri:
str# OIDCAuthorizationCodeFlowAuthThe URL of the authentication backend of the OIDC provider
-
authorization_uri:
str# OIDCAuthorizationCodeFlowAuthThe authorization url of the server (where to query for grants)
-
login_form_xpath:
str# OIDCAuthorizationCodeFlowAuthThe xpath to the HTML form element representing the user login form
-
user_consent_form_xpath:
str# OIDCAuthorizationCodeFlowAuthThe xpath to the user consent form
-
user_consent_form_data:
dict[str,str]# OIDCAuthorizationCodeFlowAuthThe data that will be passed with the POST request on the form ‘action’ URL
-
additional_login_form_data:
dict[str,str]# OIDCAuthorizationCodeFlowAuthAdditional data to be passed to the login POST request
-
exchange_url_error_pattern:
dict[str,str]# OIDCAuthorizationCodeFlowAuthKey/value pairs of patterns/messages used for Authentication errors
-
token_exchange_params:
dict[str,str]# OIDCAuthorizationCodeFlowAuthA mapping between OIDC url query string and token handler query string params
-
token_qs_key:
str# OIDCAuthorizationCodeFlowAuthRefers to the name of the query param to be used in the query request
-
token_exchange_post_data_method:
str# OIDCAuthorizationCodeFlowAuthWay to pass the data to the POST request that is made to the token server
-
token_uri:
str# OIDCAuthorizationCodeFlowAuthThe url to query to get the authorized token
-
subject:
dict[str,Any]# OIDCTokenExchangeAuthThe fullOIDCAuthorizationCodeFlowAuthplugin configuration used to retrieve subject token
-
subject_issuer:
str# OIDCTokenExchangeAuthIdentifies the issuer of the subject_token
-
token_expiration_margin:
int# TokenAuthOIDCRefreshTokenBaseSafety buffer to prevent token rejection from unexpected expiry between validity check and request.
-
audience:
str# OIDCTokenExchangeAuthAudience that the token ID is intended for.client_idof the Relying Party
-
method:
str# GenericAuthwhich authentication method should be used