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

Code before:
        if eager_fields:
            for fd, val in eager_fields.items():
                setattr(unified_job, fd, val)

        # NOTE: slice workflow jobs _get_parent_field_name method
        # is not correct until this is set
        if not parent_field_name:
            parent_field_name = unified_job._get_parent_field_name()
        setattr(unified_job, parent_field_name, self)

        # For JobTemplate-based jobs with surveys, add passwords to list for perma-redaction
        if hasattr(self, 'survey_spec') and getattr(self, 'survey_enabled', False):
            for password in self.survey_password_variables():
                new_job_passwords[password] = REPLACE_STR
        if new_job_passwords:
            unified_job.survey_passwords = new_job_passwords
            kwargs['survey_passwords'] = new_job_passwords  # saved in config object for relaunch

        from awx.main.signals import disable_activity_stream, activity_stream_create
        with disable_activity_stream():
            # Don't emit the activity stream record here for creation,
            # because we haven't attached important M2M relations yet, like
            # credentials and labels
            unified_job.save()

        logger_job_lifecycle.info(f"{unified_job._meta.model_name}-{unified_job.id} created", extra={'type': unified_job._meta.model_name, 'template_name': unified_job.unified_job_template.name, 'job_id': unified_job.id, 'state': 'created'})
        # Labels and credentials copied here
        if validated_kwargs.get('credentials'):
            Credential = UnifiedJob._meta.get_field('credentials').related_model
            cred_dict = Credential.unique_dict(self.credentials.all())
            prompted_dict = Credential.unique_dict(validated_kwargs['credentials'])
            # combine prompted credentials with JT
            cred_dict.update(prompted_dict)
            validated_kwargs['credentials'] = [cred for cred in cred_dict.values()]
            kwargs['credentials'] = validated_kwargs['credentials']

        with disable_activity_stream():
            copy_m2m_relationships(self, unified_job, fields, kwargs=validated_kwargs)

        if 'extra_vars' in validated_kwargs:
            unified_job.handle_extra_data(validated_kwargs['extra_vars'])

        # Create record of provided prompts for relaunch and rescheduling
        unified_job.create_config_from_prompts(kwargs, parent=self)

        # manually issue the create activity stream entry _after_ M2M relations
        # have been associated to the UJ
        if unified_job.__class__ in activity_stream_registrar.models:
            activity_stream_create(None, unified_job, True)

        return unified_job

Review comment (suggestion):
Could we make this a function on `model.UnifiedJob` and use it everywhere below e.g.,

```python
def log_lifecycle(self, status, **extra):
    ....

uj.log_lifecycle('created')
uj.log_lifecycle('blocked', blocked_by='blah blah blah')
```

Code after:
        if eager_fields:
            for fd, val in eager_fields.items():
                setattr(unified_job, fd, val)

        # NOTE: slice workflow jobs _get_parent_field_name method
        # is not correct until this is set
        if not parent_field_name:
            parent_field_name = unified_job._get_parent_field_name()
        setattr(unified_job, parent_field_name, self)

        # For JobTemplate-based jobs with surveys, add passwords to list for perma-redaction
        if hasattr(self, 'survey_spec') and getattr(self, 'survey_enabled', False):
            for password in self.survey_password_variables():
                new_job_passwords[password] = REPLACE_STR
        if new_job_passwords:
            unified_job.survey_passwords = new_job_passwords
            kwargs['survey_passwords'] = new_job_passwords  # saved in config object for relaunch

        from awx.main.signals import disable_activity_stream, activity_stream_create
        with disable_activity_stream():
            # Don't emit the activity stream record here for creation,
            # because we haven't attached important M2M relations yet, like
            # credentials and labels
            unified_job.save()

        # Labels and credentials copied here
        if validated_kwargs.get('credentials'):
            Credential = UnifiedJob._meta.get_field('credentials').related_model
            cred_dict = Credential.unique_dict(self.credentials.all())
            prompted_dict = Credential.unique_dict(validated_kwargs['credentials'])
            # combine prompted credentials with JT
            cred_dict.update(prompted_dict)
            validated_kwargs['credentials'] = [cred for cred in cred_dict.values()]
            kwargs['credentials'] = validated_kwargs['credentials']

        with disable_activity_stream():
            copy_m2m_relationships(self, unified_job, fields, kwargs=validated_kwargs)

        if 'extra_vars' in validated_kwargs:
            unified_job.handle_extra_data(validated_kwargs['extra_vars'])

        # Create record of provided prompts for relaunch and rescheduling
        unified_job.create_config_from_prompts(kwargs, parent=self)

        # manually issue the create activity stream entry _after_ M2M relations
        # have been associated to the UJ
        if unified_job.__class__ in activity_stream_registrar.models:
            activity_stream_create(None, unified_job, True)
        unified_job.log_lifecycle("created")
        return unified_job