def _run_task(self): self.poll_interval_s = int(self.options.get("poll_interval", 10)) self._poll() # will block until poll_complete self.logger.info("Job is complete.") summary = self.summarize_subjobs(self.subjobs) failed_batches = self.failed_batches(self.subjobs) job_aborted = summary["AnyAborted"] job_failed = summary[ "AnyFailed"] # note that a failed sub-job is different than a failed batch # per https://help.salesforce.com/articleView?id=code_apex_job.htm&type=5 if job_aborted: raise SalesforceException("Job was aborted by a user.") elif job_failed: raise SalesforceException("Job experienced a system failure.") elif failed_batches: self.logger.info("There have been some batch failures.") raise SalesforceException( f"There were batch errors: {repr(failed_batches)}") elif not summary["CountsAddUp"]: self.logger.info("The final record counts do not add up.") self.logger.info("This is probably related to W-1132237") self.logger.info(repr(summary)) if len(self.subjobs) > 1: subjob_summary = f" in {len(self.subjobs)} sub-jobs" else: subjob_summary = "" self.logger.info( f"{self.options['class_name']} took {summary['ElapsedTime']} seconds to process {summary['TotalJobItems']} batches{subjob_summary}." )
def _poll_action(self): # get batch status if not self.original_created_date: query_results = self.tooling.query( self._batch_query(date_limit=None)) if not query_results["records"]: raise SalesforceException( f"No {self.options['class_name']} job found.") self.original_created_date = parse_api_datetime( query_results["records"][0]["CreatedDate"]) else: query_results = self.tooling.query( self._batch_query(date_limit=self.original_created_date)) self.subjobs = query_results["records"] current_subjob = self.subjobs[0] summary = self.summarize_subjobs(self.subjobs) if len(self.subjobs) > 1: subjob_info = f" in {len(self.subjobs)} sub-jobs." else: subjob_info = "" self.logger.info( f"{self.options['class_name']}: " f"Job: {current_subjob['Id']} " f"{summary['JobItemsProcessed']} of {summary['TotalJobItems']} " f"({summary['NumberOfErrors']} failures)" + subjob_info) self.poll_complete = summary["Completed"]
def _run_task(self): self.logger.info('Creating community "{}"'.format( self.options["name"])) # Before we can create a Community, we have to click through the "New Community" # button in the All Communities setup page. (This does some unknown behind-the-scenes setup). # Let's simulate that without actually using a browser. self.logger.info("Preparing org for Communities") s = requests.Session() s.get(self.org_config.start_url).raise_for_status() r = s.get("{}/sites/servlet.SitePrerequisiteServlet".format( self.org_config.instance_url)) if r.status_code != 200: raise SalesforceException("Unable to prepare org for Communities") payload = { "name": self.options["name"], "description": self.options.get("description") or "", "templateName": self.options["template"], "urlPathPrefix": self.options.get("url_path_prefix") or "", } self.logger.info("Sending request to create Community") self.sf.restful("connect/communities", method="POST", data=json.dumps(payload)) # Wait for the community to be created self.time_start = datetime.now() self._poll()
def _poll_action(self): elapsed = datetime.now() - self.time_start if elapsed.total_seconds() > self.options["timeout"]: raise SalesforceException( "Community creation not finished after {timeout} seconds". format(**self.options)) community = self._get_community() if community is not None: self.poll_complete = True self.logger.info("Community {} created".format(community["id"]))
def _process_response(self, result): """Handle the compositeResponse and raise an exception if failed.""" subrequests = result["compositeResponse"] status_codes = {subrequest["httpStatusCode"] for subrequest in subrequests} all_success = all([self._http_ok(code) for code in status_codes]) if self.is_all_or_none and not all_success: self._log_exception_message(subrequests) raise SalesforceException(json.dumps(subrequests, indent=2)) else: self._log_success_message(subrequests)
def _run_task(self): object_handler = getattr(self.sf, self.object) rc = object_handler.create(self.values) if rc["success"]: self.logger.info(f"{self.object} record inserted: {rc['id']}") else: # this will probably never execute, due to simple_salesforce throwing # an exception, but just in case: raise SalesforceException( f"Could not insert {self.object} record : {rc['errors']}" )
def _poll_action(self): elapsed = datetime.now() - self.time_start if elapsed.total_seconds() > self.options["timeout"]: raise SalesforceException( "Community creation not finished after {timeout} seconds". format(**self.options)) community_list = self.sf.restful("connect/communities")["communities"] communities = {c["name"]: c for c in community_list} if self.options["name"] in communities: self.poll_complete = True self.logger.info("Community {} created".format( communities[self.options["name"]]["id"]))
def _poll_action(self, ): soql_check_upload = "select Id, Status, Errors, MetadataPackageVersionId from PackageUploadRequest where Id = '{}'".format( self.upload_id) uploadresult = self.tooling.query(soql_check_upload) if uploadresult['totalSize'] != 1: message = 'Failed to get info for upload with id {}'.format( self.upload_id) self.logger.error(message) raise SalesforceException(message) self.upload = uploadresult['records'][0] self.logger.info('PackageUploadRequest {} is {}'.format( self.upload_id, self.upload['Status'])) self.poll_complete = not self._poll_again(self.upload['Status'])
def _run_task(self): self.poll_interval_s = int(self.options.get('poll_interval', 10)) self._poll() # will block until poll_complete self.logger.info('Job is complete.') if not self.success: self.logger.info('There were some batch failures.') raise SalesforceException(self.batch['ExtendedStatus']) self.logger.info('%s took %d seconds to process %d batches.', self.batch['ApexClass']['Name'], self.delta, self.batch['TotalJobItems']) return self.success
def _check_result(self, result): # anon_results is an ExecuteAnonymous Result # https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/sforce_api_calls_executeanonymous_result.htm anon_results = result.json() # A result of `None` (body == "null") with a 200 status code # means that a gack occurred. if anon_results is None: raise SalesforceException( "Anonymous Apex returned the result `null`. " "This often indicates a gack occurred.") if not anon_results["compiled"]: raise ApexCompilationException(anon_results["line"], anon_results["compileProblem"]) if not anon_results["success"]: raise ApexException(anon_results["exceptionMessage"], anon_results["exceptionStackTrace"])
def _run_task(self): self.poll_interval_s = int(self.options.get("poll_interval", 10)) self._poll() # will block until poll_complete self.logger.info("Job is complete.") if not self.success: self.logger.info("There were some batch failures.") raise SalesforceException(self.batch["ExtendedStatus"]) self.logger.info( "%s took %d seconds to process %d batches.", self.batch["ApexClass"]["Name"], self.delta, self.batch["TotalJobItems"], ) return self.success
def _poll_action(self): try: query_results = self.sf.query(self._object_query) except SalesforceError as e: message = e.content[0]["message"] if "No such column 'SetupOwnerId'" in message: message = "Only Hierarchical Custom Settings objects are supported." raise TaskOptionsError(f"Query Error: {message}") self.record = None for row in query_results["records"]: setupOwnerId = str(row["SetupOwnerId"]) if setupOwnerId.startswith("00D"): self.record = row if not self.record: raise SalesforceException( "Hierarchical Custom Settings Org Default record not found") self.poll_complete = not self._poll_again()
def _run_task(self): community_id = self.options.get("community_id", None) community_name = self.options.get("name", None) if community_id is None: if community_name is None: missing_required = ["name", "community_id"] raise TaskOptionsError("{} requires one of options ({}) " "and no values were provided".format( self.__class__.__name__, ", ".join(missing_required))) self.logger.info('Finding id for Community "{}"'.format( self.options["name"])) community_list = self.sf.restful( "connect/communities")["communities"] communities = {c["name"]: c for c in community_list} if self.options["name"] in communities: community_id = communities[self.options["name"]]["id"] else: raise SalesforceException( 'Unable to find a Community named "{}"'.format( community_id)) self.logger.info( 'Sending request to publish Community "{}" ({})'.format( community_name, community_id)) else: self.logger.info( "Sending request to publish Community ({})".format( community_id)) response = self.sf.restful( "connect/communities/{}/publish".format(community_id), method="POST") self.logger.info(response["message"])
def _run_task(self): self.poll_interval_s = int(self.options.get("poll_interval", 10)) self._poll() # will block until poll_complete self.logger.info("Job is complete.") vals = { key: value for key, value in self.batch.items() if key in { "Id", "Status", "ExtendedStatus", "NumberOfErrors", "JobItemsProcessed", "TotalJobItems", } } if not self.success: self.logger.info("There have been some batch failures.") self.logger.info("Error values:") self.logger.info(repr(vals)) raise SalesforceException("There were import errors: %s" % repr(vals)) elif not self.done_for_sure: self.logger.info("The final record counts do not add up.") self.logger.info("This is probably related to W-1132237") self.logger.info(repr(vals)) self.logger.info( "%s took %d seconds to process %d batches.", self.batch["ApexClass"]["Name"], self.delta, self.batch["TotalJobItems"], ) return self.success
def _get_one_record(self, query, message): result = self.tooling.query(query) if result["totalSize"] != 1: self.logger.error(message) raise SalesforceException(message) return result["records"][0]
def _run_task(self): package_res = self.tooling.query( "select Id from MetadataPackage where NamespacePrefix='{}'".format( self.options['namespace'])) if package_res['totalSize'] != 1: message = 'No package found with namespace {}'.format( self.options['namespace']) self.logger.error(message) raise SalesforceException(message) package_id = package_res['records'][0]['Id'] production = self.options.get('production', False) in [True, 'True', 'true'] package_info = { 'VersionName': self.options['name'], 'IsReleaseVersion': production, 'MetadataPackageId': package_id, } if 'description' in self.options: package_info['Description'] = self.options['description'] if 'password' in self.options: package_info['Password'] = self.options['password'] if 'post_install_url' in self.options: package_info['PostInstallUrl'] = self.options['post_install_url'] if 'release_notes_url' in self.options: package_info['ReleaseNotesUrl'] = self.options['release_notes_url'] PackageUploadRequest = self._get_tooling_object('PackageUploadRequest') self.upload = PackageUploadRequest.create(package_info) self.upload_id = self.upload['id'] self.logger.info( 'Created PackageUploadRequest {} for Package {}'.format( self.upload_id, package_id)) self._poll() if self.upload['Status'] == 'ERROR': self.logger.error( 'Package upload failed with the following errors') for error in self.upload['Errors']['errors']: self.logger.error(' {}'.format(error['message'])) # use the last error in the batch, but log them all. if error['message'] == 'ApexTestFailure': e = ApexTestException else: e = SalesforceException raise e('Package upload failed') else: version_id = self.upload['MetadataPackageVersionId'] version_res = self.tooling.query( "select MajorVersion, MinorVersion, PatchVersion, BuildNumber, ReleaseState from MetadataPackageVersion where Id = '{}'" .format(version_id)) if version_res['totalSize'] != 1: message = 'Version {} not found'.format(version_id) self.logger.error(message) raise SalesforceException(message) version = version_res['records'][0] version_parts = [ str(version['MajorVersion']), str(version['MinorVersion']), ] if version['PatchVersion']: version_parts.append(str(version['PatchVersion'])) self.version_number = '.'.join(version_parts) if version['ReleaseState'] == 'Beta': self.version_number += ' (Beta {})'.format( version['BuildNumber']) self.return_values = { 'version_number': str(self.version_number), 'version_id': version_id, 'package_id': package_id } self.logger.info('Uploaded package version {} with Id {}'.format( self.version_number, version_id))
def _run_task(self): package_res = self.tooling.query( "select Id from MetadataPackage where NamespacePrefix='{}'".format( self.options["namespace"])) if package_res["totalSize"] != 1: message = "No package found with namespace {}".format( self.options["namespace"]) self.logger.error(message) raise SalesforceException(message) package_id = package_res["records"][0]["Id"] production = self.options.get("production", False) in [True, "True", "true"] package_info = { "VersionName": self.options["name"], "IsReleaseVersion": production, "MetadataPackageId": package_id, } if "description" in self.options: package_info["Description"] = self.options["description"] if "password" in self.options: package_info["Password"] = self.options["password"] if "post_install_url" in self.options: package_info["PostInstallUrl"] = self.options["post_install_url"] if "release_notes_url" in self.options: package_info["ReleaseNotesUrl"] = self.options["release_notes_url"] PackageUploadRequest = self._get_tooling_object("PackageUploadRequest") self.upload = PackageUploadRequest.create(package_info) self.upload_id = self.upload["id"] self.logger.info( "Created PackageUploadRequest {} for Package {}".format( self.upload_id, package_id)) self._poll() if self.upload["Status"] == "ERROR": self.logger.error( "Package upload failed with the following errors") for error in self.upload["Errors"]["errors"]: self.logger.error(" {}".format(error["message"])) # use the last error in the batch, but log them all. if error["message"] == "ApexTestFailure": e = ApexTestException else: e = SalesforceException raise e("Package upload failed") else: version_id = self.upload["MetadataPackageVersionId"] version_res = self.tooling.query( "select MajorVersion, MinorVersion, PatchVersion, BuildNumber, ReleaseState from MetadataPackageVersion where Id = '{}'" .format(version_id)) if version_res["totalSize"] != 1: message = "Version {} not found".format(version_id) self.logger.error(message) raise SalesforceException(message) version = version_res["records"][0] version_parts = [ str(version["MajorVersion"]), str(version["MinorVersion"]) ] if version["PatchVersion"]: version_parts.append(str(version["PatchVersion"])) self.version_number = ".".join(version_parts) if version["ReleaseState"] == "Beta": self.version_number += " (Beta {})".format( version["BuildNumber"]) self.return_values = { "version_number": str(self.version_number), "version_id": version_id, "package_id": package_id, } self.logger.info("Uploaded package version {} with Id {}".format( self.version_number, version_id))