class JobOptions(BaseModel): ''' Common options for job templates and jobs. ''' class Meta: abstract = True diff_mode = models.BooleanField( default=False, help_text= _("If enabled, textual changes made to any templated files on the host are shown in the standard output" ), ) job_type = models.CharField( max_length=64, choices=JOB_TYPE_CHOICES, default='run', ) inventory = models.ForeignKey( 'Inventory', related_name='%(class)ss', blank=True, null=True, default=None, on_delete=models.SET_NULL, ) project = models.ForeignKey( 'Project', related_name='%(class)ss', null=True, default=None, blank=True, on_delete=models.SET_NULL, ) playbook = models.CharField( max_length=1024, default='', blank=True, ) scm_branch = models.CharField( max_length=1024, default='', blank=True, help_text=_( 'Branch to use in job run. Project default used if blank. ' 'Only allowed if project allow_override field is set to true.'), ) forks = models.PositiveIntegerField( blank=True, default=0, ) limit = models.TextField( blank=True, default='', ) verbosity = models.PositiveIntegerField( choices=VERBOSITY_CHOICES, blank=True, default=0, ) extra_vars = prevent_search( accepts_json(models.TextField( blank=True, default='', ))) job_tags = models.CharField( max_length=1024, blank=True, default='', ) force_handlers = models.BooleanField( blank=True, default=False, ) skip_tags = models.CharField( max_length=1024, blank=True, default='', ) start_at_task = models.CharField( max_length=1024, blank=True, default='', ) become_enabled = models.BooleanField(default=False, ) allow_simultaneous = models.BooleanField(default=False, ) timeout = models.IntegerField( blank=True, default=0, help_text= _("The amount of time (in seconds) to run before the task is canceled." ), ) use_fact_cache = models.BooleanField( default=False, help_text= _("If enabled, Tower will act as an Ansible Fact Cache Plugin; persisting " "facts at the end of a playbook run to the database and caching facts for use by Ansible." ), ) extra_vars_dict = VarsDictProperty('extra_vars', True) @property def machine_credential(self): return self.credentials.filter(credential_type__kind='ssh').first() @property def network_credentials(self): return list(self.credentials.filter(credential_type__kind='net')) @property def cloud_credentials(self): return list(self.credentials.filter(credential_type__kind='cloud')) @property def vault_credentials(self): return list(self.credentials.filter(credential_type__kind='vault')) @property def passwords_needed_to_start(self): '''Return list of password field names needed to start the job.''' needed = [] # Unsaved credential objects can not require passwords if not self.pk: return needed for cred in self.credentials.all(): needed.extend(cred.passwords_needed) return needed
class ActivityStream(models.Model): """ Model used to describe activity stream (audit) events """ class Meta: app_label = 'main' ordering = ('pk', ) OPERATION_CHOICES = [ ('create', _('Entity Created')), ('update', _("Entity Updated")), ('delete', _("Entity Deleted")), ('associate', _("Entity Associated with another Entity")), ('disassociate', _("Entity was Disassociated with another Entity")), ] actor = models.ForeignKey('auth.User', null=True, on_delete=models.SET_NULL, related_name='activity_stream') operation = models.CharField(max_length=13, choices=OPERATION_CHOICES) timestamp = models.DateTimeField(auto_now_add=True) changes = accepts_json(models.TextField(blank=True)) deleted_actor = JSONField(null=True) action_node = models.CharField( blank=True, default='', editable=False, max_length=512, help_text=_("The cluster node the activity took place on."), ) object_relationship_type = models.TextField(blank=True) object1 = models.TextField() object2 = models.TextField() user = models.ManyToManyField("auth.User", blank=True) organization = models.ManyToManyField("Organization", blank=True) inventory = models.ManyToManyField("Inventory", blank=True) host = models.ManyToManyField("Host", blank=True) group = models.ManyToManyField("Group", blank=True) inventory_source = models.ManyToManyField("InventorySource", blank=True) inventory_update = models.ManyToManyField("InventoryUpdate", blank=True) credential = models.ManyToManyField("Credential", blank=True) credential_type = models.ManyToManyField("CredentialType", blank=True) team = models.ManyToManyField("Team", blank=True) project = models.ManyToManyField("Project", blank=True) project_update = models.ManyToManyField("ProjectUpdate", blank=True) execution_environment = models.ManyToManyField("ExecutionEnvironment", blank=True) job_template = models.ManyToManyField("JobTemplate", blank=True) job = models.ManyToManyField("Job", blank=True) workflow_job_template_node = models.ManyToManyField( "WorkflowJobTemplateNode", blank=True) workflow_job_node = models.ManyToManyField("WorkflowJobNode", blank=True) workflow_job_template = models.ManyToManyField("WorkflowJobTemplate", blank=True) workflow_job = models.ManyToManyField("WorkflowJob", blank=True) workflow_approval_template = models.ManyToManyField( "WorkflowApprovalTemplate", blank=True) workflow_approval = models.ManyToManyField("WorkflowApproval", blank=True) unified_job_template = models.ManyToManyField( "UnifiedJobTemplate", blank=True, related_name='activity_stream_as_unified_job_template+') unified_job = models.ManyToManyField( "UnifiedJob", blank=True, related_name='activity_stream_as_unified_job+') ad_hoc_command = models.ManyToManyField("AdHocCommand", blank=True) schedule = models.ManyToManyField("Schedule", blank=True) execution_environment = models.ManyToManyField("ExecutionEnvironment", blank=True) notification_template = models.ManyToManyField("NotificationTemplate", blank=True) notification = models.ManyToManyField("Notification", blank=True) label = models.ManyToManyField("Label", blank=True) role = models.ManyToManyField("Role", blank=True) instance = models.ManyToManyField("Instance", blank=True) instance_group = models.ManyToManyField("InstanceGroup", blank=True) o_auth2_application = models.ManyToManyField("OAuth2Application", blank=True) o_auth2_access_token = models.ManyToManyField("OAuth2AccessToken", blank=True) setting = JSONField(blank=True) def __str__(self): operation = self.operation if 'operation' in self.__dict__ else '_delayed_' if 'timestamp' in self.__dict__: if self.timestamp: timestamp = self.timestamp.isoformat() else: timestamp = self.timestamp else: timestamp = '_delayed_' return u'%s-%s-pk=%s' % (operation, timestamp, self.pk) def get_absolute_url(self, request=None): return reverse('api:activity_stream_detail', kwargs={'pk': self.pk}, request=request) def save(self, *args, **kwargs): # Store denormalized actor metadata so that we retain it for accounting # purposes when the User row is deleted. if self.actor: self.deleted_actor = { 'id': self.actor_id, 'username': smart_str(self.actor.username), 'first_name': smart_str(self.actor.first_name), 'last_name': smart_str(self.actor.last_name), } if 'update_fields' in kwargs and 'deleted_actor' not in kwargs[ 'update_fields']: kwargs['update_fields'].append('deleted_actor') hostname_char_limit = self._meta.get_field('action_node').max_length self.action_node = settings.CLUSTER_HOST_ID[:hostname_char_limit] super(ActivityStream, self).save(*args, **kwargs)