mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 10:00:01 -03:30
Working on surfacing inventory objects.
This commit is contained in:
parent
036458b823
commit
77695bd959
2
TODO.md
2
TODO.md
@ -28,4 +28,4 @@ TWEAKS/ASSORTED
|
||||
* allow multiple playbook execution types per project, different --tag choices, different --limit choices (maybe just free form in the job for now?)
|
||||
* permissions infrastructure about who can kick off what kind of jobs
|
||||
* it would be nice if POSTs to subcollections used the permissions of the regular collection POST rules and then called the PUT code.
|
||||
|
||||
* root API discovery resource at /api and /api/v1
|
||||
|
||||
252
lib/main/migrations/0008_changes.py
Normal file
252
lib/main/migrations/0008_changes.py
Normal file
@ -0,0 +1,252 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Deleting field 'Permission.job_type'
|
||||
db.delete_column(u'main_permission', 'job_type')
|
||||
|
||||
# Adding field 'Permission.inventory'
|
||||
db.add_column(u'main_permission', 'inventory',
|
||||
self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='permissions', null=True, on_delete=models.SET_NULL, to=orm['main.Inventory']),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Permission.permission_type'
|
||||
db.add_column(u'main_permission', 'permission_type',
|
||||
self.gf('django.db.models.fields.CharField')(default='run', max_length=64),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Adding field 'Permission.job_type'
|
||||
db.add_column(u'main_permission', 'job_type',
|
||||
self.gf('django.db.models.fields.CharField')(default='run', max_length=64),
|
||||
keep_default=False)
|
||||
|
||||
# Deleting field 'Permission.inventory'
|
||||
db.delete_column(u'main_permission', 'inventory_id')
|
||||
|
||||
# Deleting field 'Permission.permission_type'
|
||||
db.delete_column(u'main_permission', 'permission_type')
|
||||
|
||||
|
||||
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', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
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', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'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.audittrail': {
|
||||
'Meta': {'object_name': 'AuditTrail'},
|
||||
'comment': ('django.db.models.fields.TextField', [], {}),
|
||||
'delta': ('django.db.models.fields.TextField', [], {}),
|
||||
'detail': ('django.db.models.fields.TextField', [], {}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
|
||||
'resource_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
|
||||
'tag': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Tag']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'})
|
||||
},
|
||||
'main.credential': {
|
||||
'Meta': {'object_name': 'Credential'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'credential_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'credential\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'creation_date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
|
||||
'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'credentials'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': u"orm['main.Project']", 'blank': 'True', 'null': 'True'}),
|
||||
'ssh_key_data': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'ssh_key_path': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '4096', 'blank': 'True'}),
|
||||
'ssh_key_unlock': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'ssh_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'sudo_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'credential_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"}),
|
||||
'team': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'credentials'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Team']", 'blank': 'True', 'null': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'credentials'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': u"orm['auth.User']", 'blank': 'True', 'null': 'True'})
|
||||
},
|
||||
'main.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'group_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'group\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'creation_date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'groups'", 'blank': 'True', 'to': "orm['main.Host']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'groups'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
|
||||
'parents': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'children'", 'blank': 'True', 'to': "orm['main.Group']"}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'group_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"})
|
||||
},
|
||||
'main.host': {
|
||||
'Meta': {'object_name': 'Host'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'host_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'host\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'creation_date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'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': "'hosts'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'host_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"})
|
||||
},
|
||||
'main.inventory': {
|
||||
'Meta': {'object_name': 'Inventory'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'inventory_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'inventory\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'creation_date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
|
||||
'organization': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventories'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Organization']"}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'inventory_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"})
|
||||
},
|
||||
'main.launchjob': {
|
||||
'Meta': {'object_name': 'LaunchJob'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'launchjob_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'launchjob\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'creation_date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'launch_jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}),
|
||||
'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': "'launch_jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Inventory']", 'blank': 'True', 'null': 'True'}),
|
||||
'job_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
|
||||
'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'launch_jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': u"orm['main.Project']", 'blank': 'True', 'null': 'True'}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'launchjob_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'launch_jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': u"orm['auth.User']", 'blank': 'True', 'null': 'True'})
|
||||
},
|
||||
'main.launchjobstatus': {
|
||||
'Meta': {'object_name': 'LaunchJobStatus'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'launchjobstatus_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'launchjobstatus\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'creation_date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'launch_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'launch_job_statuses'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.LaunchJob']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
|
||||
'result_data': ('django.db.models.fields.TextField', [], {}),
|
||||
'status': ('django.db.models.fields.IntegerField', [], {}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'launchjobstatus_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"})
|
||||
},
|
||||
'main.organization': {
|
||||
'Meta': {'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']"}),
|
||||
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organization_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'organization\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'creation_date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'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': u"orm['main.Project']"}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organization_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"}),
|
||||
'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'}),
|
||||
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'permission_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'permission\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'creation_date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'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', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', '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': u"orm['main.Project']"}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'permission_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"}),
|
||||
'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']"})
|
||||
},
|
||||
u'main.project': {
|
||||
'Meta': {'object_name': 'Project'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'project_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'project\', \'app_label\': u\'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'creation_date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'default_playbook': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'inventories': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'projects'", 'blank': 'True', 'to': "orm['main.Inventory']"}),
|
||||
'local_repository': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
|
||||
'scm_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'project_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"})
|
||||
},
|
||||
'main.tag': {
|
||||
'Meta': {'object_name': 'Tag'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '512'})
|
||||
},
|
||||
'main.team': {
|
||||
'Meta': {'object_name': 'Team'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'team_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'team\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'creation_date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
|
||||
'organizations': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'teams'", 'symmetrical': 'False', 'to': "orm['main.Organization']"}),
|
||||
'projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'teams'", 'blank': 'True', 'to': u"orm['main.Project']"}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'team_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"}),
|
||||
'users': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'teams'", 'blank': 'True', 'to': u"orm['auth.User']"})
|
||||
},
|
||||
'main.variabledata': {
|
||||
'Meta': {'object_name': 'VariableData'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'variabledata_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'variabledata\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||
'creation_date': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'data': ('django.db.models.fields.TextField', [], {}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||
'group': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'variable_data'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Group']"}),
|
||||
'host': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'variable_data'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Host']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'variabledata_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['main']
|
||||
@ -26,9 +26,30 @@ import exceptions
|
||||
# TODO: jobs and events model TBD
|
||||
# TODO: reporting model TBD
|
||||
|
||||
PERM_INVENTORY_READ = 'read'
|
||||
PERM_INVENTORY_WRITE = 'write'
|
||||
PERM_INVENTORY_DEPLOY = 'run'
|
||||
PERM_INVENTORY_CHECK = 'check'
|
||||
|
||||
JOB_TYPE_CHOICES = [
|
||||
('run', _('Run')),
|
||||
('check', _('Check')),
|
||||
(PERM_INVENTORY_DEPLOY, _('Run')),
|
||||
(PERM_INVENTORY_CHECK, _('Check')),
|
||||
]
|
||||
|
||||
PERMISSION_TYPES = [
|
||||
PERM_INVENTORY_READ,
|
||||
PERM_INVENTORY_WRITE,
|
||||
PERM_INVENTORY_DEPLOY,
|
||||
PERM_INVENTORY_CHECK,
|
||||
]
|
||||
|
||||
PERMISSION_TYPES_ALLOWING_INVENTORY_READ = PERMISSION_TYPES
|
||||
|
||||
PERMISSION_TYPE_CHOICES = [
|
||||
(PERM_INVENTORY_READ, _('Read Inventory')),
|
||||
(PERM_INVENTORY_WRITE, _('Write Inventory')),
|
||||
(PERM_INVENTORY_DEPLOY, _('Deploy To Inventory')),
|
||||
(PERM_INVENTORY_CHECK, _('Deploy To Inventory (Dry Run)')),
|
||||
]
|
||||
|
||||
class EditHelper(object):
|
||||
@ -231,6 +252,10 @@ class Inventory(CommonModel):
|
||||
verbose_name_plural = _('inventories')
|
||||
|
||||
organization = models.ForeignKey(Organization, null=True, on_delete=SET_NULL, related_name='inventories')
|
||||
|
||||
def get_absolute_url(self):
|
||||
import lib.urls
|
||||
return reverse(lib.urls.views_InventoryDetail, args=(self.pk,))
|
||||
|
||||
def __unicode__(self):
|
||||
if self.organization:
|
||||
@ -364,7 +389,8 @@ class Permission(CommonModel):
|
||||
user = models.ForeignKey('auth.User', null=True, on_delete=SET_NULL, blank=True, related_name='permissions')
|
||||
project = models.ForeignKey('Project', null=True, on_delete=SET_NULL, blank=True, related_name='permissions')
|
||||
team = models.ForeignKey('Team', null=True, on_delete=SET_NULL, blank=True, related_name='permissions')
|
||||
job_type = models.CharField(max_length=64, choices=JOB_TYPE_CHOICES)
|
||||
inventory = models.ForeignKey('Inventory', null=True, on_delete=SET_NULL, blank=True, related_name='permissions')
|
||||
permission_type = models.CharField(max_length=64, choices=PERMISSION_TYPE_CHOICES)
|
||||
|
||||
# TODO: other job types (later)
|
||||
|
||||
@ -380,6 +406,8 @@ class LaunchJob(CommonModel):
|
||||
credential = models.ForeignKey('Credential', on_delete=SET_NULL, null=True, default=None, blank=True, related_name='launch_jobs')
|
||||
project = models.ForeignKey('Project', on_delete=SET_NULL, null=True, default=None, blank=True, related_name='launch_jobs')
|
||||
user = models.ForeignKey('auth.User', on_delete=SET_NULL, null=True, default=None, blank=True, related_name='launch_jobs')
|
||||
|
||||
# JOB_TYPE_CHOICES are a subset of PERMISSION_TYPE_CHOICES
|
||||
job_type = models.CharField(max_length=64, choices=JOB_TYPE_CHOICES)
|
||||
|
||||
def start(self):
|
||||
|
||||
@ -78,6 +78,22 @@ class ProjectSerializer(BaseSerializer):
|
||||
# FIXME: add related resources: inventories
|
||||
return dict()
|
||||
|
||||
|
||||
class InventorySerializer(BaseSerializer):
|
||||
|
||||
# add the URL and related resources
|
||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||
related = serializers.SerializerMethodField('get_related')
|
||||
|
||||
class Meta:
|
||||
model = Inventory
|
||||
fields = ('url', 'id', 'name', 'description', 'creation_date')
|
||||
|
||||
def get_related(self, obj):
|
||||
# FIXME: add related resources: inventories
|
||||
return dict()
|
||||
|
||||
|
||||
class TeamSerializer(BaseSerializer):
|
||||
|
||||
# add the URL and related resources
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
from lib.main.tests.organizations import OrganizationsTest
|
||||
from lib.main.tests.users import UsersTest
|
||||
|
||||
from lib.main.tests.inventory import InventoryTest
|
||||
|
||||
|
||||
@ -17,17 +17,65 @@ from lib.main.tests.base import BaseTest
|
||||
class InventoryTest(BaseTest):
|
||||
|
||||
def setUp(self):
|
||||
super(UsersTest, self).setUp()
|
||||
super(InventoryTest, self).setUp()
|
||||
self.setup_users()
|
||||
self.organizations = self.make_organizations(self.super_django_user, 1)
|
||||
self.organizations[0].admins.add(self.normal_django_user)
|
||||
self.organizations[0].users.add(self.other_django_user)
|
||||
self.organizations[0].users.add(self.normal_django_user)
|
||||
|
||||
self.inventory_a = Inventory.objects.create(name='inventory-a', description='foo', organization=self.organizations[0])
|
||||
self.inventory_b = Inventory.objects.create(name='inventory-b', description='foo', organization=self.organizations[0])
|
||||
|
||||
# the normal user is an org admin of org 0
|
||||
|
||||
# create a permission here on the 'other' user so they have edit access on the org
|
||||
# TODO
|
||||
|
||||
# and make one more user that won't be a part of any org, just for negative-access testing
|
||||
|
||||
self.nobody_django_user = User.objects.create(username='nobody', password='nobody')
|
||||
|
||||
def get_nobody_credentials(self):
|
||||
# here is a user without any permissions...
|
||||
return ('nobody', 'nobody')
|
||||
|
||||
def test_main_line(self):
|
||||
|
||||
#url = '/api/v1/users/'
|
||||
#new_user = dict(username='blippy')
|
||||
|
||||
# some basic URLs...
|
||||
inventories = '/api/v1/inventories/'
|
||||
inventories_1 = '/api/v1/inventories/1/'
|
||||
inventories_2 = '/api/v1/inventories/2/'
|
||||
hosts = '/api/v1/hosts/'
|
||||
groups = '/api/v1/groups/'
|
||||
variables = '/api/v1/variables/'
|
||||
|
||||
# a super user can list inventories
|
||||
data = self.get(inventories, expect=200, auth=self.get_super_credentials())
|
||||
print data
|
||||
self.assertEquals(data['count'], 2)
|
||||
|
||||
# an org admin can list inventories but is filtered to what he adminsters
|
||||
data = self.get(inventories, expect=200, auth=self.get_normal_credentials())
|
||||
self.assertEquals(data['count'], 1)
|
||||
|
||||
# a user who is on a team who has a read permissions on an inventory can see filtered inventories
|
||||
data = self.get(inventories, expect=200, auth=self.get_other_credentials())
|
||||
self.assertEquals(data['count'], 0)
|
||||
|
||||
# a regular user not part of anything cannot see any inventories
|
||||
data = self.get(inventories, expect=200, auth=self.get_nobody_credentials())
|
||||
self.assertEquals(data['count'], 0)
|
||||
|
||||
# a super user can get inventory records
|
||||
data = self.get(detail_url_1, expect=200, auth=self.get_super_credentials())
|
||||
self.assertEquals(data['name'], 'inventory-a')
|
||||
|
||||
# a user who is on a team who has read permissions on an inventory can see inventory records
|
||||
|
||||
# a regular user cannot read any inventory records
|
||||
|
||||
|
||||
#new_user2 = dict(username='blippy2')
|
||||
|
||||
# a super user can create inventory
|
||||
@ -103,22 +151,6 @@ class InventoryTest(BaseTest):
|
||||
|
||||
# a normal user with inventory edit permissions can associate subgroups
|
||||
|
||||
# a super user can list inventories
|
||||
|
||||
# an org admin can list inventories
|
||||
|
||||
# a user who is on a team who has a read permissions on an inventory can see filtered inventories
|
||||
|
||||
# a regular user not part of anything cannot see any inventories
|
||||
|
||||
# a super user can get inventory records
|
||||
|
||||
# an org admin can get inventory records
|
||||
|
||||
# a user who is on a team who has read permissions on an inventory can see inventory records
|
||||
|
||||
# a regular user cannot read any inventory records
|
||||
|
||||
# a super user can get a group record
|
||||
|
||||
# an org admin can get a group record
|
||||
@ -231,9 +263,16 @@ class InventoryTest(BaseTest):
|
||||
|
||||
# variable records
|
||||
|
||||
# on an inventory resource, I can see related resources for hosts and groups and permissions
|
||||
# and these work
|
||||
|
||||
# on a host resource, I can see related resources variables and inventories
|
||||
# and these work
|
||||
|
||||
# on a group resource, I can see related resources for variables, inventories, and children
|
||||
# and these work
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -352,4 +352,5 @@ class OrganizationsTest(BaseTest):
|
||||
# also check that DELETE on the collection doesn't work
|
||||
self.delete(self.collection(), expect=405, auth=self.get_super_credentials())
|
||||
|
||||
# TODO: tests for tag disassociation
|
||||
|
||||
|
||||
@ -253,4 +253,30 @@ class UsersDetail(BaseDetail):
|
||||
obj.set_password(request.DATA['password'])
|
||||
obj.save()
|
||||
request.DATA.pop('password')
|
||||
|
||||
class InventoryList(BaseList):
|
||||
|
||||
model = Inventory
|
||||
serializer_class = InventorySerializer
|
||||
permission_classes = (CustomRbac,)
|
||||
|
||||
def _get_queryset(self):
|
||||
''' I can see inventory when I'm a superuser, an org admin of the inventory, or I have permissions on it '''
|
||||
base = Inventory.objects
|
||||
if self.request.user.is_superuser:
|
||||
return base.all()
|
||||
admin_of = base.filter(organization__admins__in = [ self.request.user ]).distinct()
|
||||
has_perms = base.filter(
|
||||
permissions__user__in = [ self.request.user ],
|
||||
permissions__permission_type__in = PERMISSION_TYPES_ALLOWING_INVENTORY_READ,
|
||||
).distinct()
|
||||
return admin_of | has_perms
|
||||
|
||||
class InventoryDetail(BaseDetail):
|
||||
|
||||
model = Inventory
|
||||
serializer_class = InventorySerializer
|
||||
permission_classes = (CustomRbac,)
|
||||
|
||||
|
||||
|
||||
|
||||
24
lib/urls.py
24
lib/urls.py
@ -36,16 +36,16 @@ views_UsersTeamsList = views.UsersTeamsList.as_view()
|
||||
views_UsersOrganizationsList = views.UsersOrganizationsList.as_view()
|
||||
views_UsersAdminOrganizationsList = views.UsersAdminOrganizationsList.as_view()
|
||||
|
||||
|
||||
|
||||
# projects service
|
||||
views_ProjectsDetail = views.OrganizationsDetail.as_view()
|
||||
views_ProjectsDetail = views.OrganizationsDetail.as_view()
|
||||
|
||||
# audit trail service
|
||||
|
||||
# team service
|
||||
|
||||
# inventory service
|
||||
views_InventoryList = views.InventoryList.as_view()
|
||||
views_InventoryDetail = views.InventoryDetail.as_view()
|
||||
|
||||
# group service
|
||||
|
||||
@ -65,13 +65,13 @@ views_TagsDetail = views.TagsDetail.as_view()
|
||||
|
||||
urlpatterns = patterns('',
|
||||
# organizations service
|
||||
url(r'^api/v1/organizations/$', views_OrganizationsList),
|
||||
url(r'^api/v1/organizations/(?P<pk>[0-9]+)/$', views_OrganizationsDetail),
|
||||
url(r'^api/v1/organizations/(?P<pk>[0-9]+)/audit_trail/$', views_OrganizationsAuditTrailList),
|
||||
url(r'^api/v1/organizations/(?P<pk>[0-9]+)/users/$', views_OrganizationsUsersList),
|
||||
url(r'^api/v1/organizations/(?P<pk>[0-9]+)/admins/$', views_OrganizationsAdminsList),
|
||||
url(r'^api/v1/organizations/(?P<pk>[0-9]+)/projects/$', views_OrganizationsProjectsList),
|
||||
url(r'^api/v1/organizations/(?P<pk>[0-9]+)/tags/$', views_OrganizationsTagsList),
|
||||
url(r'^api/v1/organizations/$', views_OrganizationsList),
|
||||
url(r'^api/v1/organizations/(?P<pk>[0-9]+)/$', views_OrganizationsDetail),
|
||||
url(r'^api/v1/organizations/(?P<pk>[0-9]+)/audit_trail/$', views_OrganizationsAuditTrailList),
|
||||
url(r'^api/v1/organizations/(?P<pk>[0-9]+)/users/$', views_OrganizationsUsersList),
|
||||
url(r'^api/v1/organizations/(?P<pk>[0-9]+)/admins/$', views_OrganizationsAdminsList),
|
||||
url(r'^api/v1/organizations/(?P<pk>[0-9]+)/projects/$', views_OrganizationsProjectsList),
|
||||
url(r'^api/v1/organizations/(?P<pk>[0-9]+)/tags/$', views_OrganizationsTagsList),
|
||||
|
||||
# users service
|
||||
url(r'^api/v1/users/$', views_UsersList),
|
||||
@ -82,13 +82,15 @@ urlpatterns = patterns('',
|
||||
url(r'^api/v1/users/(?P<pk>[0-9]+)/admin_of_organizations/$', views_UsersAdminOrganizationsList),
|
||||
|
||||
# projects service
|
||||
url(r'^api/v1/projects/(?P<pk>[0-9]+)/$', views_ProjectsDetail),
|
||||
url(r'^api/v1/projects/(?P<pk>[0-9]+)/$', views_ProjectsDetail),
|
||||
|
||||
# audit trail service
|
||||
|
||||
# team service
|
||||
|
||||
# inventory service
|
||||
url(r'^api/v1/inventories/$', views_InventoryList),
|
||||
url(r'^api/v1/inventories/(?P<pk>[0-9]+)/$', views_InventoryDetail),
|
||||
|
||||
# group service
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user