WriteJobResultsToDrupal.py 7.06 KB
Newer Older
1
from flask_restful import Resource, request
Matthias's avatar
Matthias committed
2
from flask_restful import current_app
Matthias's avatar
Matthias committed
3
4
from requests.auth import HTTPBasicAuth

Matthias's avatar
Matthias committed
5
6
7
8
from helpers.Error import ImportApiError
from datetime import datetime
import requests
import json
9
10
11


class WriteJobResultToDrupal(Resource):
Matthias's avatar
Matthias committed
12
    def post(self, job_drupal_uuid, job_log_drupal_uuid):
13
        """
14
        Write the job summary to Drupal job log (in field_summary)
15
16
        ---
        tags:
17
          - reporting
18
19
        parameters:
        - in: path
Matthias's avatar
Matthias committed
20
          name: job_drupal_uuid
21
22
          required: true
          description: job log uuid
Matthias's avatar
Matthias committed
23
24
25
26
27
          type: string
        - in: path
          name: job_log_drupal_uuid
          required: true
          description: job report log uuid
28
          type: string
29
30
        - in: body
          name: body
31
          required: true
32
33
          schema:
              properties:
Matthias's avatar
Matthias committed
34
                sessionId:
35
                    type: string
Matthias's avatar
Matthias committed
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
                    example: "550e8400-e29b-11d4-a716-446655440000"
                step:
                    type: string
                    example: "media-metadata-extractor"
                total:
                    type: integer
                    example: 468
                success:
                    type: integer
                    example: 413
                ignore:
                    type: integer
                    example: 0
                warning:
                    type: integer
                    example: 455
                fatal:
                    type: integer
                    example: 0
                earliest:
                    type: string
                    example: "2021-03-08T14:02:23.232"
                latest:
                    type: string
                    example: "latest"
                elapsedTime:
                    type: string
                    example: "00:03:11.219"
                recordSetId:
                    type: string
                    example: "fss-001"
                institutionId:
                    type: string
                    example: "fss"
                messageId:
                    type: string
                    example: "1b7d8224-451a-4afb-b5d2-6537acb74051"
                previousMessageId:
                    type: string
                    example: "04543477-3bb5-4d01-a318-52ded1ce5e1c"
                version:
                    type: string
                    example: "3"
79
80
81
        responses:
          200:
            description: It was successful
Lionel Walter's avatar
Lionel Walter committed
82
83
          404:
            description: No log result with such a uuid
84
85
86
          500:
            description: There was a problem
        """
87
        try:
88
            body = request.json
Matthias's avatar
Matthias committed
89
            current_app.logger.debug("report data: " + json.dumps(body, indent=2))
90
            fatal = body['fatal']
Matthias's avatar
Matthias committed
91
92
93
            status = 'FAILED'
            if fatal == 0:
                status = 'SUCCESS'
Matthias's avatar
Matthias committed
94
            return write_results(job_drupal_uuid, job_log_drupal_uuid, status, body)
Lionel Walter's avatar
Lionel Walter committed
95
96
        except ImportApiError as e:
            return {'error': e.message}, 500
Matthias's avatar
Matthias committed
97
98
99
100
101


def write_results(job_drupal_uuid, job_log_drupal_uuid, status, report):
    current_app.logger.debug("job-uuid to write: " + job_drupal_uuid)
    current_app.logger.debug("job-report-uuid to write: " + job_log_drupal_uuid)
Matthias's avatar
Matthias committed
102
    current_app.logger.debug("report to write: " + json.dumps(report, indent=2))
Matthias's avatar
Matthias committed
103
104
105
    headers = {
        'Content-Type': 'application/vnd.api+json',
        'Accept': 'application/vnd.api+json',
Matthias's avatar
Matthias committed
106
        'X-API-Key': current_app.config['drupal-api-key']
Matthias's avatar
Matthias committed
107
108
    }

Matthias's avatar
Matthias committed
109
110
111
112
113
114
115
    user = current_app.config['drupal-user']
    password = current_app.config['drupal-password']
    auth = HTTPBasicAuth(user, password)

    # read "status" and "message" from log_result
    previous_status = ''
    previous_report = ''
Matthias's avatar
Matthias committed
116
    previous_report_json = ''
