WriteJobResultsToDrupal.py 7.24 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
    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)
Matthias's avatar
Matthias committed
122
123
124
125
126
127
128
        try:
            logResult = response.json()['data']
            previous_status = logResult['attributes']['field_status']
            previous_report = logResult['attributes']['field_message']
        except Exception:
            msg = 'could not parse response from ' + getUrl
            current_app.logger.error(msg)
Matthias's avatar
Matthias committed
129
130
131
132
133
    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)
Matthias's avatar
Matthias committed
134

Matthias's avatar
Matthias committed
135
136
    if previous_status == 'FAILED':
        status = previous_status
Matthias's avatar
Matthias committed
137
    if previous_report is None or previous_report == 'null':
Matthias's avatar
Matthias committed
138
139
140
        previous_report_json = {}
    else:
        previous_report_json = json.loads(previous_report)
Matthias's avatar
Matthias committed
141
    step = report['step']
Matthias's avatar
Matthias committed
142
    previous_report_json[step] = report
Matthias's avatar
Matthias committed
143
    reportString = json.dumps(previous_report_json)
Matthias's avatar
Matthias committed
144
145
146
147

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

Matthias's avatar
Matthias committed
150
    patchData = {
Matthias's avatar
Matthias committed
151
152
153
154
155
156
157
158
        "data": {
            "id": job_drupal_uuid,
            "type": "node--import_process",
            "attributes": {
                "field_state": 0
            }
        }
    }
Matthias's avatar
Matthias committed
159
    patchCalls[patchUrl] = patchData
Matthias's avatar
Matthias committed
160

Matthias's avatar
Matthias committed
161
    patchUrl = current_app.config['drupal-api-url'] + \
Matthias's avatar
Matthias committed
162
163
        '/jsonapi/node/log_result/' + job_log_drupal_uuid

Matthias's avatar
Matthias committed
164
    patchData = {
Matthias's avatar
Matthias committed
165
166
167
168
169
170
        "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
171
                "field_message": reportString
Matthias's avatar
Matthias committed
172
173
174
            }
        }
    }
Matthias's avatar
Matthias committed
175
    patchCalls[patchUrl] = patchData
Matthias's avatar
Matthias committed
176
177
    returnVal = {'message': ''}

Matthias's avatar
Matthias committed
178
179
180
    for patchCall in patchCalls:
        url = patchCall
        data = patchCalls[patchCall]
Matthias's avatar
Matthias committed
181
182
183
184
185
186
187
188
189
190
191
192
        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
193
            current_app.logger.debug('Updated: ' + url)
Matthias's avatar
Matthias committed
194
195
196
197
198
199
200
201
202
            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
203
        elif response.status_code == 500:
Matthias's avatar
Matthias committed
204
205
            message = 'There was an internal server error for ' + url + ': ' + str(response) +\
                      '. Check the logs for details.'
Matthias's avatar
Matthias committed
206
207
            current_app.logger.error(message)
            raise ImportApiError(message)
Matthias's avatar
Matthias committed
208
209
210
211
212
        else:
            message = "Unknown response status code for drupal api for url " + url
            current_app.logger.error(message)
            raise ImportApiError(message)
    return returnVal