Repository: ansible/awx
File: awx/main/models/unified_jobs.py (Python)

Code before:
        needed = self.get_passwords_needed_to_start()
        try:
            start_args = json.loads(decrypt_field(self, 'start_args'))
        except Exception:
            start_args = None

        if start_args in (None, ''):
            start_args = kwargs

        opts = dict([(field, start_args.get(field, '')) for field in needed])

        if not all(opts.values()):
            missing_fields = ', '.join([k for k, v in opts.items() if not v])
            self.job_explanation = u'Missing needed fields: %s.' % missing_fields
            self.save(update_fields=['job_explanation'])
            return (False, None)

        if 'extra_vars' in kwargs:
            self.handle_extra_data(kwargs['extra_vars'])

        # remove any job_explanations that may have been set while job was in pending
        if self.job_explanation != "":
            self.job_explanation = ""

        return (True, opts)

    def signal_start(self, **kwargs):
        """Notify the task runner system to begin work on this task."""

        # Sanity check: Are we able to start the job? If not, do not attempt
        # to do so.
        if not self.can_start:
            return False

        # Get any passwords or other data that are prerequisites to running
        # the job.
        needed = self.get_passwords_needed_to_start()
        opts = dict([(field, kwargs.get(field, '')) for field in needed])
        if not all(opts.values()):
            return False

        # Save the pending status, and inform the SocketIO listener.
        self.update_fields(start_args=json.dumps(kwargs), status='pending')
        self.websocket_emit_status("pending")

        if self.dependencies_processed:
            ScheduleTaskManager().schedule()
        else:
            ScheduleDependencyManager().schedule()

        # Each type of unified job has a different Task class; get the

Review comment (suggestion):
we already check for all(opts.values()) in get_start_kwargs
maybe get_start_kwargs should just return None, then we check for `if opts is None` here

Code after:
        return opts

    def pre_start(self):
        if not self.can_start:
            self.job_explanation = u'%s is not in a startable state: %s, expecting one of %s' % (self._meta.verbose_name, self.status, str(('new', 'waiting')))
            self.save(update_fields=['job_explanation'])
            return (False, None)

        # verify that any associated credentials aren't missing required field data
        missing_credential_inputs = []
        for credential in self.credentials.all():
            defined_fields = credential.credential_type.defined_fields
            for required in credential.credential_type.inputs.get('required', []):
                if required in defined_fields and not credential.has_input(required):
                    missing_credential_inputs.append(required)

            if missing_credential_inputs:
                self.job_explanation = '{} cannot start because Credential {} does not provide one or more required fields ({}).'.format(
                    self._meta.verbose_name.title(), credential.name, ', '.join(sorted(missing_credential_inputs))
                )
                self.save(update_fields=['job_explanation'])
                return (False, None)

        opts = self.get_start_kwargs()

        if opts and (not all(opts.values())):
            return (False, None)

        # remove any job_explanations that may have been set while job was in pending
        if self.job_explanation != "":
            self.job_explanation = ""

        return (True, opts)

    def signal_start(self, **kwargs):
        """Notify the task runner system to begin work on this task."""

        # Sanity check: Are we able to start the job? If not, do not attempt
        # to do so.
        if not self.can_start:
            return False

        # Get any passwords or other data that are prerequisites to running
        # the job.
        needed = self.get_passwords_needed_to_start()
        opts = dict([(field, kwargs.get(field, '')) for field in needed])
        if not all(opts.values()):
            return False

        # Save the pending status, and inform the SocketIO listener.
        self.update_fields(start_args=json.dumps(kwargs), status='pending')