Matthias's avatar
Matthias committed
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
    step = ''
    try:
        getUrl = current_app.config['drupal-api-url'] + \
            '/jsonapi/node/log_result/' + job_log_drupal_uuid
        response = requests.get(getUrl, headers=headers, auth=auth)
        logResult = response.json()['data']
        previous_status = logResult['attributes']['field_status']
        previous_report = logResult['attributes']['field_message']
    except requests.exceptions.RequestException:
        message = 'It was not possible to read form the Drupal API:' + getUrl +\
            '\nresponse: ' + response
        current_app.logger.error(message)
        raise ImportApiError(message)
    if previous_status == 'FAILED':
        status = previous_status
    if previous_report is None:
Matthias's avatar
Matthias committed
133
134
135
        previous_report_json = {}
    else:
        previous_report_json = json.loads(previous_report)
Matthias's avatar
Matthias committed
136
    step = report['step']
Matthias's avatar
Matthias committed
137
138
    previous_report_json[step] = report
    reportString = json.dumps(previous_report)
Matthias's avatar
Matthias committed
139
140
141
142

    # update values in drupal:
    patchCalls = {}
    patchUrl = current_app.config['drupal-api-url'] + \
Matthias's avatar
Matthias committed
143
144
        '/jsonapi/node/import_process/' + job_drupal_uuid

Matthias's avatar
Matthias committed
145
    patchData = {
Matthias's avatar
Matthias committed
146
147
148
149
150
151
152
153
        "data": {
            "id": job_drupal_uuid,
            "type": "node--import_process",
            "attributes": {
                "field_state": 0
            }
        }
    }
Matthias's avatar
Matthias committed
154
    patchCalls[patchUrl] = patchData
Matthias's avatar
Matthias committed
155

Matthias's avatar
Matthias committed
156
    patchUrl = current_app.config['drupal-api-url'] + \
Matthias's avatar
Matthias committed
157
158
        '/jsonapi/node/log_result/' + job_log_drupal_uuid

Matthias's avatar
Matthias committed
159
    patchData = {
Matthias's avatar
Matthias committed
160
161
162
163
164
165
        "data": {
            "id": job_log_drupal_uuid,
            "type": "node--job_result",
            "attributes": {
                "field_end_date": datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S+00:00"),
                "field_status": status,
Matthias's avatar
Matthias committed
166
                "field_message": reportString
Matthias's avatar
Matthias committed
167
168
169
            }
        }
    }
Matthias's avatar
Matthias committed
170
    patchCalls[patchUrl] = patchData
Matthias's avatar
Matthias committed
171
172
    returnVal = {'message': ''}

Matthias's avatar
Matthias committed
173
174
175
    for patchCall in patchCalls:
        url = patchCall
        data = patchCalls[patchCall]
Matthias's avatar
Matthias committed
176
177
178
179
180
181
182
183
184
185
186
187
        try:
            response = requests.patch(
                url,
                headers=headers,
                data=json.dumps(data)
            )
        except requests.exceptions.RequestException:
            message = "It was not possible to write to Drupal API \
                      via the following url " + url
            current_app.logger.error(message)
            raise ImportApiError(message)
        if response.status_code == 200:
Matthias's avatar
Matthias committed
188
            current_app.logger.debug('Updated: ' + url)
Matthias's avatar
Matthias committed
189
190
191
192
193
194
195
196
197
            returnVal['message'] += 'Updated: ' + url + '\n'
        elif response.status_code == 403:
            message = "Not authorized to write to: " + url
            current_app.logger.error(message)
            raise ImportApiError(message)
        elif response.status_code == 404:
            message = 'Not Found: ' + url
            current_app.logger.error(message)
            raise ImportApiError(message)
Matthias's avatar
Matthias committed
198
        elif response.status_code == 500:
Matthias's avatar
Matthias committed
199
200
            message = 'There was an internal server error for ' + url + ': ' + str(response) +\
                      '. Check the logs for details.'
Matthias's avatar
Matthias committed
201
202
            current_app.logger.error(message)
            raise ImportApiError(message)
Matthias's avatar
Matthias committed
203
204
205
206
207
        else:
            message = "Unknown response status code for drupal api for url " + url
            current_app.logger.error(message)
            raise ImportApiError(message)
    return returnVal