base_client.py 5.55 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
# Copyright © 2020 Amazon Web Services
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
14
import importlib
Spencer Sutton's avatar
Spencer Sutton committed
15
import os
Sutton's avatar
Sutton committed
16
from configparser import SafeConfigParser
17

18
import requests
19

20
21
from osdu_api.configuration.base_config_manager import BaseConfigManager
from osdu_api.configuration.config_manager import DefaultConfigManager
22
23
from osdu_api.model.http_method import HttpMethod

24

25
class BaseClient:
26
27
28
    """
    Base client that is meant to be extended by service specific clients
    """
29

Spencer Sutton's avatar
Merge    
Spencer Sutton committed
30
    def __init__(self, config_manager: BaseConfigManager = None, data_partition_id = None):
31
32
33
34
        """
        Base client gets initialized with configuration values and a bearer token
        based on provider-specific logic
        """
Spencer Sutton's avatar
Merge    
Spencer Sutton committed
35
        self._parse_config(config_manager, data_partition_id)
36
        self.unauth_retries = 0
37
        if self.use_service_principal:
38
            self._refresh_service_principal_token()
39

Spencer Sutton's avatar
Merge    
Spencer Sutton committed
40
    def _parse_config(self, config_manager: BaseConfigManager = None, data_partition_id = None):
41
        """
42
        Parse config.
43

44
45
        :param config_manager: ConfigManager to get configs, defaults to None
        :type config_manager: BaseConfigManager, optional
46
        """
47
        config_manager = config_manager or DefaultConfigManager()
48

49
50
51
52
53
54
55
56
57
58
59
        self.data_partition_id = config_manager.get('environment', 'data_partition_id')
        self.provider = config_manager.get('provider', 'name')

        self.data_workflow_url = config_manager.get('environment', 'data_workflow_url')
        self.dataset_url = config_manager.get('environment', 'dataset_url')
        self.entitlements_url = config_manager.get('environment', 'entitlements_url')
        self.file_dms_url = config_manager.get('environment', 'file_dms_url')
        self.legal_url = config_manager.get('environment', 'legal_url')
        self.schema_url = config_manager.get('environment', 'schema_url')
        self.search_url = config_manager.get('environment', 'search_url')
        self.storage_url = config_manager.get('environment', 'storage_url')
Spencer Sutton's avatar
Merge    
Spencer Sutton committed
60
61
        self.ingestion_workflow_url = config_manager.get('environment', 'ingestion_workflow_url')
        self.provider = config_manager.get('provider', 'name')
62
63
64
65

        self.use_service_principal = config_manager.getbool('environment', 'use_service_principal', False)
        if self.use_service_principal:
            self.service_principal_module_name = config_manager.get('provider', 'service_principal_module_name')
Sutton's avatar
Sutton committed
66
        config_parser = SafeConfigParser(os.environ)
67
68
69
70
71
        config_file_name = 'osdu_api.ini'
        found_names = config_parser.read(config_file_name)
        if config_file_name not in found_names:
            raise Exception('Could not find osdu_api.ini config file')

Spencer Sutton's avatar
Spencer Sutton committed
72
        if data_partition_id is None:
Spencer Sutton's avatar
Merge    
Spencer Sutton committed
73
            self.data_partition_id = config_manager.get('environment', 'data_partition_id')
Spencer Sutton's avatar
Spencer Sutton committed
74
75
        else:
            self.data_partition_id = data_partition_id
Spencer Sutton's avatar
Bug    
Spencer Sutton committed
76

77
    def _refresh_service_principal_token(self):
78
79
80
81
        """
        The path to the logic to get a valid bearer token is dynamically injected based on
        what provider and entitlements module name is provided in the configuration yaml
        """
Spencer Sutton's avatar
Bug    
Spencer Sutton committed
82
        entitlements_client = importlib.import_module('osdu_api.providers.%s.%s' % (self.provider, self.service_principal_module_name))
83
        self.service_principal_token = entitlements_client.get_service_principal_token()
84

85
    def make_request(self, method: HttpMethod, url: str, data = '', add_headers = {}, params = {}, bearer_token = None):
86
87
88
89
        """
        Makes a request using python's built in requests library. Takes additional headers if
        necessary
        """
90
91
92
        if bearer_token is None:
            bearer_token = self.service_principal_token

93
94
        if bearer_token is not None and 'Bearer ' not in bearer_token:
            bearer_token = 'Bearer ' + bearer_token
95

96
97
98
        headers = {
            'content-type': 'application/json',
            'data-partition-id': self.data_partition_id,
99
            'Authorization': bearer_token
100
101
102
        }

        if (len(add_headers) > 0):
Kyle Longhurst's avatar
Kyle Longhurst committed
103
            for key, value in add_headers.items():
104
105
106
107
108
                headers[key] = value

        response = object

        if (method == HttpMethod.GET):
109
110
111
            response = requests.get(url=url, params=params, headers=headers, verify=False)
        elif (method == HttpMethod.DELETE):
            response = requests.delete(url=url, params=params, headers=headers, verify=False)
112
        elif (method == HttpMethod.POST):
113
            response = requests.post(url=url, params=params, data=data, headers=headers, verify=False)
114
        elif (method == HttpMethod.PUT):
115
            response = requests.put(url=url, params=params, data=data, headers=headers, verify=False)
116
117
118
119
120
121

        if (response.status_code == 401 or response.status_code == 403) and self.unauth_retries < 1:
            if self.use_service_principal == 'True' or self.use_service_principal == 'true':
                self.unauth_retries += 1
                self._refresh_service_principal_token()
                self.make_request(method, url, data, add_headers, params, None)
122

123
        self.unauth_retries = 0
124

Bill Wang's avatar
Bill Wang committed
125
        return response