mirror of
https://github.com/ansible/awx.git
synced 2026-01-15 03:40:42 -03:30
Implements https://trello.com/c/bEMQtVjz - API/UI changes to support su username/password. Adds force_handlers, skip_tasks and start_at_task options to jobs, only exposed via API.
This commit is contained in:
parent
87ed378f6b
commit
e427234aec
@ -1135,13 +1135,15 @@ class CredentialSerializer(BaseSerializer):
|
||||
ssh_key_data = serializers.WritableField(required=False, default='')
|
||||
ssh_key_unlock = serializers.WritableField(required=False, default='')
|
||||
sudo_password = serializers.WritableField(required=False, default='')
|
||||
su_password = serializers.WritableField(required=False, default='')
|
||||
vault_password = serializers.WritableField(required=False, default='')
|
||||
|
||||
class Meta:
|
||||
model = Credential
|
||||
fields = ('*', 'user', 'team', 'kind', 'cloud', 'host', 'username',
|
||||
'password', 'project', 'ssh_key_data', 'ssh_key_unlock',
|
||||
'sudo_username', 'sudo_password', 'vault_password')
|
||||
'sudo_username', 'sudo_password', 'su_username',
|
||||
'su_password', 'vault_password')
|
||||
|
||||
def to_native(self, obj):
|
||||
ret = super(CredentialSerializer, self).to_native(obj)
|
||||
@ -1180,7 +1182,8 @@ class JobOptionsSerializer(BaseSerializer):
|
||||
class Meta:
|
||||
fields = ('*', 'job_type', 'inventory', 'project', 'playbook',
|
||||
'credential', 'cloud_credential', 'forks', 'limit',
|
||||
'verbosity', 'extra_vars', 'job_tags')
|
||||
'verbosity', 'extra_vars', 'job_tags', 'force_handlers',
|
||||
'skip_tags', 'start_at_task')
|
||||
|
||||
def get_related(self, obj):
|
||||
res = super(JobOptionsSerializer, self).get_related(obj)
|
||||
@ -1296,6 +1299,9 @@ class JobSerializer(UnifiedJobSerializer, JobOptionsSerializer):
|
||||
data.setdefault('verbosity', job_template.verbosity)
|
||||
data.setdefault('extra_vars', job_template.extra_vars)
|
||||
data.setdefault('job_tags', job_template.job_tags)
|
||||
data.setdefault('force_handlers', job_template.force_handlers)
|
||||
data.setdefault('skip_tags', job_template.skip_tags)
|
||||
data.setdefault('start_at_task', job_template.start_at_task)
|
||||
return super(JobSerializer, self).from_native(data, files)
|
||||
|
||||
def to_native(self, obj):
|
||||
|
||||
@ -174,9 +174,11 @@ class CallbackReceiver(object):
|
||||
with transaction.atomic():
|
||||
# If we're not in verbose mode, wipe out any module
|
||||
# arguments.
|
||||
i = data['event_data'].get('res', {}).get('invocation', {})
|
||||
if verbose == 0 and 'module_args' in i:
|
||||
i['module_args'] = ''
|
||||
res = data['event_data'].get('res', {})
|
||||
if isinstance(res, dict):
|
||||
i = res.get('invocation', {})
|
||||
if verbose == 0 and 'module_args' in i:
|
||||
i['module_args'] = ''
|
||||
|
||||
# Create a new JobEvent object.
|
||||
job_event = JobEvent(**data)
|
||||
|
||||
496
awx/main/migrations/0054_v210_changes.py
Normal file
496
awx/main/migrations/0054_v210_changes.py
Normal file
@ -0,0 +1,496 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from south.utils import datetime_utils as datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding field 'Job.force_handlers'
|
||||
db.add_column(u'main_job', 'force_handlers',
|
||||
self.gf('django.db.models.fields.BooleanField')(default=False),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Job.skip_tags'
|
||||
db.add_column(u'main_job', 'skip_tags',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Job.start_at_task'
|
||||
db.add_column(u'main_job', 'start_at_task',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Credential.su_username'
|
||||
db.add_column(u'main_credential', 'su_username',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Credential.su_password'
|
||||
db.add_column(u'main_credential', 'su_password',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'JobTemplate.force_handlers'
|
||||
db.add_column(u'main_jobtemplate', 'force_handlers',
|
||||
self.gf('django.db.models.fields.BooleanField')(default=False),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'JobTemplate.skip_tags'
|
||||
db.add_column(u'main_jobtemplate', 'skip_tags',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'JobTemplate.start_at_task'
|
||||
db.add_column(u'main_jobtemplate', 'start_at_task',
|
||||
self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting field 'Job.force_handlers'
|
||||
db.delete_column(u'main_job', 'force_handlers')
|
||||
|
||||
# Deleting field 'Job.skip_tags'
|
||||
db.delete_column(u'main_job', 'skip_tags')
|
||||
|
||||
# Deleting field 'Job.start_at_task'
|
||||
db.delete_column(u'main_job', 'start_at_task')
|
||||
|
||||
# Deleting field 'Credential.su_username'
|
||||
db.delete_column(u'main_credential', 'su_username')
|
||||
|
||||
# Deleting field 'Credential.su_password'
|
||||
db.delete_column(u'main_credential', 'su_password')
|
||||
|
||||
# Deleting field 'JobTemplate.force_handlers'
|
||||
db.delete_column(u'main_jobtemplate', 'force_handlers')
|
||||
|
||||
# Deleting field 'JobTemplate.skip_tags'
|
||||
db.delete_column(u'main_jobtemplate', 'skip_tags')
|
||||
|
||||
# Deleting field 'JobTemplate.start_at_task'
|
||||
db.delete_column(u'main_jobtemplate', 'start_at_task')
|
||||
|
||||
|
||||
models = {
|
||||
u'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
u'auth.permission': {
|
||||
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
u'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
u'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'main.activitystream': {
|
||||
'Meta': {'object_name': 'ActivityStream'},
|
||||
'actor': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_stream'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'changes': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'credential': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Credential']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'group': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'host': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Host']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'inventory': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Inventory']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'inventory_source': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventorySource']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'inventory_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventoryUpdate']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'job': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Job']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'job_template': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.JobTemplate']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'object1': ('django.db.models.fields.TextField', [], {}),
|
||||
'object2': ('django.db.models.fields.TextField', [], {}),
|
||||
'object_relationship_type': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'operation': ('django.db.models.fields.CharField', [], {'max_length': '13'}),
|
||||
'organization': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Organization']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'permission': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'project': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Project']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'project_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.ProjectUpdate']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'schedule': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Schedule']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'team': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Team']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'unified_job': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'activity_stream_as_unified_job+'", 'blank': 'True', 'to': "orm['main.UnifiedJob']"}),
|
||||
'unified_job_template': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'activity_stream_as_unified_job_template+'", 'blank': 'True', 'to': "orm['main.UnifiedJobTemplate']"}),
|
||||
'user': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'main.authtoken': {
|
||||
'Meta': {'object_name': 'AuthToken'},
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'key': ('django.db.models.fields.CharField', [], {'max_length': '40', 'primary_key': 'True'}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'request_hash': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '40', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_tokens'", 'to': u"orm['auth.User']"})
|
||||
},
|
||||
'main.credential': {
|
||||
'Meta': {'ordering': "('kind', 'name')", 'unique_together': "[('user', 'team', 'kind', 'name')]", 'object_name': 'Credential'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'cloud': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'credential\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'host': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'kind': ('django.db.models.fields.CharField', [], {'default': "'ssh'", 'max_length': '32'}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'credential\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'project': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100', 'blank': 'True'}),
|
||||
'ssh_key_data': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'ssh_key_unlock': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'su_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'su_username': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'sudo_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'sudo_username': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'team': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'credentials'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Team']"}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'credentials'", 'null': 'True', 'blank': 'True', 'to': u"orm['auth.User']"}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'vault_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'})
|
||||
},
|
||||
'main.group': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('name', 'inventory'),)", 'object_name': 'Group'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'group\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'groups_with_active_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
'has_active_failures': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'has_inventory_sources': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'groups'", 'blank': 'True', 'to': "orm['main.Host']"}),
|
||||
'hosts_with_active_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'groups'", 'to': "orm['main.Inventory']"}),
|
||||
'inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'groups'", 'symmetrical': 'False', 'to': "orm['main.InventorySource']"}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'group\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
|
||||
'parents': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'children'", 'blank': 'True', 'to': "orm['main.Group']"}),
|
||||
'total_groups': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
'total_hosts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
'variables': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'})
|
||||
},
|
||||
'main.host': {
|
||||
'Meta': {'ordering': "('inventory', 'name')", 'unique_together': "(('name', 'inventory'),)", 'object_name': 'Host'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'host\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'has_active_failures': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'has_inventory_sources': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'instance_id': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100', 'blank': 'True'}),
|
||||
'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts'", 'to': "orm['main.Inventory']"}),
|
||||
'inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'hosts'", 'symmetrical': 'False', 'to': "orm['main.InventorySource']"}),
|
||||
'last_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'hosts_as_last_job+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Job']"}),
|
||||
'last_job_host_summary': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts_as_last_job_summary+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobHostSummary']", 'blank': 'True', 'null': 'True'}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'host\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
|
||||
'variables': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'})
|
||||
},
|
||||
'main.inventory': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "[('name', 'organization')]", 'object_name': 'Inventory'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'inventory\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'groups_with_active_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
'has_active_failures': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'has_inventory_sources': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'hosts_with_active_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'inventory_sources_with_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'inventory\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
|
||||
'organization': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventories'", 'to': "orm['main.Organization']"}),
|
||||
'total_groups': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
'total_hosts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
'total_inventory_sources': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
'variables': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'})
|
||||
},
|
||||
'main.inventorysource': {
|
||||
'Meta': {'object_name': 'InventorySource', '_ormbases': ['main.UnifiedJobTemplate']},
|
||||
'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventorysources'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}),
|
||||
'group': ('awx.main.fields.AutoOneToOneField', [], {'default': 'None', 'related_name': "'inventory_source'", 'unique': 'True', 'null': 'True', 'to': "orm['main.Group']"}),
|
||||
'inventory': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_sources'", 'null': 'True', 'to': "orm['main.Inventory']"}),
|
||||
'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'overwrite_vars': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'source': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}),
|
||||
'source_path': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'source_regions': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'source_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
u'unifiedjobtemplate_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJobTemplate']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'update_cache_timeout': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
'update_on_launch': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
|
||||
},
|
||||
'main.inventoryupdate': {
|
||||
'Meta': {'object_name': 'InventoryUpdate', '_ormbases': ['main.UnifiedJob']},
|
||||
'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventoryupdates'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}),
|
||||
'inventory_source': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventory_updates'", 'to': "orm['main.InventorySource']"}),
|
||||
'license_error': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'overwrite_vars': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'source': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}),
|
||||
'source_path': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'source_regions': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'source_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
u'unifiedjob_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJob']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'main.job': {
|
||||
'Meta': {'ordering': "('id',)", 'object_name': 'Job', '_ormbases': ['main.UnifiedJob']},
|
||||
'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs_as_cloud_credential+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}),
|
||||
'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}),
|
||||
'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'force_handlers': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}),
|
||||
'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'jobs'", 'symmetrical': 'False', 'through': "orm['main.JobHostSummary']", 'to': "orm['main.Host']"}),
|
||||
'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}),
|
||||
'job_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobTemplate']", 'blank': 'True', 'null': 'True'}),
|
||||
'job_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
|
||||
'limit': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'playbook': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}),
|
||||
'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}),
|
||||
'skip_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'start_at_task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
u'unifiedjob_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJob']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'verbosity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'})
|
||||
},
|
||||
'main.jobevent': {
|
||||
'Meta': {'ordering': "('pk',)", 'object_name': 'JobEvent'},
|
||||
'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'counter': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'event': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'event_data': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}),
|
||||
'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'host': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'job_events_as_primary_host'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Host']"}),
|
||||
'host_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}),
|
||||
'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'job_events'", 'symmetrical': 'False', 'to': "orm['main.Host']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_events'", 'to': "orm['main.Job']"}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'children'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.JobEvent']"}),
|
||||
'play': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}),
|
||||
'role': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}),
|
||||
'task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'})
|
||||
},
|
||||
'main.jobhostsummary': {
|
||||
'Meta': {'ordering': "('-pk',)", 'unique_together': "[('job', 'host_name')]", 'object_name': 'JobHostSummary'},
|
||||
'changed': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'dark': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
'host': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'job_host_summaries'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Host']"}),
|
||||
'host_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_host_summaries'", 'to': "orm['main.Job']"}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'ok': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
'processed': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
'skipped': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
|
||||
},
|
||||
'main.jobtemplate': {
|
||||
'Meta': {'ordering': "('name',)", 'object_name': 'JobTemplate', '_ormbases': ['main.UnifiedJobTemplate']},
|
||||
'ask_variables_on_launch': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates_as_cloud_credential+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}),
|
||||
'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}),
|
||||
'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'force_handlers': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}),
|
||||
'host_config_key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}),
|
||||
'job_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'job_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
|
||||
'limit': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'playbook': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}),
|
||||
'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}),
|
||||
'skip_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'start_at_task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'survey_enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'survey_spec': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}),
|
||||
u'unifiedjobtemplate_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJobTemplate']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'verbosity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'})
|
||||
},
|
||||
'main.organization': {
|
||||
'Meta': {'ordering': "('name',)", 'object_name': 'Organization'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'admins': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'admin_of_organizations'", 'blank': 'True', 'to': u"orm['auth.User']"}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'organization\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'organization\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
|
||||
'projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organizations'", 'blank': 'True', 'to': "orm['main.Project']"}),
|
||||
'users': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organizations'", 'blank': 'True', 'to': u"orm['auth.User']"})
|
||||
},
|
||||
'main.permission': {
|
||||
'Meta': {'object_name': 'Permission'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'permission\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'permission\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
|
||||
'permission_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
|
||||
'project': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}),
|
||||
'team': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Team']"}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"})
|
||||
},
|
||||
'main.profile': {
|
||||
'Meta': {'object_name': 'Profile'},
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'ldap_dn': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'user': ('awx.main.fields.AutoOneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': u"orm['auth.User']"})
|
||||
},
|
||||
'main.project': {
|
||||
'Meta': {'ordering': "('id',)", 'object_name': 'Project', '_ormbases': ['main.UnifiedJobTemplate']},
|
||||
'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'projects'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}),
|
||||
'local_path': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}),
|
||||
'scm_branch': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}),
|
||||
'scm_clean': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'scm_delete_on_next_update': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'scm_delete_on_update': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'scm_type': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '8', 'blank': 'True'}),
|
||||
'scm_update_cache_timeout': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||
'scm_update_on_launch': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'scm_url': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
u'unifiedjobtemplate_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJobTemplate']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'main.projectupdate': {
|
||||
'Meta': {'object_name': 'ProjectUpdate', '_ormbases': ['main.UnifiedJob']},
|
||||
'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'projectupdates'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}),
|
||||
'local_path': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}),
|
||||
'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'project_updates'", 'to': "orm['main.Project']"}),
|
||||
'scm_branch': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}),
|
||||
'scm_clean': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'scm_delete_on_update': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'scm_type': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '8', 'blank': 'True'}),
|
||||
'scm_url': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
u'unifiedjob_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJob']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'main.schedule': {
|
||||
'Meta': {'ordering': "['-next_run']", 'object_name': 'Schedule'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'schedule\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'dtend': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
|
||||
'dtstart': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
|
||||
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'schedule\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
|
||||
'next_run': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
|
||||
'rrule': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'unified_job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'schedules'", 'to': "orm['main.UnifiedJobTemplate']"})
|
||||
},
|
||||
'main.team': {
|
||||
'Meta': {'ordering': "('organization__name', 'name')", 'unique_together': "[('organization', 'name')]", 'object_name': 'Team'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'team\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'team\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
|
||||
'organization': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'teams'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Organization']"}),
|
||||
'projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'teams'", 'blank': 'True', 'to': "orm['main.Project']"}),
|
||||
'users': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'teams'", 'blank': 'True', 'to': u"orm['auth.User']"})
|
||||
},
|
||||
'main.unifiedjob': {
|
||||
'Meta': {'object_name': 'UnifiedJob'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'cancel_flag': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'celery_task_id': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100', 'blank': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'unifiedjob\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'dependent_jobs': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'dependent_jobs_rel_+'", 'to': "orm['main.UnifiedJob']"}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'elapsed': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '3'}),
|
||||
'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'finished': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'job_args': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'job_cwd': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'job_env': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}),
|
||||
'job_explanation': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'launch_type': ('django.db.models.fields.CharField', [], {'default': "'manual'", 'max_length': '20'}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'unifiedjob\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
|
||||
'old_pk': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'null': 'True'}),
|
||||
'polymorphic_ctype': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'polymorphic_main.unifiedjob_set'", 'null': 'True', 'to': u"orm['contenttypes.ContentType']"}),
|
||||
'result_stdout_file': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'result_stdout_text': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'result_traceback': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'schedule': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['main.Schedule']", 'null': 'True', 'on_delete': 'models.SET_NULL'}),
|
||||
'start_args': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'started': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
|
||||
'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}),
|
||||
'unified_job_template': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'unifiedjob_unified_jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.UnifiedJobTemplate']"})
|
||||
},
|
||||
'main.unifiedjobtemplate': {
|
||||
'Meta': {'unique_together': "[('polymorphic_ctype', 'name')]", 'object_name': 'UnifiedJobTemplate'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'unifiedjobtemplate\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'current_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'unifiedjobtemplate_as_current_job+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.UnifiedJob']"}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'has_schedules': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'last_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'unifiedjobtemplate_as_last_job+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.UnifiedJob']"}),
|
||||
'last_job_failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_job_run': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
|
||||
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||
'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'unifiedjobtemplate\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
|
||||
'next_job_run': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
|
||||
'next_schedule': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'unifiedjobtemplate_as_next_schedule+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Schedule']"}),
|
||||
'old_pk': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'null': 'True'}),
|
||||
'polymorphic_ctype': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'polymorphic_main.unifiedjobtemplate_set'", 'null': 'True', 'to': u"orm['contenttypes.ContentType']"}),
|
||||
'status': ('django.db.models.fields.CharField', [], {'default': "'ok'", 'max_length': '32'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['main']
|
||||
@ -39,7 +39,7 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique):
|
||||
]
|
||||
|
||||
PASSWORD_FIELDS = ('password', 'ssh_key_data', 'ssh_key_unlock',
|
||||
'sudo_password', 'vault_password')
|
||||
'sudo_password', 'su_password', 'vault_password')
|
||||
|
||||
class Meta:
|
||||
app_label = 'main'
|
||||
@ -126,6 +126,18 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique):
|
||||
default='',
|
||||
help_text=_('Sudo password (or "ASK" to prompt the user).'),
|
||||
)
|
||||
su_username = models.CharField(
|
||||
max_length=1024,
|
||||
blank=True,
|
||||
default='',
|
||||
help_text=_('Su username for a job using this credential.'),
|
||||
)
|
||||
su_password = models.CharField(
|
||||
max_length=1024,
|
||||
blank=True,
|
||||
default='',
|
||||
help_text=_('Su password (or "ASK" to prompt the user).'),
|
||||
)
|
||||
vault_password = models.CharField(
|
||||
max_length=1024,
|
||||
blank=True,
|
||||
@ -155,6 +167,10 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique):
|
||||
def needs_sudo_password(self):
|
||||
return self.kind == 'ssh' and self.sudo_password == 'ASK'
|
||||
|
||||
@property
|
||||
def needs_su_password(self):
|
||||
return self.kind == 'ssh' and self.su_password == 'ASK'
|
||||
|
||||
@property
|
||||
def needs_vault_password(self):
|
||||
return self.kind == 'ssh' and self.vault_password == 'ASK'
|
||||
@ -162,7 +178,7 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique):
|
||||
@property
|
||||
def passwords_needed(self):
|
||||
needed = []
|
||||
for field in ('password', 'sudo_password', 'ssh_key_unlock', 'vault_password'):
|
||||
for field in ('password', 'sudo_password', 'su_password', 'ssh_key_unlock', 'vault_password'):
|
||||
if getattr(self, 'needs_%s' % field):
|
||||
needed.append(field)
|
||||
return needed
|
||||
@ -308,6 +324,8 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique):
|
||||
def clean(self):
|
||||
if self.user and self.team:
|
||||
raise ValidationError('Credential cannot be assigned to both a user and team')
|
||||
if (self.sudo_username or self.sudo_password) and (self.su_username or self.su_password):
|
||||
raise ValidationError('Credential cannot specify both sudo username/password and su username/password')
|
||||
|
||||
def _validate_unique_together_with_null(self, unique_check, exclude=None):
|
||||
# Based on existing Django model validation code, except it doesn't
|
||||
|
||||
@ -52,8 +52,9 @@ __all__ = ['JobTemplate', 'Job', 'JobHostSummary', 'JobEvent']
|
||||
|
||||
class JobOptions(BaseModel):
|
||||
'''
|
||||
Common options for job templates and jobs.
|
||||
'''
|
||||
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
@ -115,6 +116,20 @@ class JobOptions(BaseModel):
|
||||
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='',
|
||||
)
|
||||
|
||||
extra_vars_dict = VarsDictProperty('extra_vars', True)
|
||||
|
||||
@ -135,6 +150,18 @@ class JobOptions(BaseModel):
|
||||
)
|
||||
return cred
|
||||
|
||||
@property
|
||||
def passwords_needed_to_start(self):
|
||||
'''Return list of password field names needed to start the job.'''
|
||||
needed = []
|
||||
if self.credential:
|
||||
for pw in self.credential.passwords_needed:
|
||||
if pw == 'password':
|
||||
needed.append('ssh_password')
|
||||
else:
|
||||
needed.append(pw)
|
||||
return needed
|
||||
|
||||
|
||||
class JobTemplate(UnifiedJobTemplate, JobOptions):
|
||||
'''
|
||||
@ -174,7 +201,8 @@ class JobTemplate(UnifiedJobTemplate, JobOptions):
|
||||
def _get_unified_job_field_names(cls):
|
||||
return ['name', 'description', 'job_type', 'inventory', 'project',
|
||||
'playbook', 'credential', 'cloud_credential', 'forks',
|
||||
'limit', 'verbosity', 'extra_vars', 'job_tags']
|
||||
'limit', 'verbosity', 'extra_vars', 'job_tags',
|
||||
'force_handlers', 'skip_tags', 'start_at_task']
|
||||
|
||||
def create_job(self, **kwargs):
|
||||
'''
|
||||
@ -190,26 +218,7 @@ class JobTemplate(UnifiedJobTemplate, JobOptions):
|
||||
Return whether job template can be used to start a new job without
|
||||
requiring any user input.
|
||||
'''
|
||||
needed = []
|
||||
if self.credential:
|
||||
for pw in self.credential.passwords_needed:
|
||||
if pw == 'password':
|
||||
needed.append('ssh_password')
|
||||
else:
|
||||
needed.append(pw)
|
||||
return bool(self.credential and not len(needed))
|
||||
|
||||
@property
|
||||
def passwords_needed_to_start(self):
|
||||
'''Return list of password field names needed to start the job.'''
|
||||
needed = []
|
||||
if self.credential:
|
||||
for pw in self.credential.passwords_needed:
|
||||
if pw == 'password':
|
||||
needed.append('ssh_password')
|
||||
else:
|
||||
needed.append(pw)
|
||||
return needed
|
||||
return bool(self.credential and not len(self.passwords_needed_to_start))
|
||||
|
||||
@property
|
||||
def variables_needed_to_start(self):
|
||||
@ -337,18 +346,6 @@ class Job(UnifiedJob, JobOptions):
|
||||
return self.job_template.ask_variables_on_launch
|
||||
return False
|
||||
|
||||
@property
|
||||
def passwords_needed_to_start(self):
|
||||
'''Return list of password field names needed to start the job.'''
|
||||
needed = []
|
||||
if self.credential:
|
||||
for pw in self.credential.passwords_needed:
|
||||
if pw == 'password':
|
||||
needed.append('ssh_password')
|
||||
else:
|
||||
needed.append(pw)
|
||||
return needed
|
||||
|
||||
def get_passwords_needed_to_start(self):
|
||||
return self.passwords_needed_to_start
|
||||
|
||||
|
||||
@ -479,13 +479,13 @@ class RunJob(BaseTask):
|
||||
|
||||
def build_passwords(self, job, **kwargs):
|
||||
'''
|
||||
Build a dictionary of passwords for SSH private key, SSH user, sudo
|
||||
Build a dictionary of passwords for SSH private key, SSH user, sudo/su
|
||||
and ansible-vault.
|
||||
'''
|
||||
passwords = super(RunJob, self).build_passwords(job, **kwargs)
|
||||
creds = job.credential
|
||||
if creds:
|
||||
for field in ('ssh_key_unlock', 'ssh_password', 'sudo_password', 'vault_password'):
|
||||
for field in ('ssh_key_unlock', 'ssh_password', 'sudo_password', 'su_password', 'vault_password'):
|
||||
if field == 'ssh_password':
|
||||
value = kwargs.get(field, decrypt_field(creds, 'password'))
|
||||
else:
|
||||
@ -550,10 +550,11 @@ class RunJob(BaseTask):
|
||||
optionally using ssh-agent for public/private key authentication.
|
||||
'''
|
||||
creds = job.credential
|
||||
ssh_username, sudo_username = '', ''
|
||||
ssh_username, sudo_username, su_username = '', '', ''
|
||||
if creds:
|
||||
ssh_username = kwargs.get('username', creds.username)
|
||||
sudo_username = kwargs.get('sudo_username', creds.sudo_username)
|
||||
su_username = kwargs.get('su_username', creds.su_username)
|
||||
# Always specify the normal SSH user as root by default. Since this
|
||||
# task is normally running in the background under a service account,
|
||||
# it doesn't make sense to rely on ansible-playbook's default of using
|
||||
@ -567,9 +568,12 @@ class RunJob(BaseTask):
|
||||
args.extend(['-u', ssh_username])
|
||||
if 'ssh_password' in kwargs.get('passwords', {}):
|
||||
args.append('--ask-pass')
|
||||
# However, we should only specify sudo user if explicitly given by the
|
||||
# credentials, otherwise, the playbook will be forced to run using
|
||||
# sudo, which may not always be the desired behavior.
|
||||
# We only specify sudo/su user and password if explicitly given by the
|
||||
# credential. Credential should never specify both sudo and su.
|
||||
if su_username:
|
||||
args.extend(['-R', su_username])
|
||||
if 'su_password' in kwargs.get('passwords', {}):
|
||||
args.append('--ask-su-pass')
|
||||
if sudo_username:
|
||||
args.extend(['-U', sudo_username])
|
||||
if 'sudo_password' in kwargs.get('passwords', {}):
|
||||
@ -591,12 +595,18 @@ class RunJob(BaseTask):
|
||||
|
||||
if job.forks: # FIXME: Max limit?
|
||||
args.append('--forks=%d' % job.forks)
|
||||
if job.force_handlers:
|
||||
args.append('--force-handlers')
|
||||
if job.limit:
|
||||
args.extend(['-l', job.limit])
|
||||
if job.verbosity:
|
||||
args.append('-%s' % ('v' * min(3, job.verbosity)))
|
||||
if job.job_tags:
|
||||
args.extend(['-t', job.job_tags])
|
||||
if job.skip_tags:
|
||||
args.append('--skip-tags=%s' % job.skip_tags)
|
||||
if job.start_at_task:
|
||||
args.append('--start-at-task=%s' % job.start_at_task)
|
||||
|
||||
# Define special extra_vars for Tower, combine with job.extra_vars.
|
||||
extra_vars = {
|
||||
@ -642,6 +652,7 @@ class RunJob(BaseTask):
|
||||
d[re.compile(r'^Enter passphrase for .*:\s*?$', re.M)] = 'ssh_key_unlock'
|
||||
d[re.compile(r'^Bad passphrase, try again for .*:\s*?$', re.M)] = ''
|
||||
d[re.compile(r'^sudo password.*:\s*?$', re.M)] = 'sudo_password'
|
||||
d[re.compile(r'^su password.*:\s*?$', re.M)] = 'su_password'
|
||||
d[re.compile(r'^SSH password:\s*?$', re.M)] = 'ssh_password'
|
||||
d[re.compile(r'^Password:\s*?$', re.M)] = 'ssh_password'
|
||||
d[re.compile(r'^Vault password:\s*?$', re.M)] = 'vault_password'
|
||||
|
||||
@ -622,13 +622,16 @@ class BaseJobTestMixin(BaseTestMixin):
|
||||
|
||||
class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
|
||||
|
||||
JOB_TEMPLATE_FIELDS = ('id', 'type', 'url', 'related', 'summary_fields', 'created',
|
||||
'modified', 'name', 'description', 'job_type',
|
||||
'inventory', 'project', 'playbook', 'credential',
|
||||
'cloud_credential', 'forks', 'limit', 'verbosity',
|
||||
'extra_vars', 'ask_variables_on_launch', 'job_tags',
|
||||
'host_config_key', 'status', 'next_job_run',
|
||||
'has_schedules', 'last_job_run', 'last_job_failed', 'survey_enabled')
|
||||
JOB_TEMPLATE_FIELDS = ('id', 'type', 'url', 'related', 'summary_fields',
|
||||
'created', 'modified', 'name', 'description',
|
||||
'job_type', 'inventory', 'project', 'playbook',
|
||||
'credential', 'use_su_credential', 'sudo_su_flag',
|
||||
'cloud_credential', 'force_handlers', 'forks',
|
||||
'limit', 'verbosity', 'extra_vars',
|
||||
'ask_variables_on_launch', 'job_tags', 'skip_tags',
|
||||
'start_at_task', 'host_config_key', 'status',
|
||||
'next_job_run', 'has_schedules', 'last_job_run',
|
||||
'last_job_failed', 'survey_enabled')
|
||||
|
||||
def test_get_job_template_list(self):
|
||||
url = reverse('api:job_template_list')
|
||||
|
||||
@ -34,7 +34,7 @@ TEST_PLAYBOOK = '''- hosts: mygroup
|
||||
command: test 1 = 1
|
||||
'''
|
||||
|
||||
class ProjectsTest(BaseTest):
|
||||
class ProjectsTest(BaseTransactionTest):
|
||||
|
||||
# tests for users, projects, and teams
|
||||
|
||||
@ -541,6 +541,12 @@ class ProjectsTest(BaseTest):
|
||||
sudo_username=None)
|
||||
self.post(url, data, expect=400)
|
||||
|
||||
# Test trying to pass both sudo_username and su_username.
|
||||
with self.current_user(self.super_django_user):
|
||||
data = dict(name='zyq', user=self.super_django_user.pk, kind='ssh',
|
||||
sudo_username='sudouser', su_username='suuser')
|
||||
self.post(url, data, expect=400)
|
||||
|
||||
# Test with encrypted ssh key and no unlock password.
|
||||
with self.current_user(self.super_django_user):
|
||||
data = dict(name='wxy', user=self.super_django_user.pk, kind='ssh',
|
||||
|
||||
@ -39,6 +39,24 @@ TEST_PLAYBOOK2 = '''- name: test failed
|
||||
command: test 1 = 0
|
||||
'''
|
||||
|
||||
TEST_PLAYBOOK_WITH_TAGS = u'''
|
||||
- name: test with tags
|
||||
hosts: test-group
|
||||
gather_facts: False
|
||||
tasks:
|
||||
- name: should fail but skipped using --start-at-task="start here"
|
||||
command: test 1 = 0
|
||||
tags: runme
|
||||
- name: start here
|
||||
command: test 1 = 1
|
||||
tags: runme
|
||||
- name: should fail but skipped using --skip-tags=skipme
|
||||
command: test 1 = 0
|
||||
tags: skipme
|
||||
- name: should fail but skipped without runme tag
|
||||
command: test 1 = 0
|
||||
'''
|
||||
|
||||
TEST_EXTRA_VARS_PLAYBOOK = '''
|
||||
- name: test extra vars
|
||||
hosts: test-group
|
||||
@ -315,6 +333,8 @@ class RunJobTest(BaseCeleryTest):
|
||||
'password': '',
|
||||
'sudo_username': '',
|
||||
'sudo_password': '',
|
||||
'su_username': '',
|
||||
'su_password': '',
|
||||
'vault_password': '',
|
||||
}
|
||||
opts.update(kwargs)
|
||||
@ -796,7 +816,8 @@ class RunJobTest(BaseCeleryTest):
|
||||
def test_extra_job_options(self):
|
||||
self.create_test_project(TEST_EXTRA_VARS_PLAYBOOK)
|
||||
# Test with extra_vars containing misc whitespace.
|
||||
job_template = self.create_test_job_template(forks=3, verbosity=2,
|
||||
job_template = self.create_test_job_template(force_handlers=True,
|
||||
forks=3, verbosity=2,
|
||||
extra_vars=u'{\n\t"abc": 1234\n}')
|
||||
job = self.create_test_job(job_template=job_template)
|
||||
self.assertEqual(job.status, 'new')
|
||||
@ -804,9 +825,10 @@ class RunJobTest(BaseCeleryTest):
|
||||
self.assertTrue(job.signal_start())
|
||||
job = Job.objects.get(pk=job.pk)
|
||||
self.check_job_result(job, 'successful')
|
||||
self.assertTrue('--forks=3' in job.job_args)
|
||||
self.assertTrue('-vv' in job.job_args)
|
||||
self.assertTrue('-e' in job.job_args)
|
||||
self.assertTrue('"--force-handlers"' in job.job_args)
|
||||
self.assertTrue('"--forks=3"' in job.job_args)
|
||||
self.assertTrue('"-vv"' in job.job_args)
|
||||
self.assertTrue('"-e"' in job.job_args)
|
||||
# Test with extra_vars as key=value (old format).
|
||||
job_template2 = self.create_test_job_template(extra_vars='foo=1')
|
||||
job2 = self.create_test_job(job_template=job_template2)
|
||||
@ -833,7 +855,7 @@ class RunJobTest(BaseCeleryTest):
|
||||
job = Job.objects.get(pk=job.pk)
|
||||
self.assertTrue(len(job.job_args) > 1024)
|
||||
self.check_job_result(job, 'successful')
|
||||
self.assertTrue('-e' in job.job_args)
|
||||
self.assertTrue('"-e"' in job.job_args)
|
||||
|
||||
def test_limit_option(self):
|
||||
self.create_test_project(TEST_PLAYBOOK)
|
||||
@ -844,7 +866,7 @@ class RunJobTest(BaseCeleryTest):
|
||||
self.assertTrue(job.signal_start())
|
||||
job = Job.objects.get(pk=job.pk)
|
||||
self.check_job_result(job, 'failed')
|
||||
self.assertTrue('-l' in job.job_args)
|
||||
self.assertTrue('"-l"' in job.job_args)
|
||||
|
||||
def test_limit_option_with_group_pattern_and_ssh_key(self):
|
||||
self.create_test_credential(ssh_key_data=TEST_SSH_KEY_DATA)
|
||||
@ -856,9 +878,24 @@ class RunJobTest(BaseCeleryTest):
|
||||
self.assertTrue(job.signal_start())
|
||||
job = Job.objects.get(pk=job.pk)
|
||||
self.check_job_result(job, 'successful')
|
||||
self.assertTrue('--private-key=' in job.job_args)
|
||||
self.assertTrue('"--private-key=' in job.job_args)
|
||||
self.assertFalse('ssh-agent' in job.job_args)
|
||||
|
||||
def test_tag_and_task_options(self):
|
||||
self.create_test_project(TEST_PLAYBOOK_WITH_TAGS)
|
||||
job_template = self.create_test_job_template(job_tags='runme',
|
||||
skip_tags='skipme',
|
||||
start_at_task='start here')
|
||||
job = self.create_test_job(job_template=job_template)
|
||||
self.assertEqual(job.status, 'new')
|
||||
self.assertFalse(job.passwords_needed_to_start)
|
||||
self.assertTrue(job.signal_start())
|
||||
job = Job.objects.get(pk=job.pk)
|
||||
self.check_job_result(job, 'successful')
|
||||
self.assertTrue('"-t"' in job.job_args)
|
||||
self.assertTrue('"--skip-tags=' in job.job_args)
|
||||
self.assertTrue('"--start-at-task=' in job.job_args)
|
||||
|
||||
def test_ssh_username_and_password(self):
|
||||
self.create_test_credential(username='sshuser', password='sshpass')
|
||||
self.create_test_project(TEST_PLAYBOOK)
|
||||
@ -869,8 +906,8 @@ class RunJobTest(BaseCeleryTest):
|
||||
self.assertTrue(job.signal_start())
|
||||
job = Job.objects.get(pk=job.pk)
|
||||
self.check_job_result(job, 'successful')
|
||||
self.assertTrue('-u' in job.job_args)
|
||||
self.assertTrue('--ask-pass' in job.job_args)
|
||||
self.assertTrue('"-u"' in job.job_args)
|
||||
self.assertTrue('"--ask-pass"' in job.job_args)
|
||||
|
||||
def test_ssh_ask_password(self):
|
||||
self.create_test_credential(password='ASK')
|
||||
@ -885,7 +922,7 @@ class RunJobTest(BaseCeleryTest):
|
||||
self.assertTrue(job.signal_start(ssh_password='sshpass'))
|
||||
job = Job.objects.get(pk=job.pk)
|
||||
self.check_job_result(job, 'successful')
|
||||
self.assertTrue('--ask-pass' in job.job_args)
|
||||
self.assertTrue('"--ask-pass"' in job.job_args)
|
||||
|
||||
def test_sudo_username_and_password(self):
|
||||
self.create_test_credential(sudo_username='sudouser',
|
||||
@ -900,8 +937,12 @@ class RunJobTest(BaseCeleryTest):
|
||||
# Job may fail if current user doesn't have password-less sudo
|
||||
# privileges, but we're mainly checking the command line arguments.
|
||||
self.check_job_result(job, ('successful', 'failed'))
|
||||
self.assertTrue('-U' in job.job_args)
|
||||
self.assertTrue('--ask-sudo-pass' in job.job_args)
|
||||
self.assertTrue('"-U"' in job.job_args)
|
||||
self.assertTrue('"--ask-sudo-pass"' in job.job_args)
|
||||
self.assertFalse('"-s"' in job.job_args)
|
||||
self.assertFalse('"-R"' in job.job_args)
|
||||
self.assertFalse('"--ask-su-pass"' in job.job_args)
|
||||
self.assertFalse('"-S"' in job.job_args)
|
||||
|
||||
def test_sudo_ask_password(self):
|
||||
self.create_test_credential(sudo_password='ASK')
|
||||
@ -911,13 +952,58 @@ class RunJobTest(BaseCeleryTest):
|
||||
self.assertEqual(job.status, 'new')
|
||||
self.assertTrue(job.passwords_needed_to_start)
|
||||
self.assertTrue('sudo_password' in job.passwords_needed_to_start)
|
||||
self.assertFalse('su_password' in job.passwords_needed_to_start)
|
||||
self.assertFalse(job.signal_start())
|
||||
self.assertTrue(job.signal_start(sudo_password='sudopass'))
|
||||
job = Job.objects.get(pk=job.pk)
|
||||
# Job may fail if current user doesn't have password-less sudo
|
||||
# privileges, but we're mainly checking the command line arguments.
|
||||
self.assertTrue(job.status in ('successful', 'failed'))
|
||||
self.assertTrue('--ask-sudo-pass' in job.job_args)
|
||||
self.assertTrue('"--ask-sudo-pass"' in job.job_args)
|
||||
self.assertFalse('"-s"' in job.job_args)
|
||||
self.assertFalse('"-R"' in job.job_args)
|
||||
self.assertFalse('"--ask-su-pass"' in job.job_args)
|
||||
self.assertFalse('"-S"' in job.job_args)
|
||||
|
||||
def test_su_username_and_password(self):
|
||||
self.create_test_credential(su_username='suuser',
|
||||
su_password='supass')
|
||||
self.create_test_project(TEST_PLAYBOOK)
|
||||
job_template = self.create_test_job_template()
|
||||
job = self.create_test_job(job_template=job_template)
|
||||
self.assertEqual(job.status, 'new')
|
||||
self.assertFalse(job.passwords_needed_to_start)
|
||||
self.assertTrue(job.signal_start())
|
||||
job = Job.objects.get(pk=job.pk)
|
||||
# Job may fail, but we're mainly checking the command line arguments.
|
||||
self.check_job_result(job, ('successful', 'failed'))
|
||||
self.assertTrue('"-R"' in job.job_args)
|
||||
self.assertTrue('"--ask-su-pass"' in job.job_args)
|
||||
self.assertFalse('"-S"' in job.job_args)
|
||||
self.assertFalse('"-U"' in job.job_args)
|
||||
self.assertFalse('"--ask-sudo-pass"' in job.job_args)
|
||||
self.assertFalse('"-s"' in job.job_args)
|
||||
|
||||
def test_su_ask_password(self):
|
||||
self.create_test_credential(su_password='ASK')
|
||||
self.create_test_project(TEST_PLAYBOOK)
|
||||
job_template = self.create_test_job_template()
|
||||
job = self.create_test_job(job_template=job_template)
|
||||
self.assertEqual(job.status, 'new')
|
||||
self.assertTrue(job.passwords_needed_to_start)
|
||||
self.assertTrue('su_password' in job.passwords_needed_to_start)
|
||||
self.assertFalse('sudo_password' in job.passwords_needed_to_start)
|
||||
self.assertFalse(job.signal_start())
|
||||
self.assertTrue(job.signal_start(su_password='supass'))
|
||||
job = Job.objects.get(pk=job.pk)
|
||||
# Job may fail, but we're mainly checking the command line arguments.
|
||||
self.assertTrue(job.status in ('successful', 'failed'))
|
||||
self.assertTrue('"--ask-su-pass"' in job.job_args)
|
||||
self.assertFalse('"-S"' in job.job_args)
|
||||
self.assertFalse('"-R"' in job.job_args)
|
||||
self.assertFalse('"-U"' in job.job_args)
|
||||
self.assertFalse('"--ask-sudo-pass"' in job.job_args)
|
||||
self.assertFalse('"-s"' in job.job_args)
|
||||
|
||||
def test_unlocked_ssh_key(self):
|
||||
self.create_test_credential(ssh_key_data=TEST_SSH_KEY_DATA)
|
||||
@ -929,7 +1015,7 @@ class RunJobTest(BaseCeleryTest):
|
||||
self.assertTrue(job.signal_start())
|
||||
job = Job.objects.get(pk=job.pk)
|
||||
self.check_job_result(job, 'successful')
|
||||
self.assertTrue('--private-key=' in job.job_args)
|
||||
self.assertTrue('"--private-key=' in job.job_args)
|
||||
self.assertFalse('ssh-agent' in job.job_args)
|
||||
|
||||
def test_locked_ssh_key_with_password(self):
|
||||
@ -991,10 +1077,10 @@ class RunJobTest(BaseCeleryTest):
|
||||
job = Job.objects.get(pk=job.pk)
|
||||
if Version(self.ansible_version) >= Version('1.5'):
|
||||
self.check_job_result(job, 'successful')
|
||||
self.assertTrue('--ask-vault-pass' in job.job_args)
|
||||
self.assertTrue('"--ask-vault-pass"' in job.job_args)
|
||||
else:
|
||||
self.check_job_result(job, 'failed')
|
||||
self.assertFalse('--ask-vault-pass' in job.job_args)
|
||||
self.assertFalse('"--ask-vault-pass"' in job.job_args)
|
||||
|
||||
def test_vault_ask_password(self):
|
||||
self.create_test_credential(vault_password='ASK')
|
||||
@ -1010,10 +1096,10 @@ class RunJobTest(BaseCeleryTest):
|
||||
job = Job.objects.get(pk=job.pk)
|
||||
if Version(self.ansible_version) >= Version('1.5'):
|
||||
self.check_job_result(job, 'successful')
|
||||
self.assertTrue('--ask-vault-pass' in job.job_args)
|
||||
self.assertTrue('"--ask-vault-pass"' in job.job_args)
|
||||
else:
|
||||
self.check_job_result(job, 'failed')
|
||||
self.assertFalse('--ask-vault-pass' in job.job_args)
|
||||
self.assertFalse('"--ask-vault-pass"' in job.job_args)
|
||||
|
||||
def test_vault_bad_password(self):
|
||||
self.create_test_credential(vault_password='not it')
|
||||
@ -1026,9 +1112,9 @@ class RunJobTest(BaseCeleryTest):
|
||||
job = Job.objects.get(pk=job.pk)
|
||||
self.check_job_result(job, 'failed')
|
||||
if Version(self.ansible_version) >= Version('1.5'):
|
||||
self.assertTrue('--ask-vault-pass' in job.job_args)
|
||||
self.assertTrue('"--ask-vault-pass"' in job.job_args)
|
||||
else:
|
||||
self.assertFalse('--ask-vault-pass' in job.job_args)
|
||||
self.assertFalse('"--ask-vault-pass"' in job.job_args)
|
||||
|
||||
def _test_cloud_credential_environment_variables(self, kind):
|
||||
if kind == 'aws':
|
||||
|
||||
@ -136,7 +136,7 @@ CredentialsList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeP
|
||||
|
||||
function CredentialsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, CredentialForm, GenerateForm, Rest, Alert,
|
||||
ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GenerateList, SearchInit, PaginateInit, LookUpInit, UserList, TeamList,
|
||||
GetBasePath, GetChoices, Empty, KindChange, OwnerChange, FormSave) {
|
||||
GetBasePath, GetChoices, Empty, KindChange, OwnerChange, LoginMethodChange, FormSave) {
|
||||
|
||||
ClearScope();
|
||||
|
||||
@ -209,6 +209,17 @@ function CredentialsAdd($scope, $rootScope, $compile, $location, $log, $routePar
|
||||
OwnerChange({ scope: $scope });
|
||||
}
|
||||
|
||||
if (!Empty($routeParams.su_username) || !Empty($routeParams.su_password)) {
|
||||
$scope.login_method = 'su';
|
||||
LoginMethodChange({ scope: $scope });
|
||||
} else if (!Empty($routeParams.sudo_username) || !Empty($routeParams.sudo_password)) {
|
||||
$scope.login_method = 'sudo';
|
||||
LoginMethodChange({ scope: $scope });
|
||||
} else {
|
||||
$scope.login_method = '';
|
||||
LoginMethodChange({ scope: $scope });
|
||||
}
|
||||
|
||||
// Handle Kind change
|
||||
$scope.kindChange = function () {
|
||||
KindChange({ scope: $scope, form: form, reset: true });
|
||||
@ -228,6 +239,11 @@ function CredentialsAdd($scope, $rootScope, $compile, $location, $log, $routePar
|
||||
OwnerChange({ scope: $scope });
|
||||
};
|
||||
|
||||
// Handle Login Method change
|
||||
$scope.loginMethodChange = function () {
|
||||
LoginMethodChange({ scope: $scope });
|
||||
};
|
||||
|
||||
// Reset defaults
|
||||
$scope.formReset = function () {
|
||||
//DebugForm({ scope: $scope, form: CredentialForm });
|
||||
@ -266,13 +282,13 @@ function CredentialsAdd($scope, $rootScope, $compile, $location, $log, $routePar
|
||||
|
||||
CredentialsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'CredentialForm', 'GenerateForm',
|
||||
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList', 'SearchInit', 'PaginateInit',
|
||||
'LookUpInit', 'UserList', 'TeamList', 'GetBasePath', 'GetChoices', 'Empty', 'KindChange', 'OwnerChange', 'FormSave'
|
||||
'LookUpInit', 'UserList', 'TeamList', 'GetBasePath', 'GetChoices', 'Empty', 'KindChange', 'OwnerChange', 'LoginMethodChange', 'FormSave'
|
||||
];
|
||||
|
||||
|
||||
function CredentialsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, CredentialForm, GenerateForm, Rest, Alert,
|
||||
ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, Prompt, GetBasePath, GetChoices,
|
||||
KindChange, UserList, TeamList, LookUpInit, Empty, OwnerChange, FormSave, Stream, Wait) {
|
||||
KindChange, UserList, TeamList, LookUpInit, Empty, OwnerChange, LoginMethodChange, FormSave, Stream, Wait) {
|
||||
|
||||
ClearScope();
|
||||
|
||||
@ -338,6 +354,7 @@ function CredentialsEdit($scope, $rootScope, $compile, $location, $log, $routePa
|
||||
reset: false
|
||||
});
|
||||
OwnerChange({ scope: $scope });
|
||||
LoginMethodChange({ scope: $scope });
|
||||
Wait('stop');
|
||||
});
|
||||
|
||||
@ -377,6 +394,15 @@ function CredentialsEdit($scope, $rootScope, $compile, $location, $log, $routePa
|
||||
}
|
||||
master.owner = $scope.owner;
|
||||
|
||||
if (!Empty($scope.su_username) || !Empty($scope.su_password)) {
|
||||
$scope.login_method = 'su';
|
||||
} else if (!Empty($scope.sudo_username) || !Empty($scope.sudo_password)) {
|
||||
$scope.login_method = 'sudo';
|
||||
} else {
|
||||
$scope.login_method = '';
|
||||
}
|
||||
master.login_method = $scope.login_method;
|
||||
|
||||
for (i = 0; i < $scope.credential_kind_options.length; i++) {
|
||||
if ($scope.credential_kind_options[i].value === data.kind) {
|
||||
$scope.kind = $scope.credential_kind_options[i];
|
||||
@ -445,6 +471,11 @@ function CredentialsEdit($scope, $rootScope, $compile, $location, $log, $routePa
|
||||
OwnerChange({ scope: $scope });
|
||||
};
|
||||
|
||||
// Handle Login Method change
|
||||
$scope.loginMethodChange = function () {
|
||||
LoginMethodChange({ scope: $scope });
|
||||
};
|
||||
|
||||
// Handle Kind change
|
||||
$scope.kindChange = function () {
|
||||
KindChange({ scope: $scope, form: form, reset: true });
|
||||
@ -459,6 +490,7 @@ function CredentialsEdit($scope, $rootScope, $compile, $location, $log, $routePa
|
||||
setAskCheckboxes();
|
||||
KindChange({ scope: $scope, form: form, reset: false });
|
||||
OwnerChange({ scope: $scope });
|
||||
LoginMethodChange({ scope: $scope });
|
||||
};
|
||||
|
||||
// Related set: Add button
|
||||
@ -538,5 +570,5 @@ function CredentialsEdit($scope, $rootScope, $compile, $location, $log, $routePa
|
||||
CredentialsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'CredentialForm',
|
||||
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', 'RelatedPaginateInit',
|
||||
'ReturnToCaller', 'ClearScope', 'Prompt', 'GetBasePath', 'GetChoices', 'KindChange', 'UserList', 'TeamList', 'LookUpInit',
|
||||
'Empty', 'OwnerChange', 'FormSave', 'Stream', 'Wait'
|
||||
'Empty', 'OwnerChange', 'LoginMethodChange', 'FormSave', 'Stream', 'Wait'
|
||||
];
|
||||
@ -309,10 +309,29 @@ angular.module('CredentialFormDefinition', [])
|
||||
awPassMatch: true,
|
||||
associated: 'ssh_key_unlock'
|
||||
},
|
||||
"login_method": {
|
||||
label: "Login Method", // FIXME: Confirm this label is ok?
|
||||
type: 'radio_group',
|
||||
ngChange: "loginMethodChange()",
|
||||
options: [{
|
||||
label: 'None', // FIXME: Maybe 'Default' or 'SSH only' instead?
|
||||
value: '',
|
||||
selected: true
|
||||
}, {
|
||||
label: 'Sudo',
|
||||
value: 'sudo'
|
||||
}, {
|
||||
label: 'Su',
|
||||
value: 'su'
|
||||
}],
|
||||
awPopOver: "<p>A credential may optionally provide a sudo username and password or su username and password to use when running a playbook.</p>",
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
"sudo_username": {
|
||||
label: 'Sudo Username',
|
||||
type: 'text',
|
||||
ngShow: "kind.value == 'ssh'",
|
||||
ngShow: "kind.value == 'ssh' && login_method == 'sudo'",
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
autocomplete: false
|
||||
@ -320,7 +339,7 @@ angular.module('CredentialFormDefinition', [])
|
||||
"sudo_password": {
|
||||
label: 'Sudo Password',
|
||||
type: 'password',
|
||||
ngShow: "kind.value == 'ssh'",
|
||||
ngShow: "kind.value == 'ssh' && login_method == 'sudo'",
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
ngChange: "clearPWConfirm('sudo_password_confirm')",
|
||||
@ -332,13 +351,43 @@ angular.module('CredentialFormDefinition', [])
|
||||
"sudo_password_confirm": {
|
||||
label: 'Confirm Sudo Password',
|
||||
type: 'password',
|
||||
ngShow: "kind.value == 'ssh'",
|
||||
ngShow: "kind.value == 'ssh' && login_method == 'sudo'",
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPassMatch: true,
|
||||
associated: 'sudo_password',
|
||||
autocomplete: false
|
||||
},
|
||||
"su_username": {
|
||||
label: 'Su Username',
|
||||
type: 'text',
|
||||
ngShow: "kind.value == 'ssh' && login_method == 'su'",
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
autocomplete: false
|
||||
},
|
||||
"su_password": {
|
||||
label: 'Su Password',
|
||||
type: 'password',
|
||||
ngShow: "kind.value == 'ssh' && login_method == 'su'",
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
ngChange: "clearPWConfirm('su_password_confirm')",
|
||||
ask: true,
|
||||
clear: true,
|
||||
associated: 'su_password_confirm',
|
||||
autocomplete: false
|
||||
},
|
||||
"su_password_confirm": {
|
||||
label: 'Confirm Su Password',
|
||||
type: 'password',
|
||||
ngShow: "kind.value == 'ssh' && login_method == 'su'",
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPassMatch: true,
|
||||
associated: 'su_password',
|
||||
autocomplete: false
|
||||
},
|
||||
"project": {
|
||||
label: "Project",
|
||||
type: 'text',
|
||||
|
||||
@ -102,6 +102,9 @@ angular.module('CredentialsHelper', ['Utilities'])
|
||||
scope.sudo_username = null;
|
||||
scope.sudo_password = null;
|
||||
scope.sudo_password_confirm = null;
|
||||
scope.su_username = null;
|
||||
scope.su_password = null;
|
||||
scope.su_password_confirm = null;
|
||||
}
|
||||
|
||||
// Collapse or open help widget based on whether scm value is selected
|
||||
@ -143,6 +146,24 @@ angular.module('CredentialsHelper', ['Utilities'])
|
||||
])
|
||||
|
||||
|
||||
.factory('LoginMethodChange', [
|
||||
function () {
|
||||
return function (params) {
|
||||
var scope = params.scope,
|
||||
login_method = scope.login_method;
|
||||
if (login_method !== 'sudo') {
|
||||
scope.sudo_username = null;
|
||||
scope.sudo_password = null;
|
||||
}
|
||||
if (login_method !== 'su') {
|
||||
scope.su_username = null;
|
||||
scope.su_password = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
.factory('FormSave', ['$location', 'Alert', 'Rest', 'ProcessErrors', 'Empty', 'GetBasePath', 'CredentialForm', 'ReturnToCaller', 'Wait',
|
||||
function ($location, Alert, Rest, ProcessErrors, Empty, GetBasePath, CredentialForm, ReturnToCaller, Wait) {
|
||||
return function (params) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user