mirror of
https://github.com/ansible/awx.git
synced 2026-05-16 13:57:39 -02:30
Merge pull request #451 from matburt/iam_ephemeral_cred
Support IAM ephemeral cred
This commit is contained in:
@@ -1349,6 +1349,7 @@ class CredentialSerializer(BaseSerializer):
|
|||||||
# FIXME: may want to make some of these filtered based on user accessing
|
# FIXME: may want to make some of these filtered based on user accessing
|
||||||
|
|
||||||
password = serializers.CharField(required=False, default='')
|
password = serializers.CharField(required=False, default='')
|
||||||
|
security_token = serializers.CharField(required=False, default='')
|
||||||
ssh_key_data = serializers.CharField(required=False, default='')
|
ssh_key_data = serializers.CharField(required=False, default='')
|
||||||
ssh_key_unlock = serializers.CharField(required=False, default='')
|
ssh_key_unlock = serializers.CharField(required=False, default='')
|
||||||
become_password = serializers.CharField(required=False, default='')
|
become_password = serializers.CharField(required=False, default='')
|
||||||
@@ -1357,7 +1358,7 @@ class CredentialSerializer(BaseSerializer):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = Credential
|
model = Credential
|
||||||
fields = ('*', 'user', 'team', 'kind', 'cloud', 'host', 'username',
|
fields = ('*', 'user', 'team', 'kind', 'cloud', 'host', 'username',
|
||||||
'password', 'project', 'ssh_key_data', 'ssh_key_unlock',
|
'password', 'security_token', 'project', 'ssh_key_data', 'ssh_key_unlock',
|
||||||
'become_method', 'become_username', 'become_password',
|
'become_method', 'become_username', 'become_password',
|
||||||
'vault_password')
|
'vault_password')
|
||||||
|
|
||||||
|
|||||||
523
awx/main/migrations/0073_v240_changes.py
Normal file
523
awx/main/migrations/0073_v240_changes.py
Normal file
@@ -0,0 +1,523 @@
|
|||||||
|
# -*- 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 'Credential.security_token'
|
||||||
|
db.add_column(u'main_credential', 'security_token',
|
||||||
|
self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True),
|
||||||
|
keep_default=False)
|
||||||
|
|
||||||
|
|
||||||
|
def backwards(self, orm):
|
||||||
|
# Deleting field 'Credential.security_token'
|
||||||
|
db.delete_column(u'main_credential', 'security_token')
|
||||||
|
|
||||||
|
|
||||||
|
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']"}),
|
||||||
|
'ad_hoc_command': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.AdHocCommand']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'changes': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||||
|
'credential': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Credential']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'custom_inventory_script': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.CustomInventoryScript']", '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.adhoccommand': {
|
||||||
|
'Meta': {'object_name': 'AdHocCommand', '_ormbases': ['main.UnifiedJob']},
|
||||||
|
'become_enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'ad_hoc_commands'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Credential']"}),
|
||||||
|
'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}),
|
||||||
|
'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'ad_hoc_commands'", 'symmetrical': 'False', 'through': "orm['main.AdHocCommandEvent']", 'to': "orm['main.Host']"}),
|
||||||
|
'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ad_hoc_commands'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}),
|
||||||
|
'job_type': ('django.db.models.fields.CharField', [], {'default': "'run'", 'max_length': '64'}),
|
||||||
|
'limit': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'module_args': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||||
|
'module_name': ('django.db.models.fields.CharField', [], {'default': "'command'", '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.adhoccommandevent': {
|
||||||
|
'Meta': {'ordering': "('-pk',)", 'unique_together': "[('ad_hoc_command', 'host_name')]", 'object_name': 'AdHocCommandEvent'},
|
||||||
|
'ad_hoc_command': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ad_hoc_command_events'", 'to': "orm['main.AdHocCommand']"}),
|
||||||
|
'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': "'ad_hoc_command_events'", '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'}),
|
||||||
|
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'})
|
||||||
|
},
|
||||||
|
'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'}),
|
||||||
|
'reason': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', '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'}),
|
||||||
|
'become_method': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}),
|
||||||
|
'become_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'become_username': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': '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'}),
|
||||||
|
'security_token': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', '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'}),
|
||||||
|
'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.custominventoryscript': {
|
||||||
|
'Meta': {'ordering': "('name',)", 'unique_together': "[('name', 'organization')]", 'object_name': 'CustomInventoryScript'},
|
||||||
|
'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\': \'custominventoryscript\', \'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\': \'custominventoryscript\', \'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': "'custom_inventory_scripts'", 'to': "orm['main.Organization']"}),
|
||||||
|
'script': ('django.db.models.fields.TextField', [], {'default': "''", '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.instance': {
|
||||||
|
'Meta': {'object_name': 'Instance'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '250'}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||||
|
'primary': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'})
|
||||||
|
},
|
||||||
|
'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']"}),
|
||||||
|
'group_by': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'instance_filters': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'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_script': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['main.CustomInventoryScript']", 'null': 'True', 'on_delete': 'models.SET_NULL', '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'}),
|
||||||
|
'group_by': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'instance_filters': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': '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_script': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['main.CustomInventoryScript']", 'null': 'True', 'on_delete': 'models.SET_NULL', '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']},
|
||||||
|
'become_enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'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', [], {'default': "'run'", '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', 'blank': 'True'}),
|
||||||
|
'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Project']", 'blank': 'True', 'null': 'True'}),
|
||||||
|
'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.joborigin': {
|
||||||
|
'Meta': {'object_name': 'JobOrigin'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'instance': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Instance']"}),
|
||||||
|
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||||
|
'unified_job': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'job_origin'", 'unique': 'True', 'to': "orm['main.UnifiedJob']"})
|
||||||
|
},
|
||||||
|
'main.jobtemplate': {
|
||||||
|
'Meta': {'ordering': "('name',)", 'object_name': 'JobTemplate', '_ormbases': ['main.UnifiedJobTemplate']},
|
||||||
|
'ask_variables_on_launch': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'become_enabled': ('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', [], {'default': "'run'", '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', 'blank': 'True'}),
|
||||||
|
'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Project']", 'blank': 'True', 'null': 'True'}),
|
||||||
|
'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']"}),
|
||||||
|
'run_ad_hoc_commands': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'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', 'blank': 'True'}),
|
||||||
|
'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'}),
|
||||||
|
'extra_data': ('jsonfield.fields.JSONField', [], {'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\': \'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.systemjob': {
|
||||||
|
'Meta': {'ordering': "('id',)", 'object_name': 'SystemJob', '_ormbases': ['main.UnifiedJob']},
|
||||||
|
'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||||
|
'job_type': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}),
|
||||||
|
'system_job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.SystemJobTemplate']", 'blank': 'True', 'null': 'True'}),
|
||||||
|
u'unifiedjob_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJob']", 'unique': 'True', 'primary_key': 'True'})
|
||||||
|
},
|
||||||
|
'main.systemjobtemplate': {
|
||||||
|
'Meta': {'object_name': 'SystemJobTemplate', '_ormbases': ['main.UnifiedJobTemplate']},
|
||||||
|
'job_type': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}),
|
||||||
|
u'unifiedjobtemplate_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJobTemplate']", 'unique': 'True', 'primary_key': 'True'})
|
||||||
|
},
|
||||||
|
'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']
|
||||||
@@ -46,7 +46,7 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique):
|
|||||||
#('runas', _('Runas')),
|
#('runas', _('Runas')),
|
||||||
]
|
]
|
||||||
|
|
||||||
PASSWORD_FIELDS = ('password', 'ssh_key_data', 'ssh_key_unlock',
|
PASSWORD_FIELDS = ('password', 'security_token', 'ssh_key_data', 'ssh_key_unlock',
|
||||||
'become_password', 'vault_password')
|
'become_password', 'vault_password')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@@ -101,6 +101,13 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique):
|
|||||||
help_text=_('Password for this credential (or "ASK" to prompt the '
|
help_text=_('Password for this credential (or "ASK" to prompt the '
|
||||||
'user for machine credentials).'),
|
'user for machine credentials).'),
|
||||||
)
|
)
|
||||||
|
security_token = models.CharField(
|
||||||
|
blank=True,
|
||||||
|
default='',
|
||||||
|
max_length=1024,
|
||||||
|
verbose_name=_('Security Token'),
|
||||||
|
help_text=_('Security Token for this credential'),
|
||||||
|
)
|
||||||
project = models.CharField(
|
project = models.CharField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default='',
|
default='',
|
||||||
|
|||||||
@@ -665,6 +665,8 @@ class RunJob(BaseTask):
|
|||||||
if cloud_cred and cloud_cred.kind == 'aws':
|
if cloud_cred and cloud_cred.kind == 'aws':
|
||||||
env['AWS_ACCESS_KEY'] = cloud_cred.username
|
env['AWS_ACCESS_KEY'] = cloud_cred.username
|
||||||
env['AWS_SECRET_KEY'] = decrypt_field(cloud_cred, 'password')
|
env['AWS_SECRET_KEY'] = decrypt_field(cloud_cred, 'password')
|
||||||
|
if len(cloud_cred.security_token) > 0:
|
||||||
|
env['AWS_SECURITY_TOKEN'] = decrypt_field(cloud_cred, 'security_token')
|
||||||
# FIXME: Add EC2_URL, maybe EC2_REGION!
|
# FIXME: Add EC2_URL, maybe EC2_REGION!
|
||||||
elif cloud_cred and cloud_cred.kind == 'rax':
|
elif cloud_cred and cloud_cred.kind == 'rax':
|
||||||
env['RAX_USERNAME'] = cloud_cred.username
|
env['RAX_USERNAME'] = cloud_cred.username
|
||||||
@@ -1127,7 +1129,7 @@ class RunInventoryUpdate(BaseTask):
|
|||||||
if credential:
|
if credential:
|
||||||
for subkey in ('username', 'host', 'project'):
|
for subkey in ('username', 'host', 'project'):
|
||||||
passwords['source_%s' % subkey] = getattr(credential, subkey)
|
passwords['source_%s' % subkey] = getattr(credential, subkey)
|
||||||
for passkey in ('password', 'ssh_key_data'):
|
for passkey in ('password', 'ssh_key_data', 'security_token'):
|
||||||
k = 'source_%s' % passkey
|
k = 'source_%s' % passkey
|
||||||
passwords[k] = decrypt_field(credential, passkey)
|
passwords[k] = decrypt_field(credential, passkey)
|
||||||
return passwords
|
return passwords
|
||||||
@@ -1160,6 +1162,8 @@ class RunInventoryUpdate(BaseTask):
|
|||||||
if passwords.get('source_username', '') and passwords.get('source_password', ''):
|
if passwords.get('source_username', '') and passwords.get('source_password', ''):
|
||||||
env['AWS_ACCESS_KEY_ID'] = passwords['source_username']
|
env['AWS_ACCESS_KEY_ID'] = passwords['source_username']
|
||||||
env['AWS_SECRET_ACCESS_KEY'] = passwords['source_password']
|
env['AWS_SECRET_ACCESS_KEY'] = passwords['source_password']
|
||||||
|
if len(passwords['source_security_token']) > 0:
|
||||||
|
env['AWS_SECURITY_TOKEN'] = passwords['source_security_token']
|
||||||
env['EC2_INI_PATH'] = cloud_credential
|
env['EC2_INI_PATH'] = cloud_credential
|
||||||
elif inventory_update.source == 'rax':
|
elif inventory_update.source == 'rax':
|
||||||
env['RAX_CREDS_FILE'] = cloud_credential
|
env['RAX_CREDS_FILE'] = cloud_credential
|
||||||
@@ -1199,7 +1203,7 @@ class RunInventoryUpdate(BaseTask):
|
|||||||
inventory = inventory_source.group.inventory
|
inventory = inventory_source.group.inventory
|
||||||
|
|
||||||
# Piece together the initial command to run via. the shell.
|
# Piece together the initial command to run via. the shell.
|
||||||
args = ['awx-manage', 'inventory_import']
|
args = ['tower-manage', 'inventory_import']
|
||||||
args.extend(['--inventory-id', str(inventory.pk)])
|
args.extend(['--inventory-id', str(inventory.pk)])
|
||||||
|
|
||||||
# Add appropriate arguments for overwrite if the inventory_update
|
# Add appropriate arguments for overwrite if the inventory_update
|
||||||
@@ -1461,7 +1465,7 @@ class RunSystemJob(BaseTask):
|
|||||||
model = SystemJob
|
model = SystemJob
|
||||||
|
|
||||||
def build_args(self, system_job, **kwargs):
|
def build_args(self, system_job, **kwargs):
|
||||||
args = ['awx-manage', system_job.job_type]
|
args = ['tower-manage', system_job.job_type]
|
||||||
try:
|
try:
|
||||||
json_vars = json.loads(system_job.extra_vars)
|
json_vars = json.loads(system_job.extra_vars)
|
||||||
if 'days' in json_vars and system_job.job_type != 'cleanup_facts':
|
if 'days' in json_vars and system_job.job_type != 'cleanup_facts':
|
||||||
|
|||||||
@@ -1665,6 +1665,54 @@ class InventoryUpdatesTest(BaseTransactionTest):
|
|||||||
inventory_source.save()
|
inventory_source.save()
|
||||||
self.check_inventory_source(inventory_source, initial=False)
|
self.check_inventory_source(inventory_source, initial=False)
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_from_ec2_sts_iam(self):
|
||||||
|
source_username = getattr(settings, 'TEST_AWS_ACCESS_KEY_ID', '')
|
||||||
|
source_password = getattr(settings, 'TEST_AWS_SECRET_ACCESS_KEY', '')
|
||||||
|
source_regions = getattr(settings, 'TEST_AWS_REGIONS', 'all')
|
||||||
|
source_token = getattr(settings, 'TEST_AWS_SECURITY_TOKEN', '')
|
||||||
|
if not all([source_username, source_password, source_token]):
|
||||||
|
self.skipTest('no test ec2 sts credentials defined!')
|
||||||
|
self.create_test_license_file()
|
||||||
|
credential = Credential.objects.create(kind='aws',
|
||||||
|
user=self.super_django_user,
|
||||||
|
username=source_username,
|
||||||
|
password=source_password,
|
||||||
|
security_token=source_token)
|
||||||
|
# Set parent group name to one that might be created by the sync.
|
||||||
|
group = self.group
|
||||||
|
group.name = 'ec2'
|
||||||
|
group.save()
|
||||||
|
self.group = group
|
||||||
|
cache_path = tempfile.mkdtemp(prefix='awx_ec2_')
|
||||||
|
self._temp_paths.append(cache_path)
|
||||||
|
inventory_source = self.update_inventory_source(self.group,
|
||||||
|
source='ec2', credential=credential, source_regions=source_regions,
|
||||||
|
source_vars='---\n\nnested_groups: false\ncache_path: %s\n' % cache_path)
|
||||||
|
self.check_inventory_source(inventory_source)
|
||||||
|
|
||||||
|
def test_update_from_ec2_sts_iam_bad_token(self):
|
||||||
|
source_username = getattr(settings, 'TEST_AWS_ACCESS_KEY_ID', '')
|
||||||
|
source_password = getattr(settings, 'TEST_AWS_SECRET_ACCESS_KEY', '')
|
||||||
|
source_regions = getattr(settings, 'TEST_AWS_REGIONS', 'all')
|
||||||
|
self.create_test_license_file()
|
||||||
|
credential = Credential.objects.create(kind='aws',
|
||||||
|
user=self.super_django_user,
|
||||||
|
username=source_username,
|
||||||
|
password=source_password,
|
||||||
|
security_token="BADTOKEN")
|
||||||
|
# Set parent group name to one that might be created by the sync.
|
||||||
|
group = self.group
|
||||||
|
group.name = 'ec2'
|
||||||
|
group.save()
|
||||||
|
self.group = group
|
||||||
|
cache_path = tempfile.mkdtemp(prefix='awx_ec2_')
|
||||||
|
self._temp_paths.append(cache_path)
|
||||||
|
inventory_source = self.update_inventory_source(self.group,
|
||||||
|
source='ec2', credential=credential, source_regions=source_regions,
|
||||||
|
source_vars='---\n\nnested_groups: false\ncache_path: %s\n' % cache_path)
|
||||||
|
self.check_inventory_update(inventory_source, should_fail=True)
|
||||||
|
|
||||||
def test_update_from_ec2_without_credential(self):
|
def test_update_from_ec2_without_credential(self):
|
||||||
self.create_test_license_file()
|
self.create_test_license_file()
|
||||||
group = self.group
|
group = self.group
|
||||||
|
|||||||
@@ -22,6 +22,12 @@ you need to define:
|
|||||||
|
|
||||||
export EC2_URL=http://hostname_of_your_cc:port/services/Eucalyptus
|
export EC2_URL=http://hostname_of_your_cc:port/services/Eucalyptus
|
||||||
|
|
||||||
|
If you're using boto profiles (requires boto>=2.24.0) you can choose a profile
|
||||||
|
using the --boto-profile command line argument (e.g. ec2.py --boto-profile prod) or using
|
||||||
|
the AWS_PROFILE variable:
|
||||||
|
|
||||||
|
AWS_PROFILE=prod ansible-playbook -i ec2.py myplaybook.yml
|
||||||
|
|
||||||
For more details, see: http://docs.pythonboto.org/en/latest/boto_config_tut.html
|
For more details, see: http://docs.pythonboto.org/en/latest/boto_config_tut.html
|
||||||
|
|
||||||
When run against a specific host, this script returns the following variables:
|
When run against a specific host, this script returns the following variables:
|
||||||
@@ -121,6 +127,7 @@ from time import time
|
|||||||
import boto
|
import boto
|
||||||
from boto import ec2
|
from boto import ec2
|
||||||
from boto import rds
|
from boto import rds
|
||||||
|
from boto import elasticache
|
||||||
from boto import route53
|
from boto import route53
|
||||||
import six
|
import six
|
||||||
|
|
||||||
@@ -147,9 +154,18 @@ class Ec2Inventory(object):
|
|||||||
# Index of hostname (address) to instance ID
|
# Index of hostname (address) to instance ID
|
||||||
self.index = {}
|
self.index = {}
|
||||||
|
|
||||||
|
# Boto profile to use (if any)
|
||||||
|
self.boto_profile = None
|
||||||
|
|
||||||
# Read settings and parse CLI arguments
|
# Read settings and parse CLI arguments
|
||||||
self.read_settings()
|
|
||||||
self.parse_cli_args()
|
self.parse_cli_args()
|
||||||
|
self.read_settings()
|
||||||
|
|
||||||
|
# Make sure that profile_name is not passed at all if not set
|
||||||
|
# as pre 2.24 boto will fall over otherwise
|
||||||
|
if self.boto_profile:
|
||||||
|
if not hasattr(boto.ec2.EC2Connection, 'profile_name'):
|
||||||
|
self.fail_with_error("boto version must be >= 2.24 to use profile")
|
||||||
|
|
||||||
# Cache
|
# Cache
|
||||||
if self.args.refresh_cache:
|
if self.args.refresh_cache:
|
||||||
@@ -186,12 +202,12 @@ class Ec2Inventory(object):
|
|||||||
|
|
||||||
def read_settings(self):
|
def read_settings(self):
|
||||||
''' Reads the settings from the ec2.ini file '''
|
''' Reads the settings from the ec2.ini file '''
|
||||||
if six.PY2:
|
if six.PY3:
|
||||||
config = configparser.SafeConfigParser()
|
|
||||||
else:
|
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
|
else:
|
||||||
|
config = configparser.SafeConfigParser()
|
||||||
ec2_default_ini_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'ec2.ini')
|
ec2_default_ini_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'ec2.ini')
|
||||||
ec2_ini_path = os.environ.get('EC2_INI_PATH', ec2_default_ini_path)
|
ec2_ini_path = os.path.expanduser(os.path.expandvars(os.environ.get('EC2_INI_PATH', ec2_default_ini_path)))
|
||||||
config.read(ec2_ini_path)
|
config.read(ec2_ini_path)
|
||||||
|
|
||||||
# is eucalyptus?
|
# is eucalyptus?
|
||||||
@@ -232,18 +248,72 @@ class Ec2Inventory(object):
|
|||||||
if config.has_option('ec2', 'rds'):
|
if config.has_option('ec2', 'rds'):
|
||||||
self.rds_enabled = config.getboolean('ec2', 'rds')
|
self.rds_enabled = config.getboolean('ec2', 'rds')
|
||||||
|
|
||||||
# Return all EC2 and RDS instances (if RDS is enabled)
|
# Include ElastiCache instances?
|
||||||
|
self.elasticache_enabled = True
|
||||||
|
if config.has_option('ec2', 'elasticache'):
|
||||||
|
self.elasticache_enabled = config.getboolean('ec2', 'elasticache')
|
||||||
|
|
||||||
|
# Return all EC2 instances?
|
||||||
if config.has_option('ec2', 'all_instances'):
|
if config.has_option('ec2', 'all_instances'):
|
||||||
self.all_instances = config.getboolean('ec2', 'all_instances')
|
self.all_instances = config.getboolean('ec2', 'all_instances')
|
||||||
else:
|
else:
|
||||||
self.all_instances = False
|
self.all_instances = False
|
||||||
|
|
||||||
|
# Instance states to be gathered in inventory. Default is 'running'.
|
||||||
|
# Setting 'all_instances' to 'yes' overrides this option.
|
||||||
|
ec2_valid_instance_states = [
|
||||||
|
'pending',
|
||||||
|
'running',
|
||||||
|
'shutting-down',
|
||||||
|
'terminated',
|
||||||
|
'stopping',
|
||||||
|
'stopped'
|
||||||
|
]
|
||||||
|
self.ec2_instance_states = []
|
||||||
|
if self.all_instances:
|
||||||
|
self.ec2_instance_states = ec2_valid_instance_states
|
||||||
|
elif config.has_option('ec2', 'instance_states'):
|
||||||
|
for instance_state in config.get('ec2', 'instance_states').split(','):
|
||||||
|
instance_state = instance_state.strip()
|
||||||
|
if instance_state not in ec2_valid_instance_states:
|
||||||
|
continue
|
||||||
|
self.ec2_instance_states.append(instance_state)
|
||||||
|
else:
|
||||||
|
self.ec2_instance_states = ['running']
|
||||||
|
|
||||||
|
# Return all RDS instances? (if RDS is enabled)
|
||||||
if config.has_option('ec2', 'all_rds_instances') and self.rds_enabled:
|
if config.has_option('ec2', 'all_rds_instances') and self.rds_enabled:
|
||||||
self.all_rds_instances = config.getboolean('ec2', 'all_rds_instances')
|
self.all_rds_instances = config.getboolean('ec2', 'all_rds_instances')
|
||||||
else:
|
else:
|
||||||
self.all_rds_instances = False
|
self.all_rds_instances = False
|
||||||
|
|
||||||
|
# Return all ElastiCache replication groups? (if ElastiCache is enabled)
|
||||||
|
if config.has_option('ec2', 'all_elasticache_replication_groups') and self.elasticache_enabled:
|
||||||
|
self.all_elasticache_replication_groups = config.getboolean('ec2', 'all_elasticache_replication_groups')
|
||||||
|
else:
|
||||||
|
self.all_elasticache_replication_groups = False
|
||||||
|
|
||||||
|
# Return all ElastiCache clusters? (if ElastiCache is enabled)
|
||||||
|
if config.has_option('ec2', 'all_elasticache_clusters') and self.elasticache_enabled:
|
||||||
|
self.all_elasticache_clusters = config.getboolean('ec2', 'all_elasticache_clusters')
|
||||||
|
else:
|
||||||
|
self.all_elasticache_clusters = False
|
||||||
|
|
||||||
|
# Return all ElastiCache nodes? (if ElastiCache is enabled)
|
||||||
|
if config.has_option('ec2', 'all_elasticache_nodes') and self.elasticache_enabled:
|
||||||
|
self.all_elasticache_nodes = config.getboolean('ec2', 'all_elasticache_nodes')
|
||||||
|
else:
|
||||||
|
self.all_elasticache_nodes = False
|
||||||
|
|
||||||
|
# boto configuration profile (prefer CLI argument)
|
||||||
|
self.boto_profile = self.args.boto_profile
|
||||||
|
if config.has_option('ec2', 'boto_profile') and not self.boto_profile:
|
||||||
|
self.boto_profile = config.get('ec2', 'boto_profile')
|
||||||
|
|
||||||
# Cache related
|
# Cache related
|
||||||
cache_dir = os.path.expanduser(config.get('ec2', 'cache_path'))
|
cache_dir = os.path.expanduser(config.get('ec2', 'cache_path'))
|
||||||
|
if self.boto_profile:
|
||||||
|
cache_dir = os.path.join(cache_dir, 'profile_' + self.boto_profile)
|
||||||
if not os.path.exists(cache_dir):
|
if not os.path.exists(cache_dir):
|
||||||
os.makedirs(cache_dir)
|
os.makedirs(cache_dir)
|
||||||
|
|
||||||
@@ -272,6 +342,10 @@ class Ec2Inventory(object):
|
|||||||
'group_by_route53_names',
|
'group_by_route53_names',
|
||||||
'group_by_rds_engine',
|
'group_by_rds_engine',
|
||||||
'group_by_rds_parameter_group',
|
'group_by_rds_parameter_group',
|
||||||
|
'group_by_elasticache_engine',
|
||||||
|
'group_by_elasticache_cluster',
|
||||||
|
'group_by_elasticache_parameter_group',
|
||||||
|
'group_by_elasticache_replication_group',
|
||||||
]
|
]
|
||||||
for option in group_by_options:
|
for option in group_by_options:
|
||||||
if config.has_option('ec2', option):
|
if config.has_option('ec2', option):
|
||||||
@@ -321,6 +395,8 @@ class Ec2Inventory(object):
|
|||||||
help='Get all the variables about a specific instance')
|
help='Get all the variables about a specific instance')
|
||||||
parser.add_argument('--refresh-cache', action='store_true', default=False,
|
parser.add_argument('--refresh-cache', action='store_true', default=False,
|
||||||
help='Force refresh of cache by making API requests to EC2 (default: False - use cache files)')
|
help='Force refresh of cache by making API requests to EC2 (default: False - use cache files)')
|
||||||
|
parser.add_argument('--boto-profile', action='store',
|
||||||
|
help='Use boto profile for connections to EC2')
|
||||||
self.args = parser.parse_args()
|
self.args = parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
@@ -334,6 +410,9 @@ class Ec2Inventory(object):
|
|||||||
self.get_instances_by_region(region)
|
self.get_instances_by_region(region)
|
||||||
if self.rds_enabled:
|
if self.rds_enabled:
|
||||||
self.get_rds_instances_by_region(region)
|
self.get_rds_instances_by_region(region)
|
||||||
|
if self.elasticache_enabled:
|
||||||
|
self.get_elasticache_clusters_by_region(region)
|
||||||
|
self.get_elasticache_replication_groups_by_region(region)
|
||||||
|
|
||||||
self.write_to_cache(self.inventory, self.cache_path_cache)
|
self.write_to_cache(self.inventory, self.cache_path_cache)
|
||||||
self.write_to_cache(self.index, self.cache_path_index)
|
self.write_to_cache(self.index, self.cache_path_index)
|
||||||
@@ -344,7 +423,25 @@ class Ec2Inventory(object):
|
|||||||
conn = boto.connect_euca(host=self.eucalyptus_host)
|
conn = boto.connect_euca(host=self.eucalyptus_host)
|
||||||
conn.APIVersion = '2010-08-31'
|
conn.APIVersion = '2010-08-31'
|
||||||
else:
|
else:
|
||||||
conn = ec2.connect_to_region(region)
|
conn = self.connect_to_aws(ec2, region)
|
||||||
|
return conn
|
||||||
|
|
||||||
|
def boto_fix_security_token_in_profile(self, connect_args):
|
||||||
|
''' monkey patch for boto issue boto/boto#2100 '''
|
||||||
|
profile = 'profile ' + self.boto_profile
|
||||||
|
if boto.config.has_option(profile, 'aws_security_token'):
|
||||||
|
connect_args['security_token'] = boto.config.get(profile, 'aws_security_token')
|
||||||
|
return connect_args
|
||||||
|
|
||||||
|
def connect_to_aws(self, module, region):
|
||||||
|
connect_args = {}
|
||||||
|
|
||||||
|
# only pass the profile name if it's set (as it is not supported by older boto versions)
|
||||||
|
if self.boto_profile:
|
||||||
|
connect_args['profile_name'] = self.boto_profile
|
||||||
|
self.boto_fix_security_token_in_profile(connect_args)
|
||||||
|
|
||||||
|
conn = module.connect_to_region(region, **connect_args)
|
||||||
# connect_to_region will fail "silently" by returning None if the region name is wrong or not supported
|
# connect_to_region will fail "silently" by returning None if the region name is wrong or not supported
|
||||||
if conn is None:
|
if conn is None:
|
||||||
self.fail_with_error("region name: %s likely not supported, or AWS is down. connection to region failed." % region)
|
self.fail_with_error("region name: %s likely not supported, or AWS is down. connection to region failed." % region)
|
||||||
@@ -373,26 +470,96 @@ class Ec2Inventory(object):
|
|||||||
else:
|
else:
|
||||||
backend = 'Eucalyptus' if self.eucalyptus else 'AWS'
|
backend = 'Eucalyptus' if self.eucalyptus else 'AWS'
|
||||||
error = "Error connecting to %s backend.\n%s" % (backend, e.message)
|
error = "Error connecting to %s backend.\n%s" % (backend, e.message)
|
||||||
self.fail_with_error(error)
|
self.fail_with_error(error, 'getting EC2 instances')
|
||||||
|
|
||||||
def get_rds_instances_by_region(self, region):
|
def get_rds_instances_by_region(self, region):
|
||||||
''' Makes an AWS API call to the list of RDS instances in a particular
|
''' Makes an AWS API call to the list of RDS instances in a particular
|
||||||
region '''
|
region '''
|
||||||
|
|
||||||
try:
|
try:
|
||||||
conn = rds.connect_to_region(region)
|
conn = self.connect_to_aws(rds, region)
|
||||||
if conn:
|
if conn:
|
||||||
instances = conn.get_all_dbinstances()
|
instances = conn.get_all_dbinstances()
|
||||||
for instance in instances:
|
for instance in instances:
|
||||||
self.add_rds_instance(instance, region)
|
self.add_rds_instance(instance, region)
|
||||||
except boto.exception.BotoServerError as e:
|
except boto.exception.BotoServerError as e:
|
||||||
error = e.reason
|
error = e.reason
|
||||||
|
|
||||||
if e.error_code == 'AuthFailure':
|
if e.error_code == 'AuthFailure':
|
||||||
error = self.get_auth_error_message()
|
error = self.get_auth_error_message()
|
||||||
if not e.reason == "Forbidden":
|
if not e.reason == "Forbidden":
|
||||||
error = "Looks like AWS RDS is down:\n%s" % e.message
|
error = "Looks like AWS RDS is down:\n%s" % e.message
|
||||||
self.fail_with_error(error)
|
self.fail_with_error(error, 'getting RDS instances')
|
||||||
|
|
||||||
|
def get_elasticache_clusters_by_region(self, region):
|
||||||
|
''' Makes an AWS API call to the list of ElastiCache clusters (with
|
||||||
|
nodes' info) in a particular region.'''
|
||||||
|
|
||||||
|
# ElastiCache boto module doesn't provide a get_all_intances method,
|
||||||
|
# that's why we need to call describe directly (it would be called by
|
||||||
|
# the shorthand method anyway...)
|
||||||
|
try:
|
||||||
|
conn = elasticache.connect_to_region(region)
|
||||||
|
if conn:
|
||||||
|
# show_cache_node_info = True
|
||||||
|
# because we also want nodes' information
|
||||||
|
response = conn.describe_cache_clusters(None, None, None, True)
|
||||||
|
|
||||||
|
except boto.exception.BotoServerError as e:
|
||||||
|
error = e.reason
|
||||||
|
|
||||||
|
if e.error_code == 'AuthFailure':
|
||||||
|
error = self.get_auth_error_message()
|
||||||
|
if not e.reason == "Forbidden":
|
||||||
|
error = "Looks like AWS ElastiCache is down:\n%s" % e.message
|
||||||
|
self.fail_with_error(error, 'getting ElastiCache clusters')
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Boto also doesn't provide wrapper classes to CacheClusters or
|
||||||
|
# CacheNodes. Because of that wo can't make use of the get_list
|
||||||
|
# method in the AWSQueryConnection. Let's do the work manually
|
||||||
|
clusters = response['DescribeCacheClustersResponse']['DescribeCacheClustersResult']['CacheClusters']
|
||||||
|
|
||||||
|
except KeyError as e:
|
||||||
|
error = "ElastiCache query to AWS failed (unexpected format)."
|
||||||
|
self.fail_with_error(error, 'getting ElastiCache clusters')
|
||||||
|
|
||||||
|
for cluster in clusters:
|
||||||
|
self.add_elasticache_cluster(cluster, region)
|
||||||
|
|
||||||
|
def get_elasticache_replication_groups_by_region(self, region):
|
||||||
|
''' Makes an AWS API call to the list of ElastiCache replication groups
|
||||||
|
in a particular region.'''
|
||||||
|
|
||||||
|
# ElastiCache boto module doesn't provide a get_all_intances method,
|
||||||
|
# that's why we need to call describe directly (it would be called by
|
||||||
|
# the shorthand method anyway...)
|
||||||
|
try:
|
||||||
|
conn = elasticache.connect_to_region(region)
|
||||||
|
if conn:
|
||||||
|
response = conn.describe_replication_groups()
|
||||||
|
|
||||||
|
except boto.exception.BotoServerError as e:
|
||||||
|
error = e.reason
|
||||||
|
|
||||||
|
if e.error_code == 'AuthFailure':
|
||||||
|
error = self.get_auth_error_message()
|
||||||
|
if not e.reason == "Forbidden":
|
||||||
|
error = "Looks like AWS ElastiCache [Replication Groups] is down:\n%s" % e.message
|
||||||
|
self.fail_with_error(error, 'getting ElastiCache clusters')
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Boto also doesn't provide wrapper classes to ReplicationGroups
|
||||||
|
# Because of that wo can't make use of the get_list method in the
|
||||||
|
# AWSQueryConnection. Let's do the work manually
|
||||||
|
replication_groups = response['DescribeReplicationGroupsResponse']['DescribeReplicationGroupsResult']['ReplicationGroups']
|
||||||
|
|
||||||
|
except KeyError as e:
|
||||||
|
error = "ElastiCache [Replication Groups] query to AWS failed (unexpected format)."
|
||||||
|
self.fail_with_error(error, 'getting ElastiCache clusters')
|
||||||
|
|
||||||
|
for replication_group in replication_groups:
|
||||||
|
self.add_elasticache_replication_group(replication_group, region)
|
||||||
|
|
||||||
def get_auth_error_message(self):
|
def get_auth_error_message(self):
|
||||||
''' create an informative error message if there is an issue authenticating'''
|
''' create an informative error message if there is an issue authenticating'''
|
||||||
@@ -410,9 +577,12 @@ class Ec2Inventory(object):
|
|||||||
errors.append(" - No Boto config found at any expected location '%s'" % ', '.join(boto_paths))
|
errors.append(" - No Boto config found at any expected location '%s'" % ', '.join(boto_paths))
|
||||||
|
|
||||||
return '\n'.join(errors)
|
return '\n'.join(errors)
|
||||||
|
|
||||||
def fail_with_error(self, err_msg):
|
def fail_with_error(self, err_msg, err_operation=None):
|
||||||
'''log an error to std err for ansible-playbook to consume and exit'''
|
'''log an error to std err for ansible-playbook to consume and exit'''
|
||||||
|
if err_operation:
|
||||||
|
err_msg = 'ERROR: "{err_msg}", while: {err_operation}'.format(
|
||||||
|
err_msg=err_msg, err_operation=err_operation)
|
||||||
sys.stderr.write(err_msg)
|
sys.stderr.write(err_msg)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
@@ -428,8 +598,8 @@ class Ec2Inventory(object):
|
|||||||
''' Adds an instance to the inventory and index, as long as it is
|
''' Adds an instance to the inventory and index, as long as it is
|
||||||
addressable '''
|
addressable '''
|
||||||
|
|
||||||
# Only want running instances unless all_instances is True
|
# Only return instances with desired instance states
|
||||||
if not self.all_instances and instance.state != 'running':
|
if instance.state not in self.ec2_instance_states:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Select the best destination address
|
# Select the best destination address
|
||||||
@@ -527,8 +697,7 @@ class Ec2Inventory(object):
|
|||||||
self.push(self.inventory, key, dest)
|
self.push(self.inventory, key, dest)
|
||||||
if self.nested_groups:
|
if self.nested_groups:
|
||||||
self.push_group(self.inventory, 'tags', self.to_safe("tag_" + k))
|
self.push_group(self.inventory, 'tags', self.to_safe("tag_" + k))
|
||||||
if v:
|
self.push_group(self.inventory, self.to_safe("tag_" + k), key)
|
||||||
self.push_group(self.inventory, self.to_safe("tag_" + k), key)
|
|
||||||
|
|
||||||
# Inventory: Group by Route53 domain names if enabled
|
# Inventory: Group by Route53 domain names if enabled
|
||||||
if self.route53_enabled and self.group_by_route53_names:
|
if self.route53_enabled and self.group_by_route53_names:
|
||||||
@@ -633,6 +802,243 @@ class Ec2Inventory(object):
|
|||||||
|
|
||||||
self.inventory["_meta"]["hostvars"][dest] = self.get_host_info_dict_from_instance(instance)
|
self.inventory["_meta"]["hostvars"][dest] = self.get_host_info_dict_from_instance(instance)
|
||||||
|
|
||||||
|
def add_elasticache_cluster(self, cluster, region):
|
||||||
|
''' Adds an ElastiCache cluster to the inventory and index, as long as
|
||||||
|
it's nodes are addressable '''
|
||||||
|
|
||||||
|
# Only want available clusters unless all_elasticache_clusters is True
|
||||||
|
if not self.all_elasticache_clusters and cluster['CacheClusterStatus'] != 'available':
|
||||||
|
return
|
||||||
|
|
||||||
|
# Select the best destination address
|
||||||
|
if 'ConfigurationEndpoint' in cluster and cluster['ConfigurationEndpoint']:
|
||||||
|
# Memcached cluster
|
||||||
|
dest = cluster['ConfigurationEndpoint']['Address']
|
||||||
|
is_redis = False
|
||||||
|
else:
|
||||||
|
# Redis sigle node cluster
|
||||||
|
# Because all Redis clusters are single nodes, we'll merge the
|
||||||
|
# info from the cluster with info about the node
|
||||||
|
dest = cluster['CacheNodes'][0]['Endpoint']['Address']
|
||||||
|
is_redis = True
|
||||||
|
|
||||||
|
if not dest:
|
||||||
|
# Skip clusters we cannot address (e.g. private VPC subnet)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Add to index
|
||||||
|
self.index[dest] = [region, cluster['CacheClusterId']]
|
||||||
|
|
||||||
|
# Inventory: Group by instance ID (always a group of 1)
|
||||||
|
if self.group_by_instance_id:
|
||||||
|
self.inventory[cluster['CacheClusterId']] = [dest]
|
||||||
|
if self.nested_groups:
|
||||||
|
self.push_group(self.inventory, 'instances', cluster['CacheClusterId'])
|
||||||
|
|
||||||
|
# Inventory: Group by region
|
||||||
|
if self.group_by_region and not is_redis:
|
||||||
|
self.push(self.inventory, region, dest)
|
||||||
|
if self.nested_groups:
|
||||||
|
self.push_group(self.inventory, 'regions', region)
|
||||||
|
|
||||||
|
# Inventory: Group by availability zone
|
||||||
|
if self.group_by_availability_zone and not is_redis:
|
||||||
|
self.push(self.inventory, cluster['PreferredAvailabilityZone'], dest)
|
||||||
|
if self.nested_groups:
|
||||||
|
if self.group_by_region:
|
||||||
|
self.push_group(self.inventory, region, cluster['PreferredAvailabilityZone'])
|
||||||
|
self.push_group(self.inventory, 'zones', cluster['PreferredAvailabilityZone'])
|
||||||
|
|
||||||
|
# Inventory: Group by node type
|
||||||
|
if self.group_by_instance_type and not is_redis:
|
||||||
|
type_name = self.to_safe('type_' + cluster['CacheNodeType'])
|
||||||
|
self.push(self.inventory, type_name, dest)
|
||||||
|
if self.nested_groups:
|
||||||
|
self.push_group(self.inventory, 'types', type_name)
|
||||||
|
|
||||||
|
# Inventory: Group by VPC (information not available in the current
|
||||||
|
# AWS API version for ElastiCache)
|
||||||
|
|
||||||
|
# Inventory: Group by security group
|
||||||
|
if self.group_by_security_group and not is_redis:
|
||||||
|
|
||||||
|
# Check for the existence of the 'SecurityGroups' key and also if
|
||||||
|
# this key has some value. When the cluster is not placed in a SG
|
||||||
|
# the query can return None here and cause an error.
|
||||||
|
if 'SecurityGroups' in cluster and cluster['SecurityGroups'] is not None:
|
||||||
|
for security_group in cluster['SecurityGroups']:
|
||||||
|
key = self.to_safe("security_group_" + security_group['SecurityGroupId'])
|
||||||
|
self.push(self.inventory, key, dest)
|
||||||
|
if self.nested_groups:
|
||||||
|
self.push_group(self.inventory, 'security_groups', key)
|
||||||
|
|
||||||
|
# Inventory: Group by engine
|
||||||
|
if self.group_by_elasticache_engine and not is_redis:
|
||||||
|
self.push(self.inventory, self.to_safe("elasticache_" + cluster['Engine']), dest)
|
||||||
|
if self.nested_groups:
|
||||||
|
self.push_group(self.inventory, 'elasticache_engines', self.to_safe(cluster['Engine']))
|
||||||
|
|
||||||
|
# Inventory: Group by parameter group
|
||||||
|
if self.group_by_elasticache_parameter_group:
|
||||||
|
self.push(self.inventory, self.to_safe("elasticache_parameter_group_" + cluster['CacheParameterGroup']['CacheParameterGroupName']), dest)
|
||||||
|
if self.nested_groups:
|
||||||
|
self.push_group(self.inventory, 'elasticache_parameter_groups', self.to_safe(cluster['CacheParameterGroup']['CacheParameterGroupName']))
|
||||||
|
|
||||||
|
# Inventory: Group by replication group
|
||||||
|
if self.group_by_elasticache_replication_group and 'ReplicationGroupId' in cluster and cluster['ReplicationGroupId']:
|
||||||
|
self.push(self.inventory, self.to_safe("elasticache_replication_group_" + cluster['ReplicationGroupId']), dest)
|
||||||
|
if self.nested_groups:
|
||||||
|
self.push_group(self.inventory, 'elasticache_replication_groups', self.to_safe(cluster['ReplicationGroupId']))
|
||||||
|
|
||||||
|
# Global Tag: all ElastiCache clusters
|
||||||
|
self.push(self.inventory, 'elasticache_clusters', cluster['CacheClusterId'])
|
||||||
|
|
||||||
|
host_info = self.get_host_info_dict_from_describe_dict(cluster)
|
||||||
|
|
||||||
|
self.inventory["_meta"]["hostvars"][dest] = host_info
|
||||||
|
|
||||||
|
# Add the nodes
|
||||||
|
for node in cluster['CacheNodes']:
|
||||||
|
self.add_elasticache_node(node, cluster, region)
|
||||||
|
|
||||||
|
def add_elasticache_node(self, node, cluster, region):
|
||||||
|
''' Adds an ElastiCache node to the inventory and index, as long as
|
||||||
|
it is addressable '''
|
||||||
|
|
||||||
|
# Only want available nodes unless all_elasticache_nodes is True
|
||||||
|
if not self.all_elasticache_nodes and node['CacheNodeStatus'] != 'available':
|
||||||
|
return
|
||||||
|
|
||||||
|
# Select the best destination address
|
||||||
|
dest = node['Endpoint']['Address']
|
||||||
|
|
||||||
|
if not dest:
|
||||||
|
# Skip nodes we cannot address (e.g. private VPC subnet)
|
||||||
|
return
|
||||||
|
|
||||||
|
node_id = self.to_safe(cluster['CacheClusterId'] + '_' + node['CacheNodeId'])
|
||||||
|
|
||||||
|
# Add to index
|
||||||
|
self.index[dest] = [region, node_id]
|
||||||
|
|
||||||
|
# Inventory: Group by node ID (always a group of 1)
|
||||||
|
if self.group_by_instance_id:
|
||||||
|
self.inventory[node_id] = [dest]
|
||||||
|
if self.nested_groups:
|
||||||
|
self.push_group(self.inventory, 'instances', node_id)
|
||||||
|
|
||||||
|
# Inventory: Group by region
|
||||||
|
if self.group_by_region:
|
||||||
|
self.push(self.inventory, region, dest)
|
||||||
|
if self.nested_groups:
|
||||||
|
self.push_group(self.inventory, 'regions', region)
|
||||||
|
|
||||||
|
# Inventory: Group by availability zone
|
||||||
|
if self.group_by_availability_zone:
|
||||||
|
self.push(self.inventory, cluster['PreferredAvailabilityZone'], dest)
|
||||||
|
if self.nested_groups:
|
||||||
|
if self.group_by_region:
|
||||||
|
self.push_group(self.inventory, region, cluster['PreferredAvailabilityZone'])
|
||||||
|
self.push_group(self.inventory, 'zones', cluster['PreferredAvailabilityZone'])
|
||||||
|
|
||||||
|
# Inventory: Group by node type
|
||||||
|
if self.group_by_instance_type:
|
||||||
|
type_name = self.to_safe('type_' + cluster['CacheNodeType'])
|
||||||
|
self.push(self.inventory, type_name, dest)
|
||||||
|
if self.nested_groups:
|
||||||
|
self.push_group(self.inventory, 'types', type_name)
|
||||||
|
|
||||||
|
# Inventory: Group by VPC (information not available in the current
|
||||||
|
# AWS API version for ElastiCache)
|
||||||
|
|
||||||
|
# Inventory: Group by security group
|
||||||
|
if self.group_by_security_group:
|
||||||
|
|
||||||
|
# Check for the existence of the 'SecurityGroups' key and also if
|
||||||
|
# this key has some value. When the cluster is not placed in a SG
|
||||||
|
# the query can return None here and cause an error.
|
||||||
|
if 'SecurityGroups' in cluster and cluster['SecurityGroups'] is not None:
|
||||||
|
for security_group in cluster['SecurityGroups']:
|
||||||
|
key = self.to_safe("security_group_" + security_group['SecurityGroupId'])
|
||||||
|
self.push(self.inventory, key, dest)
|
||||||
|
if self.nested_groups:
|
||||||
|
self.push_group(self.inventory, 'security_groups', key)
|
||||||
|
|
||||||
|
# Inventory: Group by engine
|
||||||
|
if self.group_by_elasticache_engine:
|
||||||
|
self.push(self.inventory, self.to_safe("elasticache_" + cluster['Engine']), dest)
|
||||||
|
if self.nested_groups:
|
||||||
|
self.push_group(self.inventory, 'elasticache_engines', self.to_safe("elasticache_" + cluster['Engine']))
|
||||||
|
|
||||||
|
# Inventory: Group by parameter group (done at cluster level)
|
||||||
|
|
||||||
|
# Inventory: Group by replication group (done at cluster level)
|
||||||
|
|
||||||
|
# Inventory: Group by ElastiCache Cluster
|
||||||
|
if self.group_by_elasticache_cluster:
|
||||||
|
self.push(self.inventory, self.to_safe("elasticache_cluster_" + cluster['CacheClusterId']), dest)
|
||||||
|
|
||||||
|
# Global Tag: all ElastiCache nodes
|
||||||
|
self.push(self.inventory, 'elasticache_nodes', dest)
|
||||||
|
|
||||||
|
host_info = self.get_host_info_dict_from_describe_dict(node)
|
||||||
|
|
||||||
|
if dest in self.inventory["_meta"]["hostvars"]:
|
||||||
|
self.inventory["_meta"]["hostvars"][dest].update(host_info)
|
||||||
|
else:
|
||||||
|
self.inventory["_meta"]["hostvars"][dest] = host_info
|
||||||
|
|
||||||
|
def add_elasticache_replication_group(self, replication_group, region):
|
||||||
|
''' Adds an ElastiCache replication group to the inventory and index '''
|
||||||
|
|
||||||
|
# Only want available clusters unless all_elasticache_replication_groups is True
|
||||||
|
if not self.all_elasticache_replication_groups and replication_group['Status'] != 'available':
|
||||||
|
return
|
||||||
|
|
||||||
|
# Select the best destination address (PrimaryEndpoint)
|
||||||
|
dest = replication_group['NodeGroups'][0]['PrimaryEndpoint']['Address']
|
||||||
|
|
||||||
|
if not dest:
|
||||||
|
# Skip clusters we cannot address (e.g. private VPC subnet)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Add to index
|
||||||
|
self.index[dest] = [region, replication_group['ReplicationGroupId']]
|
||||||
|
|
||||||
|
# Inventory: Group by ID (always a group of 1)
|
||||||
|
if self.group_by_instance_id:
|
||||||
|
self.inventory[replication_group['ReplicationGroupId']] = [dest]
|
||||||
|
if self.nested_groups:
|
||||||
|
self.push_group(self.inventory, 'instances', replication_group['ReplicationGroupId'])
|
||||||
|
|
||||||
|
# Inventory: Group by region
|
||||||
|
if self.group_by_region:
|
||||||
|
self.push(self.inventory, region, dest)
|
||||||
|
if self.nested_groups:
|
||||||
|
self.push_group(self.inventory, 'regions', region)
|
||||||
|
|
||||||
|
# Inventory: Group by availability zone (doesn't apply to replication groups)
|
||||||
|
|
||||||
|
# Inventory: Group by node type (doesn't apply to replication groups)
|
||||||
|
|
||||||
|
# Inventory: Group by VPC (information not available in the current
|
||||||
|
# AWS API version for replication groups
|
||||||
|
|
||||||
|
# Inventory: Group by security group (doesn't apply to replication groups)
|
||||||
|
# Check this value in cluster level
|
||||||
|
|
||||||
|
# Inventory: Group by engine (replication groups are always Redis)
|
||||||
|
if self.group_by_elasticache_engine:
|
||||||
|
self.push(self.inventory, 'elasticache_redis', dest)
|
||||||
|
if self.nested_groups:
|
||||||
|
self.push_group(self.inventory, 'elasticache_engines', 'redis')
|
||||||
|
|
||||||
|
# Global Tag: all ElastiCache clusters
|
||||||
|
self.push(self.inventory, 'elasticache_replication_groups', replication_group['ReplicationGroupId'])
|
||||||
|
|
||||||
|
host_info = self.get_host_info_dict_from_describe_dict(replication_group)
|
||||||
|
|
||||||
|
self.inventory["_meta"]["hostvars"][dest] = host_info
|
||||||
|
|
||||||
def get_route53_records(self):
|
def get_route53_records(self):
|
||||||
''' Get and store the map of resource records to domain names that
|
''' Get and store the map of resource records to domain names that
|
||||||
@@ -681,7 +1087,6 @@ class Ec2Inventory(object):
|
|||||||
|
|
||||||
return list(name_list)
|
return list(name_list)
|
||||||
|
|
||||||
|
|
||||||
def get_host_info_dict_from_instance(self, instance):
|
def get_host_info_dict_from_instance(self, instance):
|
||||||
instance_vars = {}
|
instance_vars = {}
|
||||||
for key in vars(instance):
|
for key in vars(instance):
|
||||||
@@ -727,6 +1132,91 @@ class Ec2Inventory(object):
|
|||||||
|
|
||||||
return instance_vars
|
return instance_vars
|
||||||
|
|
||||||
|
def get_host_info_dict_from_describe_dict(self, describe_dict):
|
||||||
|
''' Parses the dictionary returned by the API call into a flat list
|
||||||
|
of parameters. This method should be used only when 'describe' is
|
||||||
|
used directly because Boto doesn't provide specific classes. '''
|
||||||
|
|
||||||
|
# I really don't agree with prefixing everything with 'ec2'
|
||||||
|
# because EC2, RDS and ElastiCache are different services.
|
||||||
|
# I'm just following the pattern used until now to not break any
|
||||||
|
# compatibility.
|
||||||
|
|
||||||
|
host_info = {}
|
||||||
|
for key in describe_dict:
|
||||||
|
value = describe_dict[key]
|
||||||
|
key = self.to_safe('ec2_' + self.uncammelize(key))
|
||||||
|
|
||||||
|
# Handle complex types
|
||||||
|
|
||||||
|
# Target: Memcached Cache Clusters
|
||||||
|
if key == 'ec2_configuration_endpoint' and value:
|
||||||
|
host_info['ec2_configuration_endpoint_address'] = value['Address']
|
||||||
|
host_info['ec2_configuration_endpoint_port'] = value['Port']
|
||||||
|
|
||||||
|
# Target: Cache Nodes and Redis Cache Clusters (single node)
|
||||||
|
if key == 'ec2_endpoint' and value:
|
||||||
|
host_info['ec2_endpoint_address'] = value['Address']
|
||||||
|
host_info['ec2_endpoint_port'] = value['Port']
|
||||||
|
|
||||||
|
# Target: Redis Replication Groups
|
||||||
|
if key == 'ec2_node_groups' and value:
|
||||||
|
host_info['ec2_endpoint_address'] = value[0]['PrimaryEndpoint']['Address']
|
||||||
|
host_info['ec2_endpoint_port'] = value[0]['PrimaryEndpoint']['Port']
|
||||||
|
replica_count = 0
|
||||||
|
for node in value[0]['NodeGroupMembers']:
|
||||||
|
if node['CurrentRole'] == 'primary':
|
||||||
|
host_info['ec2_primary_cluster_address'] = node['ReadEndpoint']['Address']
|
||||||
|
host_info['ec2_primary_cluster_port'] = node['ReadEndpoint']['Port']
|
||||||
|
host_info['ec2_primary_cluster_id'] = node['CacheClusterId']
|
||||||
|
elif node['CurrentRole'] == 'replica':
|
||||||
|
host_info['ec2_replica_cluster_address_'+ str(replica_count)] = node['ReadEndpoint']['Address']
|
||||||
|
host_info['ec2_replica_cluster_port_'+ str(replica_count)] = node['ReadEndpoint']['Port']
|
||||||
|
host_info['ec2_replica_cluster_id_'+ str(replica_count)] = node['CacheClusterId']
|
||||||
|
replica_count += 1
|
||||||
|
|
||||||
|
# Target: Redis Replication Groups
|
||||||
|
if key == 'ec2_member_clusters' and value:
|
||||||
|
host_info['ec2_member_clusters'] = ','.join([str(i) for i in value])
|
||||||
|
|
||||||
|
# Target: All Cache Clusters
|
||||||
|
elif key == 'ec2_cache_parameter_group':
|
||||||
|
host_info["ec2_cache_node_ids_to_reboot"] = ','.join([str(i) for i in value['CacheNodeIdsToReboot']])
|
||||||
|
host_info['ec2_cache_parameter_group_name'] = value['CacheParameterGroupName']
|
||||||
|
host_info['ec2_cache_parameter_apply_status'] = value['ParameterApplyStatus']
|
||||||
|
|
||||||
|
# Target: Almost everything
|
||||||
|
elif key == 'ec2_security_groups':
|
||||||
|
|
||||||
|
# Skip if SecurityGroups is None
|
||||||
|
# (it is possible to have the key defined but no value in it).
|
||||||
|
if value is not None:
|
||||||
|
sg_ids = []
|
||||||
|
for sg in value:
|
||||||
|
sg_ids.append(sg['SecurityGroupId'])
|
||||||
|
host_info["ec2_security_group_ids"] = ','.join([str(i) for i in sg_ids])
|
||||||
|
|
||||||
|
# Target: Everything
|
||||||
|
# Preserve booleans and integers
|
||||||
|
elif type(value) in [int, bool]:
|
||||||
|
host_info[key] = value
|
||||||
|
|
||||||
|
# Target: Everything
|
||||||
|
# Sanitize string values
|
||||||
|
elif isinstance(value, six.string_types):
|
||||||
|
host_info[key] = value.strip()
|
||||||
|
|
||||||
|
# Target: Everything
|
||||||
|
# Replace None by an empty string
|
||||||
|
elif type(value) == type(None):
|
||||||
|
host_info[key] = ''
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Remove non-processed complex types
|
||||||
|
pass
|
||||||
|
|
||||||
|
return host_info
|
||||||
|
|
||||||
def get_host_info(self):
|
def get_host_info(self):
|
||||||
''' Get variables about a specific host '''
|
''' Get variables about a specific host '''
|
||||||
|
|
||||||
@@ -790,6 +1280,9 @@ class Ec2Inventory(object):
|
|||||||
cache.write(json_data)
|
cache.write(json_data)
|
||||||
cache.close()
|
cache.close()
|
||||||
|
|
||||||
|
def uncammelize(self, key):
|
||||||
|
temp = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', key)
|
||||||
|
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', temp).lower()
|
||||||
|
|
||||||
def to_safe(self, word):
|
def to_safe(self, word):
|
||||||
''' Converts 'bad' characters in a string to underscores so they can be
|
''' Converts 'bad' characters in a string to underscores so they can be
|
||||||
@@ -797,7 +1290,6 @@ class Ec2Inventory(object):
|
|||||||
|
|
||||||
return re.sub("[^A-Za-z0-9\_]", "_", word)
|
return re.sub("[^A-Za-z0-9\_]", "_", word)
|
||||||
|
|
||||||
|
|
||||||
def json_format_dict(self, data, pretty=False):
|
def json_format_dict(self, data, pretty=False):
|
||||||
''' Converts a dict to a JSON object and dumps it as a formatted
|
''' Converts a dict to a JSON object and dumps it as a formatted
|
||||||
string '''
|
string '''
|
||||||
|
|||||||
508
awx/settings/local_settings.py.docker_compose
Normal file
508
awx/settings/local_settings.py.docker_compose
Normal file
@@ -0,0 +1,508 @@
|
|||||||
|
# Copyright (c) 2015 Ansible, Inc. (formerly AnsibleWorks, Inc.)
|
||||||
|
# All Rights Reserved.
|
||||||
|
|
||||||
|
# Local Django settings for AWX project. Rename to "local_settings.py" and
|
||||||
|
# edit as needed for your development environment.
|
||||||
|
|
||||||
|
# All variables defined in awx/settings/development.py will already be loaded
|
||||||
|
# into the global namespace before this file is loaded, to allow for reading
|
||||||
|
# and updating the default settings as needed.
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# MISC PROJECT SETTINGS
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
ADMINS = (
|
||||||
|
# ('Your Name', 'your_email@domain.com'),
|
||||||
|
)
|
||||||
|
|
||||||
|
MANAGERS = ADMINS
|
||||||
|
|
||||||
|
# Database settings to use PostgreSQL for development.
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||||
|
'NAME': 'awx-dev',
|
||||||
|
'USER': 'awx-dev',
|
||||||
|
'PASSWORD': 'AWXsome1',
|
||||||
|
'HOST': 'postgres',
|
||||||
|
'PORT': '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Use SQLite for unit tests instead of PostgreSQL. If the lines below are
|
||||||
|
# commented out, Django will create the test_awx-dev database in PostgreSQL to
|
||||||
|
# run unit tests.
|
||||||
|
if len(sys.argv) >= 2 and sys.argv[1] == 'test':
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'NAME': os.path.join(BASE_DIR, 'awx.sqlite3'),
|
||||||
|
# Test database cannot be :memory: for celery/inventory tests.
|
||||||
|
'TEST_NAME': os.path.join(BASE_DIR, 'awx_test.sqlite3'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MONGO_DB = 'system_tracking_test'
|
||||||
|
|
||||||
|
# Celery AMQP configuration.
|
||||||
|
BROKER_URL = 'redis://redis/'
|
||||||
|
|
||||||
|
# Mongo host configuration
|
||||||
|
MONGO_HOST = 'mongo'
|
||||||
|
|
||||||
|
# Set True to enable additional logging from the job_event_callback plugin
|
||||||
|
JOB_CALLBACK_DEBUG = False
|
||||||
|
|
||||||
|
# Absolute filesystem path to the directory to host projects (with playbooks).
|
||||||
|
# This directory should NOT be web-accessible.
|
||||||
|
PROJECTS_ROOT = os.path.join(BASE_DIR, 'projects')
|
||||||
|
|
||||||
|
# Absolute filesystem path to the directory for job status stdout
|
||||||
|
# This directory should not be web-accessible
|
||||||
|
JOBOUTPUT_ROOT = os.path.join(BASE_DIR, 'job_status')
|
||||||
|
|
||||||
|
# The UUID of the system, for HA.
|
||||||
|
SYSTEM_UUID = '00000000-0000-0000-0000-000000000000'
|
||||||
|
|
||||||
|
# Local time zone for this installation. Choices can be found here:
|
||||||
|
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
|
||||||
|
# although not all choices may be available on all operating systems.
|
||||||
|
# On Unix systems, a value of None will cause Django to use the same
|
||||||
|
# timezone as the operating system.
|
||||||
|
# If running in a Windows environment this must be set to the same as your
|
||||||
|
# system time zone.
|
||||||
|
TIME_ZONE = 'America/New_York'
|
||||||
|
|
||||||
|
# Language code for this installation. All choices can be found here:
|
||||||
|
# http://www.i18nguy.com/unicode/language-identifiers.html
|
||||||
|
LANGUAGE_CODE = 'en-us'
|
||||||
|
|
||||||
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
|
# Hardcoded values can leak through source control. Consider loading
|
||||||
|
# the secret key from an environment variable or a file instead.
|
||||||
|
SECRET_KEY = 'p7z7g1ql4%6+(6nlebb6hdk7sd^&fnjpal308%n%+p^_e6vo1y'
|
||||||
|
|
||||||
|
# HTTP headers and meta keys to search to determine remote host name or IP. Add
|
||||||
|
# additional items to this list, such as "HTTP_X_FORWARDED_FOR", if behind a
|
||||||
|
# reverse proxy.
|
||||||
|
REMOTE_HOST_HEADERS = ['REMOTE_ADDR', 'REMOTE_HOST']
|
||||||
|
|
||||||
|
# Define additional environment variables to be passed to subprocess started by
|
||||||
|
# the celery task.
|
||||||
|
#AWX_TASK_ENV['FOO'] = 'BAR'
|
||||||
|
|
||||||
|
# If set, use -vvv for project updates instead of -v for more output.
|
||||||
|
# PROJECT_UPDATE_VVV=True
|
||||||
|
|
||||||
|
# Set verbosity for inventory import command when running inventory updates.
|
||||||
|
# INVENTORY_UPDATE_VERBOSITY=1
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# EMAIL SETTINGS
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
# Email address that error messages come from.
|
||||||
|
SERVER_EMAIL = 'root@localhost'
|
||||||
|
|
||||||
|
# The email backend to use. For possible shortcuts see django.core.mail.
|
||||||
|
# The default is to use the SMTP backend.
|
||||||
|
# Third-party backends can be specified by providing a Python path
|
||||||
|
# to a module that defines an EmailBackend class.
|
||||||
|
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
||||||
|
|
||||||
|
# Host for sending email.
|
||||||
|
EMAIL_HOST = 'localhost'
|
||||||
|
|
||||||
|
# Port for sending email.
|
||||||
|
EMAIL_PORT = 25
|
||||||
|
|
||||||
|
# Optional SMTP authentication information for EMAIL_HOST.
|
||||||
|
EMAIL_HOST_USER = ''
|
||||||
|
EMAIL_HOST_PASSWORD = ''
|
||||||
|
EMAIL_USE_TLS = False
|
||||||
|
|
||||||
|
# Default email address to use for various automated correspondence from
|
||||||
|
# the site managers.
|
||||||
|
DEFAULT_FROM_EMAIL = 'webmaster@localhost'
|
||||||
|
|
||||||
|
# Subject-line prefix for email messages send with django.core.mail.mail_admins
|
||||||
|
# or ...mail_managers. Make sure to include the trailing space.
|
||||||
|
EMAIL_SUBJECT_PREFIX = '[AWX] '
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# LOGGING SETTINGS
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
# Enable logging to syslog. Setting level to ERROR captures 500 errors,
|
||||||
|
# WARNING also logs 4xx responses.
|
||||||
|
LOGGING['handlers']['syslog'] = {
|
||||||
|
'level': 'WARNING',
|
||||||
|
'filters': [],
|
||||||
|
'class': 'logging.handlers.SysLogHandler',
|
||||||
|
'address': '/dev/log',
|
||||||
|
'facility': 'local0',
|
||||||
|
'formatter': 'simple',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Enable the following lines to also log to a file.
|
||||||
|
#LOGGING['handlers']['file'] = {
|
||||||
|
# 'class': 'logging.FileHandler',
|
||||||
|
# 'filename': os.path.join(BASE_DIR, 'awx.log'),
|
||||||
|
# 'formatter': 'simple',
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Enable the following lines to turn on lots of permissions-related logging.
|
||||||
|
#LOGGING['loggers']['awx.main.access']['propagate'] = True
|
||||||
|
#LOGGING['loggers']['awx.main.signals']['propagate'] = True
|
||||||
|
#LOGGING['loggers']['awx.main.permissions']['propagate'] = True
|
||||||
|
|
||||||
|
# Enable the following lines to turn on LDAP auth logging.
|
||||||
|
#LOGGING['loggers']['django_auth_ldap']['handlers'] = ['console']
|
||||||
|
#LOGGING['loggers']['django_auth_ldap']['level'] = 'DEBUG'
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# LDAP AUTHENTICATION SETTINGS
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
# Refer to django-auth-ldap docs for more details:
|
||||||
|
# http://pythonhosted.org/django-auth-ldap/authentication.html
|
||||||
|
|
||||||
|
# LDAP server URI, such as "ldap://ldap.example.com:389" (non-SSL) or
|
||||||
|
# "ldaps://ldap.example.com:636" (SSL). LDAP authentication is disable if this
|
||||||
|
# parameter is empty.
|
||||||
|
AUTH_LDAP_SERVER_URI = ''
|
||||||
|
|
||||||
|
# DN of user to bind for all search queries. Normally in the format
|
||||||
|
# "CN=Some User,OU=Users,DC=example,DC=com" but may also be specified as
|
||||||
|
# "DOMAIN\username" for Active Directory.
|
||||||
|
AUTH_LDAP_BIND_DN = ''
|
||||||
|
|
||||||
|
# Password using to bind above user account.
|
||||||
|
AUTH_LDAP_BIND_PASSWORD = ''
|
||||||
|
|
||||||
|
# Enable TLS when the connection is not using SSL.
|
||||||
|
AUTH_LDAP_START_TLS = False
|
||||||
|
|
||||||
|
# Imports needed for remaining LDAP configuration.
|
||||||
|
import ldap
|
||||||
|
from django_auth_ldap.config import LDAPSearch, LDAPSearchUnion
|
||||||
|
from django_auth_ldap.config import ActiveDirectoryGroupType
|
||||||
|
|
||||||
|
# LDAP search query to find users.
|
||||||
|
AUTH_LDAP_USER_SEARCH = LDAPSearch(
|
||||||
|
'OU=Users,DC=example,DC=com', # Base DN
|
||||||
|
ldap.SCOPE_SUBTREE, # SCOPE_BASE, SCOPE_ONELEVEL, SCOPE_SUBTREE
|
||||||
|
'(sAMAccountName=%(user)s)', # Query
|
||||||
|
)
|
||||||
|
|
||||||
|
# Alternative to user search, if user DNs are all of the same format.
|
||||||
|
#AUTH_LDAP_USER_DN_TEMPLATE = 'uid=%(user)s,OU=Users,DC=example,DC=com'
|
||||||
|
|
||||||
|
# Mapping of LDAP to user atrributes (key is user attribute name, value is LDAP
|
||||||
|
# attribute name).
|
||||||
|
AUTH_LDAP_USER_ATTR_MAP = {
|
||||||
|
'first_name': 'givenName',
|
||||||
|
'last_name': 'sn',
|
||||||
|
'email': 'mail',
|
||||||
|
}
|
||||||
|
|
||||||
|
# LDAP search query to find groups. Does not support LDAPSearchUnion.
|
||||||
|
AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
|
||||||
|
'DC=example,DC=com', # Base DN
|
||||||
|
ldap.SCOPE_SUBTREE, # SCOPE_BASE, SCOPE_ONELEVEL, SCOPE_SUBTREE
|
||||||
|
'(objectClass=group)', # Query
|
||||||
|
)
|
||||||
|
# Type of group returned by the search above. Should be one of the types
|
||||||
|
# listed at: http://pythonhosted.org/django-auth-ldap/groups.html#types-of-groups
|
||||||
|
AUTH_LDAP_GROUP_TYPE = ActiveDirectoryGroupType()
|
||||||
|
|
||||||
|
# Group DN required to login. If specified, user must be a member of this
|
||||||
|
# group to login via LDAP.
|
||||||
|
#AUTH_LDAP_REQUIRE_GROUP = ''
|
||||||
|
|
||||||
|
# Group DN denied from login. If specified, user will not be allowed to login
|
||||||
|
# if a member of this group.
|
||||||
|
#AUTH_LDAP_DENY_GROUP = ''
|
||||||
|
|
||||||
|
# User profile flags updated from group membership (key is user attribute name,
|
||||||
|
# value is group DN).
|
||||||
|
AUTH_LDAP_USER_FLAGS_BY_GROUP = {
|
||||||
|
#'is_superuser': 'CN=Domain Admins,CN=Users,DC=example,DC=com',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Mapping between organization admins/users and LDAP groups. Keys are
|
||||||
|
# organization names (will be created if not present). Values are dictionaries
|
||||||
|
# of options for each organization's membership, where each can contain the
|
||||||
|
# following parameters:
|
||||||
|
# - remove: True/False. Defaults to False. Specifies the default for
|
||||||
|
# remove_admins or remove_users if those parameters aren't explicitly set.
|
||||||
|
# - admins: None, True/False, string or list/tuple of strings.
|
||||||
|
# If None, organization admins will not be updated.
|
||||||
|
# If True/False, all LDAP users will be added/removed as admins.
|
||||||
|
# If a string or list of strings, specifies the group DN(s). User will be
|
||||||
|
# added as an org admin if the user is a member of ANY of these groups.
|
||||||
|
# - remove_admins: True/False. Defaults to False. If True, a user who is not a
|
||||||
|
# member of the given groups will be removed from the organization's admins.
|
||||||
|
# - users: None, True/False, string or list/tuple of strings. Same rules apply
|
||||||
|
# as for admins.
|
||||||
|
# - remove_users: True/False. Defaults to False. If True, a user who is not a
|
||||||
|
# member of the given groups will be removed from the organization's users.
|
||||||
|
AUTH_LDAP_ORGANIZATION_MAP = {
|
||||||
|
#'Test Org': {
|
||||||
|
# 'admins': 'CN=Domain Admins,CN=Users,DC=example,DC=com',
|
||||||
|
# 'users': ['CN=Domain Users,CN=Users,DC=example,DC=com'],
|
||||||
|
#},
|
||||||
|
#'Test Org 2': {
|
||||||
|
# 'admins': ['CN=Administrators,CN=Builtin,DC=example,DC=com'],
|
||||||
|
# 'users': True,
|
||||||
|
#},
|
||||||
|
}
|
||||||
|
|
||||||
|
# Mapping between team members (users) and LDAP groups. Keys are team names
|
||||||
|
# (will be created if not present). Values are dictionaries of options for
|
||||||
|
# each team's membership, where each can contain the following parameters:
|
||||||
|
# - organization: string. The name of the organization to which the team
|
||||||
|
# belongs. The team will be created if the combination of organization and
|
||||||
|
# team name does not exist. The organization will first be created if it
|
||||||
|
# does not exist.
|
||||||
|
# - users: None, True/False, string or list/tuple of strings.
|
||||||
|
# If None, team members will not be updated.
|
||||||
|
# If True/False, all LDAP users will be added/removed as team members.
|
||||||
|
# If a string or list of strings, specifies the group DN(s). User will be
|
||||||
|
# added as a team member if the user is a member of ANY of these groups.
|
||||||
|
# - remove: True/False. Defaults to False. If True, a user who is not a member
|
||||||
|
# of the given groups will be removed from the team.
|
||||||
|
AUTH_LDAP_TEAM_MAP = {
|
||||||
|
'My Team': {
|
||||||
|
'organization': 'Test Org',
|
||||||
|
'users': ['CN=Domain Users,CN=Users,DC=example,DC=com'],
|
||||||
|
'remove': True,
|
||||||
|
},
|
||||||
|
'Other Team': {
|
||||||
|
'organization': 'Test Org 2',
|
||||||
|
'users': 'CN=Other Users,CN=Users,DC=example,DC=com',
|
||||||
|
'remove': False,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# SCM TEST SETTINGS
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
# Define these variables to enable more complete testing of project support for
|
||||||
|
# SCM updates. The test repositories listed do not have to contain any valid
|
||||||
|
# playbooks.
|
||||||
|
|
||||||
|
try:
|
||||||
|
path = os.path.expanduser(os.path.expandvars('~/.ssh/id_rsa'))
|
||||||
|
TEST_SSH_KEY_DATA = file(path, 'rb').read()
|
||||||
|
except IOError:
|
||||||
|
TEST_SSH_KEY_DATA = ''
|
||||||
|
|
||||||
|
TEST_GIT_USERNAME = ''
|
||||||
|
TEST_GIT_PASSWORD = ''
|
||||||
|
TEST_GIT_KEY_DATA = TEST_SSH_KEY_DATA
|
||||||
|
TEST_GIT_PUBLIC_HTTPS = 'https://github.com/ansible/ansible.github.com.git'
|
||||||
|
TEST_GIT_PRIVATE_HTTPS = 'https://github.com/ansible/product-docs.git'
|
||||||
|
TEST_GIT_PRIVATE_SSH = 'git@github.com:ansible/product-docs.git'
|
||||||
|
|
||||||
|
TEST_HG_USERNAME = ''
|
||||||
|
TEST_HG_PASSWORD = ''
|
||||||
|
TEST_HG_KEY_DATA = TEST_SSH_KEY_DATA
|
||||||
|
TEST_HG_PUBLIC_HTTPS = 'https://bitbucket.org/cchurch/django-hotrunner'
|
||||||
|
TEST_HG_PRIVATE_HTTPS = ''
|
||||||
|
TEST_HG_PRIVATE_SSH = ''
|
||||||
|
|
||||||
|
TEST_SVN_USERNAME = ''
|
||||||
|
TEST_SVN_PASSWORD = ''
|
||||||
|
TEST_SVN_PUBLIC_HTTPS = 'https://github.com/ansible/ansible.github.com'
|
||||||
|
TEST_SVN_PRIVATE_HTTPS = 'https://github.com/ansible/product-docs'
|
||||||
|
|
||||||
|
# To test repo access via SSH login to localhost.
|
||||||
|
import getpass
|
||||||
|
TEST_SSH_LOOPBACK_USERNAME = getpass.getuser()
|
||||||
|
TEST_SSH_LOOPBACK_PASSWORD = ''
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# LDAP TEST SETTINGS
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
# LDAP connection and authentication settings for unit tests only. LDAP tests
|
||||||
|
# will be skipped if TEST_AUTH_LDAP_SERVER_URI is not configured.
|
||||||
|
|
||||||
|
TEST_AUTH_LDAP_SERVER_URI = ''
|
||||||
|
TEST_AUTH_LDAP_BIND_DN = ''
|
||||||
|
TEST_AUTH_LDAP_BIND_PASSWORD = ''
|
||||||
|
TEST_AUTH_LDAP_START_TLS = False
|
||||||
|
|
||||||
|
# LDAP username/password for testing authentication.
|
||||||
|
TEST_AUTH_LDAP_USERNAME = ''
|
||||||
|
TEST_AUTH_LDAP_PASSWORD = ''
|
||||||
|
|
||||||
|
# LDAP search query to find users.
|
||||||
|
TEST_AUTH_LDAP_USER_SEARCH = LDAPSearch(
|
||||||
|
'CN=Users,DC=example,DC=com',
|
||||||
|
ldap.SCOPE_SUBTREE,
|
||||||
|
'(sAMAccountName=%(user)s)',
|
||||||
|
)
|
||||||
|
|
||||||
|
# Alternative to user search.
|
||||||
|
#TEST_AUTH_LDAP_USER_DN_TEMPLATE = 'sAMAccountName=%(user)s,OU=Users,DC=example,DC=com'
|
||||||
|
|
||||||
|
# Mapping of LDAP attributes to user attributes.
|
||||||
|
TEST_AUTH_LDAP_USER_ATTR_MAP = {
|
||||||
|
'first_name': 'givenName',
|
||||||
|
'last_name': 'sn',
|
||||||
|
'email': 'mail',
|
||||||
|
}
|
||||||
|
|
||||||
|
# LDAP search query for finding groups.
|
||||||
|
TEST_AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
|
||||||
|
'DC=example,DC=com',
|
||||||
|
ldap.SCOPE_SUBTREE,
|
||||||
|
'(objectClass=group)',
|
||||||
|
)
|
||||||
|
# Type of group returned by the search above.
|
||||||
|
TEST_AUTH_LDAP_GROUP_TYPE = ActiveDirectoryGroupType()
|
||||||
|
|
||||||
|
# Test DNs for a group required to login. User should be a member of the first
|
||||||
|
# group, but not a member of the second.
|
||||||
|
TEST_AUTH_LDAP_REQUIRE_GROUP = 'CN=Domain Admins,CN=Users,DC=example,DC=com'
|
||||||
|
TEST_AUTH_LDAP_REQUIRE_GROUP_FAIL = 'CN=Guest,CN=Users,DC=example,DC=com'
|
||||||
|
|
||||||
|
# Test DNs for a group denied from login. User should not be a member of the
|
||||||
|
# first group, but should be a member of the second.
|
||||||
|
TEST_AUTH_LDAP_DENY_GROUP = 'CN=Guest,CN=Users,DC=example,DC=com'
|
||||||
|
TEST_AUTH_LDAP_DENY_GROUP_FAIL = 'CN=Domain Admins,CN=Users,DC=example,DC=com'
|
||||||
|
|
||||||
|
# User profile flags updated from group membership. Test user should be a
|
||||||
|
# member of the group.
|
||||||
|
TEST_AUTH_LDAP_USER_FLAGS_BY_GROUP = {
|
||||||
|
'is_superuser': 'CN=Domain Admins,CN=Users,DC=example,DC=com',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test mapping between organization admins/users and LDAP groups.
|
||||||
|
TEST_AUTH_LDAP_ORGANIZATION_MAP = {
|
||||||
|
'Test Org': {
|
||||||
|
'admins': 'CN=Domain Admins,CN=Users,DC=example,DC=com',
|
||||||
|
'users': ['CN=Domain Users,CN=Users,DC=example,DC=com'],
|
||||||
|
},
|
||||||
|
'Test Org 2': {
|
||||||
|
'admins': ['CN=Administrators,CN=Builtin,DC=example,DC=com'],
|
||||||
|
'users': True,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
# Expected results from organization mapping. After login, should user be an
|
||||||
|
# admin/user in the given organization?
|
||||||
|
TEST_AUTH_LDAP_ORGANIZATION_MAP_RESULT = {
|
||||||
|
'Test Org': {'admins': True, 'users': False},
|
||||||
|
'Test Org 2': {'admins': False, 'users': True},
|
||||||
|
}
|
||||||
|
|
||||||
|
# Second test mapping to test remove parameters.
|
||||||
|
TEST_AUTH_LDAP_ORGANIZATION_MAP_2 = {
|
||||||
|
'Test Org': {
|
||||||
|
'admins': 'CN=Domain Users,CN=Users,DC=example,DC=com',
|
||||||
|
'users': True,
|
||||||
|
'remove_admins': True,
|
||||||
|
'remove_users': False,
|
||||||
|
},
|
||||||
|
'Test Org 2': {
|
||||||
|
'admins': ['CN=Domain Admins,CN=Users,DC=example,DC=com',
|
||||||
|
'CN=Administrators,CN=Builtin,DC=example,DC=com'],
|
||||||
|
'users': False,
|
||||||
|
'remove': True,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
# Expected results from second organization mapping.
|
||||||
|
TEST_AUTH_LDAP_ORGANIZATION_MAP_2_RESULT = {
|
||||||
|
'Test Org': {'admins': False, 'users': True},
|
||||||
|
'Test Org 2': {'admins': True, 'users': False},
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test mapping between team users and LDAP groups.
|
||||||
|
TEST_AUTH_LDAP_TEAM_MAP = {
|
||||||
|
'Domain Users Team': {
|
||||||
|
'organization': 'Test Org',
|
||||||
|
'users': ['CN=Domain Users,CN=Users,DC=example,DC=com'],
|
||||||
|
'remove': False,
|
||||||
|
},
|
||||||
|
'Admins Team': {
|
||||||
|
'organization': 'Admins Org',
|
||||||
|
'users': 'CN=Domain Admins,CN=Users,DC=example,DC=com',
|
||||||
|
'remove': True,
|
||||||
|
},
|
||||||
|
'Everyone Team': {
|
||||||
|
'organization': 'Test Org 2',
|
||||||
|
'users': True,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
# Expected results from team mapping. After login, should user be a member of
|
||||||
|
# the given team?
|
||||||
|
TEST_AUTH_LDAP_TEAM_MAP_RESULT = {
|
||||||
|
'Domain Users Team': {'users': False},
|
||||||
|
'Admins Team': {'users': True},
|
||||||
|
'Everyone Team': {'users': True},
|
||||||
|
}
|
||||||
|
|
||||||
|
# Second test mapping for teams to remove user.
|
||||||
|
TEST_AUTH_LDAP_TEAM_MAP_2 = {
|
||||||
|
'Domain Users Team': {
|
||||||
|
'organization': 'Test Org',
|
||||||
|
'users': ['CN=Domain Users,CN=Users,DC=example,DC=com'],
|
||||||
|
'remove': False,
|
||||||
|
},
|
||||||
|
'Admins Team': {
|
||||||
|
'organization': 'Admins Org',
|
||||||
|
'users': 'CN=Administrators,CN=Builtin,DC=example,DC=com',
|
||||||
|
'remove': True,
|
||||||
|
},
|
||||||
|
'Everyone Team': {
|
||||||
|
'organization': 'Test Org 2',
|
||||||
|
'users': False,
|
||||||
|
'remove': False,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
# Expected results from second team mapping. After login, should user be a
|
||||||
|
# member of the given team?
|
||||||
|
TEST_AUTH_LDAP_TEAM_MAP_2_RESULT = {
|
||||||
|
'Domain Users Team': {'users': False},
|
||||||
|
'Admins Team': {'users': False},
|
||||||
|
'Everyone Team': {'users': True},
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# INVENTORY IMPORT TEST SETTINGS
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
# Define these variables to enable more complete testing of inventory import
|
||||||
|
# from cloud providers.
|
||||||
|
|
||||||
|
# EC2 credentials
|
||||||
|
TEST_AWS_ACCESS_KEY_ID = ''
|
||||||
|
TEST_AWS_SECRET_ACCESS_KEY = ''
|
||||||
|
TEST_AWS_REGIONS = 'all'
|
||||||
|
# Check IAM STS credentials
|
||||||
|
TEST_AWS_SECURITY_TOKEN = ''
|
||||||
|
|
||||||
|
# Rackspace credentials
|
||||||
|
TEST_RACKSPACE_USERNAME = ''
|
||||||
|
TEST_RACKSPACE_API_KEY = ''
|
||||||
|
TEST_RACKSPACE_REGIONS = 'all'
|
||||||
|
|
||||||
|
# VMware credentials
|
||||||
|
TEST_VMWARE_HOST = ''
|
||||||
|
TEST_VMWARE_USER = ''
|
||||||
|
TEST_VMWARE_PASSWORD = ''
|
||||||
|
|
||||||
|
# OpenStack credentials
|
||||||
|
TEST_OPENSTACK_HOST = ''
|
||||||
|
TEST_OPENSTACK_USER = ''
|
||||||
|
TEST_OPENSTACK_PASSWORD = ''
|
||||||
|
TEST_OPENSTACK_PROJECT = ''
|
||||||
|
|
||||||
|
# Azure credentials.
|
||||||
|
TEST_AZURE_USERNAME = ''
|
||||||
|
TEST_AZURE_KEY_DATA = ''
|
||||||
@@ -481,6 +481,9 @@ TEST_AUTH_LDAP_TEAM_MAP_2_RESULT = {
|
|||||||
TEST_AWS_ACCESS_KEY_ID = ''
|
TEST_AWS_ACCESS_KEY_ID = ''
|
||||||
TEST_AWS_SECRET_ACCESS_KEY = ''
|
TEST_AWS_SECRET_ACCESS_KEY = ''
|
||||||
TEST_AWS_REGIONS = 'all'
|
TEST_AWS_REGIONS = 'all'
|
||||||
|
# Check IAM STS credentials
|
||||||
|
TEST_AWS_SECURITY_TOKEN = ''
|
||||||
|
|
||||||
|
|
||||||
# Rackspace credentials
|
# Rackspace credentials
|
||||||
TEST_RACKSPACE_USERNAME = ''
|
TEST_RACKSPACE_USERNAME = ''
|
||||||
|
|||||||
Reference in New Issue
Block a user