def _process_response_start(self, response): if response.status_code == httplib.INTERNAL_SERVER_ERROR: raise MetadataApiError('HTTP ERROR {}: {}'.format(response.status_code, response.content), response) ids = parseString(response.content).getElementsByTagName('id') if ids: self.process_id = ids[0].firstChild.nodeValue return response
def _handle_soap_error(self, headers, envelope, refresh, response): resp_xml = parseString(response.content) faultcode = resp_xml.getElementsByTagName("faultcode") if faultcode: faultcode = faultcode[0].firstChild.nodeValue faultstring = resp_xml.getElementsByTagName("faultstring") if faultstring: faultstring = faultstring[0].firstChild.nodeValue else: faultstring = response.text if ( faultcode == "sf:INVALID_SESSION_ID" and self.task.org_config and self.task.org_config.refresh_token ): # Attempt to refresh token and recall request if refresh: self.task.org_config.refresh_oauth_token( self.task.project_config.keychain ) return self._call_mdapi(headers, envelope, refresh=False) # Log the error message = f"{faultcode}: {faultstring}" self._set_status("Failed", message) raise MetadataApiError(message, response)
def _process_response_status(self, response): if response.status_code == http.client.INTERNAL_SERVER_ERROR: raise MetadataApiError( "HTTP ERROR {}: {}".format(response.status_code, response.text), response, ) resp_xml = parseString(response.content) done = resp_xml.getElementsByTagName("done") if done: if done[0].firstChild.nodeValue == "true": self._set_status("Done") else: state_detail = resp_xml.getElementsByTagName("stateDetail") if state_detail: log = state_detail[0].firstChild.nodeValue self._set_status("InProgress", log) self.check_num = 1 elif self.status == "InProgress": self.check_num = 1 self._set_status( "InProgress", "next check in {} seconds".format(self._get_check_interval()), ) else: self._set_status( "Pending", "next check in {} seconds".format(self._get_check_interval()), ) else: # If no done element was in the xml, fail logging the entire SOAP # envelope as the log self._set_status("Failed", response.text, response=response) return response
def _process_response_start(self, response): if response.status_code == http.client.INTERNAL_SERVER_ERROR: raise MetadataApiError( f"HTTP ERROR {response.status_code}: {response.text}", response ) ids = parseString(response.content).getElementsByTagName("id") if ids: self.process_id = ids[0].firstChild.nodeValue return response
def test_run_task_with_retry(self): project_config = create_project_config() project_config.get_latest_version = mock.Mock(return_value="1.0") project_config.config["project"]["package"]["namespace"] = "ns" task = create_task(InstallPackageVersion, {"version": "latest"}, project_config) not_yet = MetadataApiError("This package is not yet available", None) api = mock.Mock(side_effect=[not_yet, None]) task.api_class = mock.Mock(return_value=api) task() self.assertEqual(2, api.call_count)
def __call__(self): self.task.logger.info("Pending") response = self._get_response() if self.status != "Failed": try: return self._process_response(response) except Exception as e: raise MetadataParseError( f"Could not process MDAPI response: {str(e)}", response=response ) else: raise MetadataApiError(response.text, response)
def _set_status(self, status, log=None, level=None, response=None): if not level: level = 'info' if status == 'Failed': level = 'error' logger = getattr(self.task.logger, level) self.status = status if log: logger('[{}]: {}'.format(status, log)) else: logger('[{}]'.format(status)) if level == 'error': raise MetadataApiError(log, response)
def _handle_soap_error(self, headers, envelope, refresh, response): faultcode = parseString( response.content).getElementsByTagName('faultcode') if faultcode: faultcode = faultcode[0].firstChild.nodeValue faultstring = parseString( response.content).getElementsByTagName('faultstring') if faultstring: faultstring = faultstring[0].firstChild.nodeValue else: faultstring = response.content if faultcode == 'sf:INVALID_SESSION_ID' and self.task.org_config and self.task.org_config.refresh_token: # Attempt to refresh token and recall request if refresh: self.task.org_config.refresh_oauth_token() return self._call_mdapi(headers, envelope, refresh=False) # Log the error message = '{}: {}'.format(faultcode, faultstring) self._set_status('Failed', message) raise MetadataApiError(message, response)
def _process_response_status(self, response): if response.status_code == httplib.INTERNAL_SERVER_ERROR: raise MetadataApiError('HTTP ERROR {}: {}'.format(response.status_code, response.content), response) resp_xml = parseString(response.content) done = resp_xml.getElementsByTagName('done') if done: if done[0].firstChild.nodeValue == 'true': self._set_status('Done') else: state_detail = resp_xml.getElementsByTagName('stateDetail') if state_detail: log = state_detail[0].firstChild.nodeValue self._set_status('InProgress', log) self.check_num = 1 elif self.status == 'InProgress': self.check_num = 1 self._set_status('InProgress', 'next check in {} seconds'.format(self._get_check_interval())) else: self._set_status('Pending', 'next check in {} seconds'.format(self._get_check_interval())) else: # If no done element was in the xml, fail logging the entire SOAP # envelope as the log self._set_status('Failed', response.content, response=response) return response
def _process_response(self, response): resp_xml = parseString(response.content) status = resp_xml.getElementsByTagName("status") if status: status = status[0].firstChild.nodeValue else: # If no status element is in the result xml, return fail and log # the entire SOAP envelope in the log self._set_status("Failed", response.text) return self.status # Only done responses should be passed so we need to handle any status # related to done if status in ["Succeeded", "SucceededPartial"]: self._set_status("Success", status) else: # If failed, parse out the problem text and raise appropriate exception messages = [] component_failures = resp_xml.getElementsByTagName("componentFailures") for component_failure in component_failures: problems = component_failure.getElementsByTagName("problem") problem_types = component_failure.getElementsByTagName("problemType") failure_info = { "component_type": None, "file_name": None, "line_num": None, "column_num": None, "problem": problems[0].firstChild.nodeValue if problems else "Unknown problem", "problem_type": problem_types[0].firstChild.nodeValue if problem_types else "Error", } failure_info["component_type"] = self._get_element_value( component_failure, "componentType" ) full_name = self._get_element_value(component_failure, "fullName") file_name = self._get_element_value(component_failure, "fileName") failure_info["file_name"] = full_name or file_name failure_info["line_num"] = self._get_element_value( component_failure, "lineNumber" ) failure_info["column_num"] = self._get_element_value( component_failure, "columnNumber" ) created = ( component_failure.getElementsByTagName("created")[ 0 ].firstChild.nodeValue == "true" ) deleted = ( component_failure.getElementsByTagName("deleted")[ 0 ].firstChild.nodeValue == "true" ) failure_info["action"] = self._get_action(created, deleted) if failure_info["file_name"] and failure_info["line_num"]: messages.append( "{action} of {component_type} {file_name}: {problem_type} on line {line_num}, col {column_num}: {problem}".format( **failure_info ) ) elif failure_info["file_name"]: messages.append( "{action} of {component_type} {file_name}: {problem_type}: {problem}".format( **failure_info ) ) else: messages.append( "{action} of {component_type}: {problem_type}: {problem}".format( **failure_info ) ) if messages: # Deploy failures due to a component failure should raise MetadataComponentFailure log = "\n\n".join(messages) self._set_status("Failed", log) raise MetadataComponentFailure(log, response) else: problems = resp_xml.getElementsByTagName("problem") for problem in problems: messages.append(problem.firstChild.nodeValue) errorMessages = resp_xml.getElementsByTagName("errorMessage") for errorMessage in errorMessages: messages.append(errorMessage.firstChild.nodeValue) if messages: log = "\n\n".join(messages) raise MetadataApiError(log, response) # Parse out any failure text (from test failures in production # deployments) and add to log failures = resp_xml.getElementsByTagName("failures") for failure in failures: # Get needed values from subelements namespace = self._get_element_value(failure, "namespace") stacktrace = self._get_element_value(failure, "stackTrace") message = ["Apex Test Failure: "] if namespace: message.append(f"from namespace {namespace}: ") if stacktrace: message.append(stacktrace) messages.append("".join(message)) if messages: # Deploy failures due to a component failure should raise MetadataComponentFailure log = "\n\n".join(messages) self._set_status("Failed", log) raise ApexTestException(log) else: log = response.text self._set_status("Failed", log) raise MetadataApiError(log, response) return self.status
def _process_response(self, response): status = parseString(response.content).getElementsByTagName('status') if status: status = status[0].firstChild.nodeValue else: # If no status element is in the result xml, return fail and log # the entire SOAP envelope in the log self._set_status('Failed', response.content) return self.status # Only done responses should be passed so we need to handle any status # related to done if status in ['Succeeded', 'SucceededPartial']: self._set_status('Success', status) else: # If failed, parse out the problem text and raise appropriate exception messages = [] resp_xml = parseString(response.content) component_failures = resp_xml.getElementsByTagName('componentFailures') for component_failure in component_failures: failure_info = { 'component_type': None, 'file_name': None, 'line_num': None, 'column_num': None, 'problem': component_failure.getElementsByTagName('problem')[0].firstChild.nodeValue, 'problem_type': component_failure.getElementsByTagName('problemType')[0].firstChild.nodeValue, } failure_info['component_type'] = self._get_element_value( component_failure, 'componentType') full_name = self._get_element_value(component_failure, 'fullName') file_name = self._get_element_value(component_failure, 'fileName') failure_info['file_name'] = full_name or file_name failure_info['line_num'] = self._get_element_value(component_failure, 'lineNumber') failure_info['column_num'] = self._get_element_value(component_failure, 'columnNumber') created = component_failure.getElementsByTagName('created')[0].firstChild.nodeValue == 'true' deleted = component_failure.getElementsByTagName('deleted')[0].firstChild.nodeValue == 'true' failure_info['action'] = self._get_action(created, deleted) if failure_info['file_name'] and failure_info['line_num']: messages.append('{action} of {component_type} {file_name}: {problem_type} on line {line_num}, col {column_num}: {problem}'.format(**failure_info)) elif failure_info['file_name']: messages.append('{action} of {component_type} {file_name}: {problem_type}: {problem}'.format(**failure_info)) else: messages.append('{action} of {problem_type}: {problem}'.format(**failure_info)) if messages: # Deploy failures due to a component failure should raise MetadataComponentFailure log = '\n\n'.join(messages) self._set_status('Failed', log) raise MetadataComponentFailure(log, response) else: problems = parseString( response.content).getElementsByTagName('problem') for problem in problems: messages.append(problem.firstChild.nodeValue) # Parse out any failure text (from test failures in production # deployments) and add to log failures = parseString( response.content).getElementsByTagName('failures') for failure in failures: # Get needed values from subelements namespace = self._get_element_value(failure, 'namespace') stacktrace = self._get_element_value(failure, 'stackTrace') message = ['Apex Test Failure: ', ] if namespace: message.append('from namespace {}: '.format(namespace)) if stacktrace: message.append(stacktrace) messages.append(''.join(message)) if messages: # Deploy failures due to a component failure should raise MetadataComponentFailure log = '\n\n'.join(messages) self._set_status('Failed', log) raise ApexTestException(log) else: log = response.content self._set_status('Failed', log) raise MetadataApiError(log, response) return self.status