mirror of
https://github.com/ansible/awx.git
synced 2026-05-19 14:57:39 -02:30
Merge branch 'master' into expunge-zeromq-unstable
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -52,6 +52,7 @@ tools/vagrant/local.yml
|
|||||||
# Setup
|
# Setup
|
||||||
setup/tower_setup_conf.yml
|
setup/tower_setup_conf.yml
|
||||||
setup/setup.log
|
setup/setup.log
|
||||||
|
setup/inventory
|
||||||
|
|
||||||
# Other
|
# Other
|
||||||
.tower_cycle
|
.tower_cycle
|
||||||
|
|||||||
@@ -109,6 +109,8 @@ class ApiV1RootView(APIView):
|
|||||||
data['hosts'] = reverse('api:host_list')
|
data['hosts'] = reverse('api:host_list')
|
||||||
data['job_templates'] = reverse('api:job_template_list')
|
data['job_templates'] = reverse('api:job_template_list')
|
||||||
data['jobs'] = reverse('api:job_list')
|
data['jobs'] = reverse('api:job_list')
|
||||||
|
data['system_job_templates'] = reverse('api:system_job_template_list')
|
||||||
|
data['system_jobs'] = reverse('api:system_job_list')
|
||||||
data['schedules'] = reverse('api:schedule_list')
|
data['schedules'] = reverse('api:schedule_list')
|
||||||
data['unified_job_templates'] = reverse('api:unified_job_template_list')
|
data['unified_job_templates'] = reverse('api:unified_job_template_list')
|
||||||
data['unified_jobs'] = reverse('api:unified_job_list')
|
data['unified_jobs'] = reverse('api:unified_job_list')
|
||||||
@@ -1720,6 +1722,11 @@ class SystemJobTemplateList(ListAPIView):
|
|||||||
model = SystemJobTemplate
|
model = SystemJobTemplate
|
||||||
serializer_class = SystemJobTemplateSerializer
|
serializer_class = SystemJobTemplateSerializer
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
if not request.user.is_superuser:
|
||||||
|
return Response(status=status.HTTP_404_NOT_FOUND)
|
||||||
|
return super(SystemJobTemplateList, self).get(request, *args, **kwargs)
|
||||||
|
|
||||||
class SystemJobTemplateDetail(RetrieveAPIView):
|
class SystemJobTemplateDetail(RetrieveAPIView):
|
||||||
|
|
||||||
model = SystemJobTemplate
|
model = SystemJobTemplate
|
||||||
@@ -1738,7 +1745,7 @@ class SystemJobTemplateLaunch(GenericAPIView):
|
|||||||
raise PermissionDenied()
|
raise PermissionDenied()
|
||||||
new_job = obj.create_unified_job()
|
new_job = obj.create_unified_job()
|
||||||
result = new_job.signal_start()
|
result = new_job.signal_start()
|
||||||
data = dict(job=new_job.id)
|
data = dict(system_job=new_job.id)
|
||||||
return Response(data, status=status.HTTP_202_ACCEPTED)
|
return Response(data, status=status.HTTP_202_ACCEPTED)
|
||||||
|
|
||||||
class SystemJobTemplateSchedulesList(SubListCreateAPIView):
|
class SystemJobTemplateSchedulesList(SubListCreateAPIView):
|
||||||
@@ -2174,6 +2181,12 @@ class SystemJobList(ListCreateAPIView):
|
|||||||
model = SystemJob
|
model = SystemJob
|
||||||
serializer_class = SystemJobListSerializer
|
serializer_class = SystemJobListSerializer
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
if not request.user.is_superuser:
|
||||||
|
return Response(status=status.HTTP_404_NOT_FOUND)
|
||||||
|
return super(SystemJobList, self).get(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class SystemJobDetail(RetrieveAPIView):
|
class SystemJobDetail(RetrieveAPIView):
|
||||||
|
|
||||||
model = SystemJob
|
model = SystemJob
|
||||||
|
|||||||
@@ -980,6 +980,8 @@ class JobAccess(BaseAccess):
|
|||||||
def can_add(self, data):
|
def can_add(self, data):
|
||||||
if not data or '_method' in data: # So the browseable API will work?
|
if not data or '_method' in data: # So the browseable API will work?
|
||||||
return True
|
return True
|
||||||
|
if not self.user.is_superuser:
|
||||||
|
return False
|
||||||
|
|
||||||
reader = TaskSerializer()
|
reader = TaskSerializer()
|
||||||
validation_info = reader.from_file()
|
validation_info = reader.from_file()
|
||||||
@@ -995,8 +997,6 @@ class JobAccess(BaseAccess):
|
|||||||
if validation_info.get('free_instances', 0) < 0:
|
if validation_info.get('free_instances', 0) < 0:
|
||||||
raise PermissionDenied("Host Count exceeds available instances")
|
raise PermissionDenied("Host Count exceeds available instances")
|
||||||
|
|
||||||
if self.user.is_superuser:
|
|
||||||
return True
|
|
||||||
add_data = dict(data.items())
|
add_data = dict(data.items())
|
||||||
|
|
||||||
# If a job template is provided, the user should have read access to it.
|
# If a job template is provided, the user should have read access to it.
|
||||||
@@ -1012,9 +1012,6 @@ class JobAccess(BaseAccess):
|
|||||||
add_data.setdefault('credential', job_template.credential.pk)
|
add_data.setdefault('credential', job_template.credential.pk)
|
||||||
else:
|
else:
|
||||||
job_template = None
|
job_template = None
|
||||||
# Only admins can create jobs without job templates
|
|
||||||
if not self.user.is_superuser:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Check that the user would be able to add a job template with the
|
# Check that the user would be able to add a job template with the
|
||||||
# same data.
|
# same data.
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import logging
|
|||||||
import json
|
import json
|
||||||
import signal
|
import signal
|
||||||
import time
|
import time
|
||||||
|
import urllib
|
||||||
from optparse import make_option
|
from optparse import make_option
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
@@ -31,23 +32,71 @@ from socketio import socketio_manage
|
|||||||
from socketio.server import SocketIOServer
|
from socketio.server import SocketIOServer
|
||||||
from socketio.namespace import BaseNamespace
|
from socketio.namespace import BaseNamespace
|
||||||
|
|
||||||
class TestNamespace(BaseNamespace):
|
class TowerBaseNamespace(BaseNamespace):
|
||||||
|
|
||||||
|
def get_allowed_methods(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_initial_acl(self):
|
||||||
|
print self
|
||||||
|
if self.valid_user() is not None:
|
||||||
|
return set(['recv_connect'] + self.get_allowed_methods())
|
||||||
|
return set()
|
||||||
|
|
||||||
|
def valid_user(self):
|
||||||
|
if 'HTTP_COOKIE' not in self.environ:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
all_keys = [e.strip() for e in self.environ['HTTP_COOKIE'].split(";")]
|
||||||
|
for each_key in all_keys:
|
||||||
|
k, v = each_key.split("=")
|
||||||
|
if k == "token":
|
||||||
|
token_actual = urllib.unquote_plus(v).decode().replace("\"","")
|
||||||
|
auth_token = AuthToken.objects.filter(key=token_actual)
|
||||||
|
if not auth_token.exists():
|
||||||
|
return False
|
||||||
|
auth_token = auth_token[0]
|
||||||
|
if not auth_token.expired:
|
||||||
|
return auth_token.user
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
except Exception, e:
|
||||||
|
return False
|
||||||
|
|
||||||
|
class TestNamespace(TowerBaseNamespace):
|
||||||
|
|
||||||
def recv_connect(self):
|
def recv_connect(self):
|
||||||
print("Received client connect for test namespace from %s" % str(self.environ['REMOTE_ADDR']))
|
print("Received client connect for test namespace from %s" % str(self.environ['REMOTE_ADDR']))
|
||||||
self.emit('test', "If you see this then you are connected to the test socket endpoint")
|
self.emit('test', "If you see this then you are connected to the test socket endpoint")
|
||||||
|
|
||||||
class JobNamespace(BaseNamespace):
|
class JobNamespace(TowerBaseNamespace):
|
||||||
|
|
||||||
|
def get_allowed_methods(self):
|
||||||
|
return ['summary_complete', 'status_changed']
|
||||||
|
|
||||||
def recv_connect(self):
|
def recv_connect(self):
|
||||||
print("Received client connect for job namespace from %s" % str(self.environ['REMOTE_ADDR']))
|
print("Received client connect for job namespace from %s" % str(self.environ['REMOTE_ADDR']))
|
||||||
|
|
||||||
class JobEventNamespace(BaseNamespace):
|
class JobEventNamespace(TowerBaseNamespace):
|
||||||
|
|
||||||
|
def get_initial_acl(self):
|
||||||
|
valid_user = self.valid_user()
|
||||||
|
if valid_user is None or valid_user is False:
|
||||||
|
return set()
|
||||||
|
else:
|
||||||
|
user_jobs = get_user_queryset(valid_user, Job).filter(finished__isnull=True)
|
||||||
|
visible_jobs = set(['recv_connect'] + ["job_events-%s" % str(j.id) for j in user_jobs])
|
||||||
|
print("Visible jobs: " + str(visible_jobs))
|
||||||
|
return visible_jobs
|
||||||
|
|
||||||
def recv_connect(self):
|
def recv_connect(self):
|
||||||
print("Received client connect for job event namespace from %s" % str(self.environ['REMOTE_ADDR']))
|
print("Received client connect for job event namespace from %s" % str(self.environ['REMOTE_ADDR']))
|
||||||
|
|
||||||
class ScheduleNamespace(BaseNamespace):
|
class ScheduleNamespace(TowerBaseNamespace):
|
||||||
|
|
||||||
|
def get_allowed_methods(self):
|
||||||
|
return ["schedule_changed"]
|
||||||
|
|
||||||
def recv_connect(self):
|
def recv_connect(self):
|
||||||
print("Received client connect for schedule namespace from %s" % str(self.environ['REMOTE_ADDR']))
|
print("Received client connect for schedule namespace from %s" % str(self.environ['REMOTE_ADDR']))
|
||||||
|
|||||||
494
awx/main/migrations/0059_v210_changes.py
Normal file
494
awx/main/migrations/0059_v210_changes.py
Normal file
@@ -0,0 +1,494 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from south.utils import datetime_utils as datetime
|
||||||
|
from south.db import db
|
||||||
|
from south.v2 import DataMigration
|
||||||
|
from django.db import models
|
||||||
|
from django.utils.timezone import now
|
||||||
|
from awx.main.models import *
|
||||||
|
|
||||||
|
class Migration(DataMigration):
|
||||||
|
|
||||||
|
def forwards(self, orm):
|
||||||
|
SystemJobTemplate(name='Delete Old Jobs',
|
||||||
|
description="Run a job to delete jobs that are older than a given number of days",
|
||||||
|
job_type="cleanup_jobs",
|
||||||
|
created=now(),
|
||||||
|
modified=now()).save()
|
||||||
|
SystemJobTemplate(name='Cleanup Deleted Data',
|
||||||
|
description="Run a job to cleanup any deleted objects that are older than a given number of days",
|
||||||
|
job_type="cleanup_deleted",
|
||||||
|
created=now(),
|
||||||
|
modified=now()).save()
|
||||||
|
SystemJobTemplate(name='Cleanup Activity Stream',
|
||||||
|
description="Run a job to purge activity stream data that's older than a given number of days",
|
||||||
|
job_type="cleanup_activitystream",
|
||||||
|
created=now(),
|
||||||
|
modified=now()).save()
|
||||||
|
|
||||||
|
def backwards(self, orm):
|
||||||
|
orm.SystemJobTemplate.objects.all().delete()
|
||||||
|
|
||||||
|
models = {
|
||||||
|
u'auth.group': {
|
||||||
|
'Meta': {'object_name': 'Group'},
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||||
|
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||||
|
},
|
||||||
|
u'auth.permission': {
|
||||||
|
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
|
||||||
|
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||||
|
},
|
||||||
|
u'auth.user': {
|
||||||
|
'Meta': {'object_name': 'User'},
|
||||||
|
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||||
|
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||||
|
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||||
|
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||||
|
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||||
|
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||||
|
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||||
|
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
|
||||||
|
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||||
|
},
|
||||||
|
u'contenttypes.contenttype': {
|
||||||
|
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||||
|
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||||
|
},
|
||||||
|
'main.activitystream': {
|
||||||
|
'Meta': {'object_name': 'ActivityStream'},
|
||||||
|
'actor': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_stream'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||||
|
'changes': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||||
|
'credential': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Credential']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'group': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'host': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Host']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'inventory': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Inventory']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'inventory_source': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventorySource']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'inventory_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventoryUpdate']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'job': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Job']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'job_template': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.JobTemplate']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'object1': ('django.db.models.fields.TextField', [], {}),
|
||||||
|
'object2': ('django.db.models.fields.TextField', [], {}),
|
||||||
|
'object_relationship_type': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||||
|
'operation': ('django.db.models.fields.CharField', [], {'max_length': '13'}),
|
||||||
|
'organization': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Organization']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'permission': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'project': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Project']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'project_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.ProjectUpdate']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'schedule': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Schedule']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'team': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Team']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'unified_job': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'activity_stream_as_unified_job+'", 'blank': 'True', 'to': "orm['main.UnifiedJob']"}),
|
||||||
|
'unified_job_template': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'activity_stream_as_unified_job_template+'", 'blank': 'True', 'to': "orm['main.UnifiedJobTemplate']"}),
|
||||||
|
'user': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'symmetrical': 'False', 'blank': 'True'})
|
||||||
|
},
|
||||||
|
'main.authtoken': {
|
||||||
|
'Meta': {'object_name': 'AuthToken'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'expires': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||||
|
'key': ('django.db.models.fields.CharField', [], {'max_length': '40', 'primary_key': 'True'}),
|
||||||
|
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||||
|
'request_hash': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '40', 'blank': 'True'}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_tokens'", 'to': u"orm['auth.User']"})
|
||||||
|
},
|
||||||
|
'main.credential': {
|
||||||
|
'Meta': {'ordering': "('kind', 'name')", 'unique_together': "[('user', 'team', 'kind', 'name')]", 'object_name': 'Credential'},
|
||||||
|
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||||
|
'cloud': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||||
|
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'credential\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||||
|
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||||
|
'host': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'kind': ('django.db.models.fields.CharField', [], {'default': "'ssh'", 'max_length': '32'}),
|
||||||
|
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||||
|
'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'credential\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
|
||||||
|
'password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'project': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100', 'blank': 'True'}),
|
||||||
|
'ssh_key_data': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||||
|
'ssh_key_unlock': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'su_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'su_username': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'sudo_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'sudo_username': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'team': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'credentials'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Team']"}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'credentials'", 'null': 'True', 'blank': 'True', 'to': u"orm['auth.User']"}),
|
||||||
|
'username': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'vault_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'})
|
||||||
|
},
|
||||||
|
'main.custominventoryscript': {
|
||||||
|
'Meta': {'ordering': "('name',)", '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', [], {'unique': 'True', 'max_length': '512'}),
|
||||||
|
'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'}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'ip_address': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
|
||||||
|
'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']"}),
|
||||||
|
'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'}),
|
||||||
|
'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']},
|
||||||
|
'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs_as_cloud_credential+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}),
|
||||||
|
'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}),
|
||||||
|
'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||||
|
'force_handlers': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}),
|
||||||
|
'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'jobs'", 'symmetrical': 'False', 'through': "orm['main.JobHostSummary']", 'to': "orm['main.Host']"}),
|
||||||
|
'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}),
|
||||||
|
'job_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobTemplate']", 'blank': 'True', 'null': 'True'}),
|
||||||
|
'job_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
|
||||||
|
'limit': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'playbook': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}),
|
||||||
|
'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}),
|
||||||
|
'skip_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'start_at_task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
u'unifiedjob_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJob']", 'unique': 'True', 'primary_key': 'True'}),
|
||||||
|
'verbosity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'})
|
||||||
|
},
|
||||||
|
'main.jobevent': {
|
||||||
|
'Meta': {'ordering': "('pk',)", 'object_name': 'JobEvent'},
|
||||||
|
'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'counter': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||||
|
'event': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'event_data': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}),
|
||||||
|
'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'host': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'job_events_as_primary_host'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Host']"}),
|
||||||
|
'host_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}),
|
||||||
|
'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'job_events'", 'symmetrical': 'False', 'to': "orm['main.Host']"}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_events'", 'to': "orm['main.Job']"}),
|
||||||
|
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||||
|
'parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'children'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.JobEvent']"}),
|
||||||
|
'play': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}),
|
||||||
|
'role': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}),
|
||||||
|
'task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'})
|
||||||
|
},
|
||||||
|
'main.jobhostsummary': {
|
||||||
|
'Meta': {'ordering': "('-pk',)", 'unique_together': "[('job', 'host_name')]", 'object_name': 'JobHostSummary'},
|
||||||
|
'changed': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||||
|
'dark': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||||
|
'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||||
|
'host': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'job_host_summaries'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Host']"}),
|
||||||
|
'host_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_host_summaries'", 'to': "orm['main.Job']"}),
|
||||||
|
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||||
|
'ok': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||||
|
'processed': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||||
|
'skipped': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
|
||||||
|
},
|
||||||
|
'main.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'}),
|
||||||
|
'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates_as_cloud_credential+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}),
|
||||||
|
'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}),
|
||||||
|
'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||||
|
'force_handlers': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}),
|
||||||
|
'host_config_key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}),
|
||||||
|
'job_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'job_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
|
||||||
|
'limit': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'playbook': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}),
|
||||||
|
'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}),
|
||||||
|
'skip_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'start_at_task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'survey_enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'survey_spec': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}),
|
||||||
|
u'unifiedjobtemplate_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJobTemplate']", 'unique': 'True', 'primary_key': 'True'}),
|
||||||
|
'verbosity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'})
|
||||||
|
},
|
||||||
|
'main.organization': {
|
||||||
|
'Meta': {'ordering': "('name',)", 'object_name': 'Organization'},
|
||||||
|
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||||
|
'admins': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'admin_of_organizations'", 'blank': 'True', 'to': u"orm['auth.User']"}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||||
|
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'organization\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||||
|
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||||
|
'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'organization\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
|
||||||
|
'projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organizations'", 'blank': 'True', 'to': "orm['main.Project']"}),
|
||||||
|
'users': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organizations'", 'blank': 'True', 'to': u"orm['auth.User']"})
|
||||||
|
},
|
||||||
|
'main.permission': {
|
||||||
|
'Meta': {'object_name': 'Permission'},
|
||||||
|
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||||
|
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'permission\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||||
|
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}),
|
||||||
|
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||||
|
'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'permission\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
|
||||||
|
'permission_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
|
||||||
|
'project': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}),
|
||||||
|
'team': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Team']"}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"})
|
||||||
|
},
|
||||||
|
'main.profile': {
|
||||||
|
'Meta': {'object_name': 'Profile'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||||
|
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'ldap_dn': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}),
|
||||||
|
'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||||
|
'user': ('awx.main.fields.AutoOneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': u"orm['auth.User']"})
|
||||||
|
},
|
||||||
|
'main.project': {
|
||||||
|
'Meta': {'ordering': "('id',)", 'object_name': 'Project', '_ormbases': ['main.UnifiedJobTemplate']},
|
||||||
|
'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'projects'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}),
|
||||||
|
'local_path': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'scm_branch': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}),
|
||||||
|
'scm_clean': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'scm_delete_on_next_update': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'scm_delete_on_update': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'scm_type': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '8', 'blank': 'True'}),
|
||||||
|
'scm_update_cache_timeout': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
|
||||||
|
'scm_update_on_launch': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'scm_url': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
u'unifiedjobtemplate_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJobTemplate']", 'unique': 'True', 'primary_key': 'True'})
|
||||||
|
},
|
||||||
|
'main.projectupdate': {
|
||||||
|
'Meta': {'object_name': 'ProjectUpdate', '_ormbases': ['main.UnifiedJob']},
|
||||||
|
'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'projectupdates'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}),
|
||||||
|
'local_path': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}),
|
||||||
|
'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'project_updates'", 'to': "orm['main.Project']"}),
|
||||||
|
'scm_branch': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}),
|
||||||
|
'scm_clean': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'scm_delete_on_update': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'scm_type': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '8', 'blank': 'True'}),
|
||||||
|
'scm_url': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
|
||||||
|
u'unifiedjob_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJob']", 'unique': 'True', 'primary_key': 'True'})
|
||||||
|
},
|
||||||
|
'main.schedule': {
|
||||||
|
'Meta': {'ordering': "['-next_run']", 'object_name': 'Schedule'},
|
||||||
|
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
|
||||||
|
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'schedule\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
|
||||||
|
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
|
||||||
|
'dtend': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
|
||||||
|
'dtstart': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
|
||||||
|
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||||
|
'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']
|
||||||
|
symmetrical = True
|
||||||
@@ -957,7 +957,7 @@ class RunInventoryUpdate(BaseTask):
|
|||||||
ec2_opts['cache_path'] = cache_path
|
ec2_opts['cache_path'] = cache_path
|
||||||
ec2_opts.setdefault('cache_max_age', '300')
|
ec2_opts.setdefault('cache_max_age', '300')
|
||||||
for k,v in ec2_opts.items():
|
for k,v in ec2_opts.items():
|
||||||
cp.set(section, k, str(v))
|
cp.set(section, k, unicode(v))
|
||||||
# Build pyrax creds INI for rax inventory script.
|
# Build pyrax creds INI for rax inventory script.
|
||||||
elif inventory_update.source == 'rax':
|
elif inventory_update.source == 'rax':
|
||||||
section = 'rackspace_cloud'
|
section = 'rackspace_cloud'
|
||||||
@@ -967,6 +967,15 @@ class RunInventoryUpdate(BaseTask):
|
|||||||
cp.set(section, 'username', credential.username)
|
cp.set(section, 'username', credential.username)
|
||||||
cp.set(section, 'api_key', decrypt_field(credential,
|
cp.set(section, 'api_key', decrypt_field(credential,
|
||||||
'password'))
|
'password'))
|
||||||
|
# Allow custom options to vmware inventory script.
|
||||||
|
elif inventory_update.source == 'vmware':
|
||||||
|
section = 'defaults'
|
||||||
|
cp.add_section(section)
|
||||||
|
vmware_opts = dict(inventory_update.source_vars_dict.items())
|
||||||
|
vmware_opts.setdefault('guests_only', 'True')
|
||||||
|
for k,v in vmware_opts.items():
|
||||||
|
cp.set(section, k, unicode(v))
|
||||||
|
|
||||||
# Return INI content.
|
# Return INI content.
|
||||||
if cp.sections():
|
if cp.sections():
|
||||||
f = cStringIO.StringIO()
|
f = cStringIO.StringIO()
|
||||||
@@ -1027,6 +1036,7 @@ class RunInventoryUpdate(BaseTask):
|
|||||||
# complain about not being able to determine its version number.
|
# complain about not being able to determine its version number.
|
||||||
env['PBR_VERSION'] = '0.5.21'
|
env['PBR_VERSION'] = '0.5.21'
|
||||||
elif inventory_update.source == 'vmware':
|
elif inventory_update.source == 'vmware':
|
||||||
|
env['VMWARE_INI'] = kwargs.get('private_data_file', '')
|
||||||
env['VMWARE_HOST'] = passwords.get('source_host', '')
|
env['VMWARE_HOST'] = passwords.get('source_host', '')
|
||||||
env['VMWARE_USER'] = passwords.get('source_username', '')
|
env['VMWARE_USER'] = passwords.get('source_username', '')
|
||||||
env['VMWARE_PASSWORD'] = passwords.get('source_password', '')
|
env['VMWARE_PASSWORD'] = passwords.get('source_password', '')
|
||||||
@@ -1042,8 +1052,8 @@ class RunInventoryUpdate(BaseTask):
|
|||||||
pass
|
pass
|
||||||
elif inventory_update.source == 'custom':
|
elif inventory_update.source == 'custom':
|
||||||
for env_k in inventory_update.source_vars_dict:
|
for env_k in inventory_update.source_vars_dict:
|
||||||
if env_k not in os.environ:
|
if str(env_k) not in os.environ:
|
||||||
env[env_k] = unicode(inventory_update.source_vars_dict[env_k])
|
env[str(env_k)] = unicode(inventory_update.source_vars_dict[env_k])
|
||||||
return env
|
return env
|
||||||
|
|
||||||
def build_args(self, inventory_update, **kwargs):
|
def build_args(self, inventory_update, **kwargs):
|
||||||
@@ -1146,6 +1156,13 @@ class RunSystemJob(BaseTask):
|
|||||||
json_vars = json.loads(system_job.extra_vars)
|
json_vars = json.loads(system_job.extra_vars)
|
||||||
if 'days' in json_vars:
|
if 'days' in json_vars:
|
||||||
args.extend(['--days', str(json_vars['days'])])
|
args.extend(['--days', str(json_vars['days'])])
|
||||||
|
if system_job.job_type == 'cleanup_jobs':
|
||||||
|
if 'jobs' in json_vars and json_vars['jobs']:
|
||||||
|
args.extend(['--jobs'])
|
||||||
|
if 'project_updates' in json_vars and json_vars['project_updates']:
|
||||||
|
args.extend(['--project-updates'])
|
||||||
|
if 'inventory_updates' in json_vars and json_vars['inventory_updates']:
|
||||||
|
args.extend(['--inventory-updates'])
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
pass
|
pass
|
||||||
print args
|
print args
|
||||||
|
|||||||
@@ -1562,6 +1562,62 @@ class InventoryUpdatesTest(BaseTransactionTest):
|
|||||||
# its own child).
|
# its own child).
|
||||||
self.assertTrue(self.group in self.inventory.root_groups)
|
self.assertTrue(self.group in self.inventory.root_groups)
|
||||||
|
|
||||||
|
def test_update_from_vmware(self):
|
||||||
|
source_host = getattr(settings, 'TEST_VMWARE_HOST', '')
|
||||||
|
source_username = getattr(settings, 'TEST_VMWARE_USER', '')
|
||||||
|
source_password = getattr(settings, 'TEST_VMWARE_PASSWORD', '')
|
||||||
|
if not all([source_host, source_username, source_password]):
|
||||||
|
self.skipTest('no test vmware credentials defined!')
|
||||||
|
self.create_test_license_file()
|
||||||
|
credential = Credential.objects.create(kind='vmware',
|
||||||
|
user=self.super_django_user,
|
||||||
|
username=source_username,
|
||||||
|
password=source_password,
|
||||||
|
host=source_host)
|
||||||
|
inventory_source = self.update_inventory_source(self.group,
|
||||||
|
source='vmware', credential=credential)
|
||||||
|
# Check first without instance_id set (to import by name only).
|
||||||
|
with self.settings(VMWARE_INSTANCE_ID_VAR=''):
|
||||||
|
self.check_inventory_source(inventory_source)
|
||||||
|
# Rename hosts and verify the import picks up the instance_id present
|
||||||
|
# in host variables.
|
||||||
|
for host in self.inventory.hosts.all():
|
||||||
|
self.assertFalse(host.instance_id, host.instance_id)
|
||||||
|
if host.enabled:
|
||||||
|
self.assertTrue(host.variables_dict.get('ansible_ssh_host', ''))
|
||||||
|
# Test a field that should be present for host systems, not VMs.
|
||||||
|
self.assertFalse(host.variables_dict.get('vmware_product_name', ''))
|
||||||
|
host.name = 'updated-%s' % host.name
|
||||||
|
host.save()
|
||||||
|
old_host_pks = set(self.inventory.hosts.values_list('pk', flat=True))
|
||||||
|
self.check_inventory_source(inventory_source, initial=False)
|
||||||
|
new_host_pks = set(self.inventory.hosts.values_list('pk', flat=True))
|
||||||
|
self.assertEqual(old_host_pks, new_host_pks)
|
||||||
|
# Manually disable all hosts, verify a new update re-enables them.
|
||||||
|
# Also change the host name, and verify it is not deleted, but instead
|
||||||
|
# updated because the instance ID matches.
|
||||||
|
enabled_host_pks = set(self.inventory.hosts.filter(enabled=True).values_list('pk', flat=True))
|
||||||
|
for host in self.inventory.hosts.all():
|
||||||
|
host.enabled = False
|
||||||
|
host.name = 'changed-%s' % host.name
|
||||||
|
host.save()
|
||||||
|
old_host_pks = set(self.inventory.hosts.values_list('pk', flat=True))
|
||||||
|
self.check_inventory_source(inventory_source, initial=False, enabled_host_pks=enabled_host_pks)
|
||||||
|
new_host_pks = set(self.inventory.hosts.values_list('pk', flat=True))
|
||||||
|
self.assertEqual(old_host_pks, new_host_pks)
|
||||||
|
# Update again and include host systems in addition to guests.
|
||||||
|
inventory_source.source_vars = '---\n\nguests_only: false\n'
|
||||||
|
inventory_source.save()
|
||||||
|
old_host_pks = set(self.inventory.hosts.values_list('pk', flat=True))
|
||||||
|
self.check_inventory_source(inventory_source, initial=False)
|
||||||
|
new_host_pks = set(self.inventory.hosts.values_list('pk', flat=True))
|
||||||
|
self.assertTrue(new_host_pks > old_host_pks)
|
||||||
|
for host in self.inventory.hosts.filter(pk__in=(new_host_pks - old_host_pks)):
|
||||||
|
if host.enabled:
|
||||||
|
self.assertTrue(host.variables_dict.get('ansible_ssh_host', ''))
|
||||||
|
# Test a field only present for host systems.
|
||||||
|
self.assertTrue(host.variables_dict.get('vmware_product_name', ''))
|
||||||
|
|
||||||
def test_update_from_custom_script(self):
|
def test_update_from_custom_script(self):
|
||||||
# Create the inventory script
|
# Create the inventory script
|
||||||
self.create_test_license_file()
|
self.create_test_license_file()
|
||||||
|
|||||||
@@ -1,232 +1,414 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
'''
|
'''
|
||||||
VMWARE external inventory script
|
VMware Inventory Script
|
||||||
=================================
|
=======================
|
||||||
|
|
||||||
shamelessly copied from existing inventory scripts.
|
Retrieve information about virtual machines from a vCenter server or
|
||||||
|
standalone ESX host. When `group_by=false` (in the INI file), host systems
|
||||||
|
are also returned in addition to VMs.
|
||||||
|
|
||||||
This script and it's ini can be used more than once,
|
This script will attempt to read configuration from an INI file with the same
|
||||||
|
base filename if present, or `vmware.ini` if not. It is possible to create
|
||||||
|
symlinks to the inventory script to support multiple configurations, e.g.:
|
||||||
|
|
||||||
i.e vmware.py/vmware_colo.ini vmware_idf.py/vmware_idf.ini
|
* `vmware.py` (this script)
|
||||||
(script can be link)
|
* `vmware.ini` (default configuration, will be read by `vmware.py`)
|
||||||
|
* `vmware_test.py` (symlink to `vmware.py`)
|
||||||
|
* `vmware_test.ini` (test configuration, will be read by `vmware_test.py`)
|
||||||
|
* `vmware_other.py` (symlink to `vmware.py`, will read `vmware.ini` since no
|
||||||
|
`vmware_other.ini` exists)
|
||||||
|
|
||||||
so if you don't have clustered vcenter but multiple esx machines or
|
The path to an INI file may also be specified via the `VMWARE_INI` environment
|
||||||
just diff clusters you can have a inventory per each and automatically
|
variable, in which case the filename matching rules above will not apply.
|
||||||
group hosts based on file name or specify a group in the ini.
|
|
||||||
|
Host and authentication parameters may be specified via the `VMWARE_HOST`,
|
||||||
|
`VMWARE_USER` and `VMWARE_PASSWORD` environment variables; these options will
|
||||||
|
take precedence over options present in the INI file. An INI file is not
|
||||||
|
required if these options are specified using environment variables.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
import collections
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import optparse
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import ConfigParser
|
import ConfigParser
|
||||||
from psphere.client import Client
|
|
||||||
from psphere.managedobjects import HostSystem
|
|
||||||
|
|
||||||
|
# Disable logging message trigged by pSphere/suds.
|
||||||
try:
|
try:
|
||||||
import json
|
from logging import NullHandler
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import simplejson as json
|
from logging import Handler
|
||||||
|
class NullHandler(Handler):
|
||||||
|
def emit(self, record):
|
||||||
|
pass
|
||||||
|
logging.getLogger('psphere').addHandler(NullHandler())
|
||||||
|
logging.getLogger('suds').addHandler(NullHandler())
|
||||||
|
|
||||||
|
from psphere.client import Client
|
||||||
|
from psphere.errors import ObjectNotFoundError
|
||||||
|
from psphere.managedobjects import HostSystem, VirtualMachine, ManagedObject, Network
|
||||||
|
from suds.sudsobject import Object as SudsObject
|
||||||
|
|
||||||
|
|
||||||
def save_cache(cache_item, data, config):
|
class VMwareInventory(object):
|
||||||
''' saves item to cache '''
|
|
||||||
|
def __init__(self, guests_only=None):
|
||||||
|
self.config = ConfigParser.SafeConfigParser()
|
||||||
|
if os.environ.get('VMWARE_INI', ''):
|
||||||
|
config_files = [os.environ['VMWARE_INI']]
|
||||||
|
else:
|
||||||
|
config_files = [os.path.abspath(sys.argv[0]).rstrip('.py') + '.ini', 'vmware.ini']
|
||||||
|
for config_file in config_files:
|
||||||
|
if os.path.exists(config_file):
|
||||||
|
self.config.read(config_file)
|
||||||
|
break
|
||||||
|
|
||||||
# Sanity check: Is caching enabled? If not, don't cache.
|
# Retrieve only guest VMs, or include host systems?
|
||||||
if not config.has_option('defaults', 'cache_dir'):
|
if guests_only is not None:
|
||||||
return
|
self.guests_only = guests_only
|
||||||
|
elif self.config.has_option('defaults', 'guests_only'):
|
||||||
|
self.guests_only = self.config.getboolean('defaults', 'guests_only')
|
||||||
|
else:
|
||||||
|
self.guests_only = True
|
||||||
|
|
||||||
dpath = config.get('defaults', 'cache_dir')
|
# Read authentication information from VMware environment variables
|
||||||
try:
|
# (if set), otherwise from INI file.
|
||||||
cache = open('/'.join([dpath,cache_item]), 'w')
|
auth_host = os.environ.get('VMWARE_HOST')
|
||||||
cache.write(json.dumps(data))
|
if not auth_host and self.config.has_option('auth', 'host'):
|
||||||
cache.close()
|
auth_host = self.config.get('auth', 'host')
|
||||||
except IOError, e:
|
auth_user = os.environ.get('VMWARE_USER')
|
||||||
pass # not really sure what to do here
|
if not auth_user and self.config.has_option('auth', 'user'):
|
||||||
|
auth_user = self.config.get('auth', 'user')
|
||||||
|
auth_password = os.environ.get('VMWARE_PASSWORD')
|
||||||
|
if not auth_password and self.config.has_option('auth', 'password'):
|
||||||
|
auth_password = self.config.get('auth', 'password')
|
||||||
|
|
||||||
|
# Create the VMware client connection.
|
||||||
|
self.client = Client(auth_host, auth_user, auth_password)
|
||||||
|
|
||||||
def get_cache(cache_item, config):
|
def _put_cache(self, name, value):
|
||||||
''' returns cached item '''
|
'''
|
||||||
|
Saves the value to cache with the name given.
|
||||||
|
'''
|
||||||
|
if self.config.has_option('defaults', 'cache_dir'):
|
||||||
|
cache_dir = self.config.get('defaults', 'cache_dir')
|
||||||
|
if not os.path.exists(cache_dir):
|
||||||
|
os.makedirs(cache_dir)
|
||||||
|
cache_file = os.path.join(cache_dir, name)
|
||||||
|
with open(cache_file, 'w') as cache:
|
||||||
|
json.dump(value, cache)
|
||||||
|
|
||||||
# Sanity check: Is caching enabled? If not, return None.
|
def _get_cache(self, name, default=None):
|
||||||
if not config.has_option('defaults', 'cache_dir'):
|
'''
|
||||||
return
|
Retrieves the value from cache for the given name.
|
||||||
|
'''
|
||||||
|
if self.config.has_option('defaults', 'cache_dir'):
|
||||||
|
cache_dir = self.config.get('defaults', 'cache_dir')
|
||||||
|
cache_file = os.path.join(cache_dir, name)
|
||||||
|
if os.path.exists(cache_file):
|
||||||
|
if self.config.has_option('defaults', 'cache_max_age'):
|
||||||
|
cache_max_age = self.config.getint('defaults', 'cache_max_age')
|
||||||
|
else:
|
||||||
|
cache_max_age = 0
|
||||||
|
cache_stat = os.stat(cache_file)
|
||||||
|
if (cache_stat.st_mtime + cache_max_age) < time.time():
|
||||||
|
with open(cache_file) as cache:
|
||||||
|
return json.load(cache)
|
||||||
|
return default
|
||||||
|
|
||||||
dpath = config.get('defaults', 'cache_dir')
|
def _flatten_dict(self, d, parent_key='', sep='_'):
|
||||||
inv = {}
|
'''
|
||||||
try:
|
Flatten nested dicts by combining keys with a separator. Lists with
|
||||||
cache = open('/'.join([dpath,cache_item]), 'r')
|
only string items are included as is; any other lists are discarded.
|
||||||
inv = json.loads(cache.read())
|
'''
|
||||||
cache.close()
|
items = []
|
||||||
except IOError, e:
|
for k, v in d.items():
|
||||||
pass # not really sure what to do here
|
if k.startswith('_'):
|
||||||
|
continue
|
||||||
|
new_key = parent_key + sep + k if parent_key else k
|
||||||
|
if isinstance(v, collections.MutableMapping):
|
||||||
|
items.extend(self._flatten_dict(v, new_key, sep).items())
|
||||||
|
elif isinstance(v, (list, tuple)):
|
||||||
|
if all([isinstance(x, basestring) for x in v]):
|
||||||
|
items.append((new_key, v))
|
||||||
|
else:
|
||||||
|
items.append((new_key, v))
|
||||||
|
return dict(items)
|
||||||
|
|
||||||
return inv
|
def _get_obj_info(self, obj, depth=99, seen=None):
|
||||||
|
'''
|
||||||
def cache_available(cache_item, config):
|
Recursively build a data structure for the given pSphere object (depth
|
||||||
''' checks if we have a 'fresh' cache available for item requested '''
|
only applies to ManagedObject instances).
|
||||||
|
'''
|
||||||
if config.has_option('defaults', 'cache_dir'):
|
seen = seen or set()
|
||||||
dpath = config.get('defaults', 'cache_dir')
|
if isinstance(obj, ManagedObject):
|
||||||
|
try:
|
||||||
|
obj_unicode = unicode(getattr(obj, 'name'))
|
||||||
|
except AttributeError:
|
||||||
|
obj_unicode = ()
|
||||||
|
if obj in seen:
|
||||||
|
return obj_unicode
|
||||||
|
seen.add(obj)
|
||||||
|
if depth <= 0:
|
||||||
|
return obj_unicode
|
||||||
|
d = {}
|
||||||
|
for attr in dir(obj):
|
||||||
|
if attr.startswith('_'):
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
val = getattr(obj, attr)
|
||||||
|
obj_info = self._get_obj_info(val, depth - 1, seen)
|
||||||
|
if obj_info != ():
|
||||||
|
d[attr] = obj_info
|
||||||
|
except Exception, e:
|
||||||
|
pass
|
||||||
|
return d
|
||||||
|
elif isinstance(obj, SudsObject):
|
||||||
|
d = {}
|
||||||
|
for key, val in iter(obj):
|
||||||
|
obj_info = self._get_obj_info(val, depth, seen)
|
||||||
|
if obj_info != ():
|
||||||
|
d[key] = obj_info
|
||||||
|
return d
|
||||||
|
elif isinstance(obj, (list, tuple)):
|
||||||
|
l = []
|
||||||
|
for val in iter(obj):
|
||||||
|
obj_info = self._get_obj_info(val, depth, seen)
|
||||||
|
if obj_info != ():
|
||||||
|
l.append(obj_info)
|
||||||
|
return l
|
||||||
|
elif isinstance(obj, (type(None), bool, int, long, float, basestring)):
|
||||||
|
return obj
|
||||||
|
else:
|
||||||
|
return ()
|
||||||
|
|
||||||
|
def _get_host_info(self, host, prefix='vmware'):
|
||||||
|
'''
|
||||||
|
Return a flattened dict with info about the given host system.
|
||||||
|
'''
|
||||||
|
host_info = {
|
||||||
|
'name': host.name,
|
||||||
|
'tag': host.tag,
|
||||||
|
'datastores': self._get_obj_info(host.datastore, depth=0),
|
||||||
|
'networks': self._get_obj_info(host.network, depth=0),
|
||||||
|
'vms': self._get_obj_info(host.vm, depth=0),
|
||||||
|
}
|
||||||
|
for k, v in self._get_obj_info(host.summary, depth=0).items():
|
||||||
|
if isinstance(v, collections.MutableMapping):
|
||||||
|
for k2, v2 in v.items():
|
||||||
|
host_info[k2] = v2
|
||||||
|
elif k != 'host':
|
||||||
|
host_info[k] = v
|
||||||
try:
|
try:
|
||||||
existing = os.stat( '/'.join([dpath,cache_item]))
|
host_info['ipAddress'] = host.config.network.vnic[0].spec.ip.ipAddress
|
||||||
except:
|
except Exception, e:
|
||||||
# cache doesn't exist or isn't accessible
|
print >> sys.stderr, e
|
||||||
return False
|
host_info = self._flatten_dict(host_info, prefix)
|
||||||
|
if ('%s_ipAddress' % prefix) in host_info:
|
||||||
|
host_info['ansible_ssh_host'] = host_info['%s_ipAddress' % prefix]
|
||||||
|
return host_info
|
||||||
|
|
||||||
if config.has_option('defaults', 'cache_max_age'):
|
def _get_vm_info(self, vm, prefix='vmware'):
|
||||||
maxage = config.get('defaults', 'cache_max_age')
|
'''
|
||||||
|
Return a flattened dict with info about the given virtual machine.
|
||||||
|
'''
|
||||||
|
vm_info = {
|
||||||
|
'name': vm.name,
|
||||||
|
'tag': vm.tag,
|
||||||
|
'datastores': self._get_obj_info(vm.datastore, depth=0),
|
||||||
|
'networks': self._get_obj_info(vm.network, depth=0),
|
||||||
|
'resourcePool': self._get_obj_info(vm.resourcePool, depth=0),
|
||||||
|
'guestState': vm.guest.guestState,
|
||||||
|
}
|
||||||
|
for k, v in self._get_obj_info(vm.summary, depth=0).items():
|
||||||
|
if isinstance(v, collections.MutableMapping):
|
||||||
|
for k2, v2 in v.items():
|
||||||
|
if k2 == 'host':
|
||||||
|
k2 = 'hostSystem'
|
||||||
|
vm_info[k2] = v2
|
||||||
|
elif k != 'vm':
|
||||||
|
vm_info[k] = v
|
||||||
|
vm_info = self._flatten_dict(vm_info, prefix)
|
||||||
|
if ('%s_ipAddress' % prefix) in vm_info:
|
||||||
|
vm_info['ansible_ssh_host'] = vm_info['%s_ipAddress' % prefix]
|
||||||
|
return vm_info
|
||||||
|
|
||||||
if (existing.st_mtime - int(time.time())) <= maxage:
|
def _add_host(self, inv, parent_group, host_name):
|
||||||
return True
|
'''
|
||||||
|
Add the host to the parent group in the given inventory.
|
||||||
|
'''
|
||||||
|
p_group = inv.setdefault(parent_group, [])
|
||||||
|
if isinstance(p_group, dict):
|
||||||
|
group_hosts = p_group.setdefault('hosts', [])
|
||||||
|
else:
|
||||||
|
group_hosts = p_group
|
||||||
|
if host_name not in group_hosts:
|
||||||
|
group_hosts.append(host_name)
|
||||||
|
|
||||||
return False
|
def _add_child(self, inv, parent_group, child_group):
|
||||||
|
'''
|
||||||
|
Add a child group to a parent group in the given inventory.
|
||||||
|
'''
|
||||||
|
if parent_group != 'all':
|
||||||
|
p_group = inv.setdefault(parent_group, {})
|
||||||
|
if not isinstance(p_group, dict):
|
||||||
|
inv[parent_group] = {'hosts': p_group}
|
||||||
|
p_group = inv[parent_group]
|
||||||
|
group_children = p_group.setdefault('children', [])
|
||||||
|
if child_group not in group_children:
|
||||||
|
group_children.append(child_group)
|
||||||
|
inv.setdefault(child_group, [])
|
||||||
|
|
||||||
def get_host_info(host):
|
def get_inventory(self, meta_hostvars=True):
|
||||||
''' Get variables about a specific host '''
|
'''
|
||||||
|
Reads the inventory from cache or VMware API via pSphere.
|
||||||
|
'''
|
||||||
|
# Use different cache names for guests only vs. all hosts.
|
||||||
|
if self.guests_only:
|
||||||
|
cache_name = '__inventory_guests__'
|
||||||
|
else:
|
||||||
|
cache_name = '__inventory_all__'
|
||||||
|
|
||||||
hostinfo = {
|
inv = self._get_cache(cache_name, None)
|
||||||
'vmware_name' : host.name,
|
if inv is not None:
|
||||||
'vmware_tag' : host.tag,
|
return inv
|
||||||
'vmware_parent': host.parent.name,
|
|
||||||
}
|
|
||||||
for k in host.capability.__dict__.keys():
|
|
||||||
if k.startswith('_'):
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
hostinfo['vmware_' + k] = str(host.capability[k])
|
|
||||||
except:
|
|
||||||
continue
|
|
||||||
|
|
||||||
return hostinfo
|
inv = {'all': {'hosts': []}}
|
||||||
|
if meta_hostvars:
|
||||||
|
inv['_meta'] = {'hostvars': {}}
|
||||||
|
|
||||||
|
|
||||||
def get_inventory(client, config):
|
|
||||||
''' Reads the inventory from cache or vmware api '''
|
|
||||||
|
|
||||||
if cache_available('inventory', config):
|
|
||||||
inv = get_cache('inventory',config)
|
|
||||||
else:
|
|
||||||
inv= { 'all': {'hosts': []}, '_meta': { 'hostvars': {} } }
|
|
||||||
default_group = os.path.basename(sys.argv[0]).rstrip('.py')
|
default_group = os.path.basename(sys.argv[0]).rstrip('.py')
|
||||||
|
|
||||||
if config.has_option('defaults', 'guests_only'):
|
if not self.guests_only:
|
||||||
guests_only = config.get('defaults', 'guests_only')
|
if self.config.has_option('defaults', 'hw_group'):
|
||||||
else:
|
hw_group = self.config.get('defaults', 'hw_group')
|
||||||
guests_only = True
|
|
||||||
|
|
||||||
if not guests_only:
|
|
||||||
if config.has_option('defaults','hw_group'):
|
|
||||||
hw_group = config.get('defaults','hw_group')
|
|
||||||
else:
|
else:
|
||||||
hw_group = default_group + '_hw'
|
hw_group = default_group + '_hw'
|
||||||
inv[hw_group] = []
|
|
||||||
|
|
||||||
if config.has_option('defaults','vm_group'):
|
if self.config.has_option('defaults', 'vm_group'):
|
||||||
vm_group = config.get('defaults','vm_group')
|
vm_group = self.config.get('defaults', 'vm_group')
|
||||||
else:
|
else:
|
||||||
vm_group = default_group + '_vm'
|
vm_group = default_group + '_vm'
|
||||||
inv[vm_group] = []
|
|
||||||
|
|
||||||
# Loop through physical hosts:
|
# Loop through physical hosts:
|
||||||
hosts = HostSystem.all(client)
|
for host in HostSystem.all(self.client):
|
||||||
for host in hosts:
|
|
||||||
if not guests_only:
|
|
||||||
inv['all']['hosts'].append(host.name)
|
|
||||||
inv[hw_group].append(host.name)
|
|
||||||
if host.tag:
|
|
||||||
taggroup = 'vmware_' + host.tag
|
|
||||||
if taggroup in inv:
|
|
||||||
inv[taggroup].append(host.name)
|
|
||||||
else:
|
|
||||||
inv[taggroup] = [ host.name ]
|
|
||||||
|
|
||||||
inv['_meta']['hostvars'][host.name] = get_host_info(host)
|
if not self.guests_only:
|
||||||
save_cache(vm.name, inv['_meta']['hostvars'][host.name], config)
|
self._add_host(inv, 'all', host.name)
|
||||||
|
self._add_host(inv, hw_group, host.name)
|
||||||
|
if host.tag: # FIXME: Is this always a string?
|
||||||
|
host_tag = 'vmware_%s' % host.tag
|
||||||
|
self._add_host(inv, host_tag, host.name)
|
||||||
|
|
||||||
|
host_info = self._get_host_info(host)
|
||||||
|
if meta_hostvars:
|
||||||
|
inv['_meta']['hostvars'][host.name] = host_info
|
||||||
|
self._put_cache(host.name, host_info)
|
||||||
|
|
||||||
|
# Loop through all VMs on physical host.
|
||||||
for vm in host.vm:
|
for vm in host.vm:
|
||||||
inv['all']['hosts'].append(vm.name)
|
self._add_host(inv, 'all', vm.name)
|
||||||
inv[vm_group].append(vm.name)
|
self._add_host(inv, vm_group, vm.name)
|
||||||
for tag in vm.tag:
|
if vm.tag: # FIXME: Is this always a string?
|
||||||
taggroup = 'vmware_' + tag.key.lower()
|
vm_tag = 'vmware_%s' % vm.tag
|
||||||
if taggroup in inv:
|
self._add_host(inv, vm_tag, vm.name)
|
||||||
inv[taggroup].append(vm.name)
|
vm_info = self._get_vm_info(vm)
|
||||||
else:
|
if meta_hostvars:
|
||||||
inv[taggroup] = [ vm.name ]
|
inv['_meta']['hostvars'][vm.name] = vm_info
|
||||||
|
self._put_cache(vm.name, vm_info)
|
||||||
|
|
||||||
inv['_meta']['hostvars'][vm.name] = get_host_info(host)
|
# Group by resource pool.
|
||||||
save_cache(vm.name, inv['_meta']['hostvars'][vm.name], config)
|
vm_resourcePool = vm_info.get('vmware_resourcePool', None)
|
||||||
|
if vm_resourcePool:
|
||||||
|
self._add_child(inv, vm_group, 'resource_pools')
|
||||||
|
self._add_child(inv, 'resource_pools', vm_resourcePool)
|
||||||
|
self._add_host(inv, vm_resourcePool, vm.name)
|
||||||
|
|
||||||
save_cache('inventory', inv, config)
|
# Group by datastore.
|
||||||
return json.dumps(inv)
|
for vm_datastore in vm_info.get('vmware_datastores', []):
|
||||||
|
self._add_child(inv, vm_group, 'datastores')
|
||||||
|
self._add_child(inv, 'datastores', vm_datastore)
|
||||||
|
self._add_host(inv, vm_datastore, vm.name)
|
||||||
|
|
||||||
def get_single_host(client, config, hostname):
|
# Group by network.
|
||||||
|
for vm_network in vm_info.get('vmware_networks', []):
|
||||||
|
self._add_child(inv, vm_group, 'networks')
|
||||||
|
self._add_child(inv, 'networks', vm_network)
|
||||||
|
self._add_host(inv, vm_network, vm.name)
|
||||||
|
|
||||||
inv = {}
|
# Group by guest OS.
|
||||||
|
vm_guestId = vm_info.get('vmware_guestId', None)
|
||||||
|
if vm_guestId:
|
||||||
|
self._add_child(inv, vm_group, 'guests')
|
||||||
|
self._add_child(inv, 'guests', vm_guestId)
|
||||||
|
self._add_host(inv, vm_guestId, vm.name)
|
||||||
|
|
||||||
if cache_available(hostname, config):
|
self._put_cache(cache_name, inv)
|
||||||
inv = get_cache(hostname,config)
|
return inv
|
||||||
|
|
||||||
|
def get_host(self, hostname):
|
||||||
|
'''
|
||||||
|
Read info about a specific host or VM from cache or VMware API.
|
||||||
|
'''
|
||||||
|
inv = self._get_cache(hostname, None)
|
||||||
|
if inv is not None:
|
||||||
|
return inv
|
||||||
|
|
||||||
|
if not self.guests_only:
|
||||||
|
try:
|
||||||
|
host = HostSystem.get(self.client, name=hostname)
|
||||||
|
inv = self._get_host_info(host)
|
||||||
|
except ObjectNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if inv is None:
|
||||||
|
try:
|
||||||
|
vm = VirtualMachine.get(self.client, name=hostname)
|
||||||
|
inv = self._get_vm_info(vm)
|
||||||
|
except ObjectNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if inv is not None:
|
||||||
|
self._put_cache(hostname, inv)
|
||||||
|
return inv or {}
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = optparse.OptionParser()
|
||||||
|
parser.add_option('--list', action='store_true', dest='list',
|
||||||
|
default=False, help='Output inventory groups and hosts')
|
||||||
|
parser.add_option('--host', dest='host', default=None, metavar='HOST',
|
||||||
|
help='Output variables only for the given hostname')
|
||||||
|
# Additional options for use when running the script standalone, but never
|
||||||
|
# used by Ansible.
|
||||||
|
parser.add_option('--pretty', action='store_true', dest='pretty',
|
||||||
|
default=False, help='Output nicely-formatted JSON')
|
||||||
|
parser.add_option('--include-host-systems', action='store_true',
|
||||||
|
dest='include_host_systems', default=False,
|
||||||
|
help='Include host systems in addition to VMs')
|
||||||
|
parser.add_option('--no-meta-hostvars', action='store_false',
|
||||||
|
dest='meta_hostvars', default=True,
|
||||||
|
help='Exclude [\'_meta\'][\'hostvars\'] with --list')
|
||||||
|
options, args = parser.parse_args()
|
||||||
|
|
||||||
|
if options.include_host_systems:
|
||||||
|
vmware_inventory = VMwareInventory(guests_only=False)
|
||||||
else:
|
else:
|
||||||
hosts = HostSystem.all(client) #TODO: figure out single host getter
|
vmware_inventory = VMwareInventory()
|
||||||
for host in hosts:
|
if options.host is not None:
|
||||||
if hostname == host.name:
|
inventory = vmware_inventory.get_host(options.host)
|
||||||
inv = get_host_info(host)
|
else:
|
||||||
break
|
inventory = vmware_inventory.get_inventory(options.meta_hostvars)
|
||||||
for vm in host.vm:
|
|
||||||
if hostname == vm.name:
|
json_kwargs = {}
|
||||||
inv = get_host_info(host)
|
if options.pretty:
|
||||||
break
|
json_kwargs.update({'indent': 4, 'sort_keys': True})
|
||||||
save_cache(hostname,inv,config)
|
json.dump(inventory, sys.stdout, **json_kwargs)
|
||||||
|
|
||||||
return json.dumps(inv)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
inventory = {}
|
main()
|
||||||
hostname = None
|
|
||||||
|
|
||||||
if len(sys.argv) > 1:
|
|
||||||
if sys.argv[1] == "--host":
|
|
||||||
hostname = sys.argv[2]
|
|
||||||
|
|
||||||
# Read config
|
|
||||||
config = ConfigParser.SafeConfigParser(
|
|
||||||
defaults={'host': '', 'user': '', 'password': ''},
|
|
||||||
)
|
|
||||||
for section in ('auth', 'defaults'):
|
|
||||||
config.add_section(section)
|
|
||||||
for configfilename in [os.path.abspath(sys.argv[0]).rstrip('.py') + '.ini', 'vmware.ini']:
|
|
||||||
if os.path.exists(configfilename):
|
|
||||||
config.read(configfilename)
|
|
||||||
break
|
|
||||||
|
|
||||||
auth_host, auth_user, auth_password = None, None, None
|
|
||||||
|
|
||||||
# Read our authentication information from the INI file, if it exists.
|
|
||||||
try:
|
|
||||||
auth_host = config.get('auth', 'host')
|
|
||||||
auth_user = config.get('auth', 'user')
|
|
||||||
auth_password = config.get('auth', 'password')
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# If any of the VMware environment variables are set, they trump
|
|
||||||
# the INI configuration.
|
|
||||||
if 'VMWARE_HOST' in os.environ:
|
|
||||||
auth_host = os.environ['VMWARE_HOST']
|
|
||||||
if 'VMWARE_USER' in os.environ:
|
|
||||||
auth_user = os.environ['VMWARE_USER']
|
|
||||||
if 'VMWARE_PASSWORD' in os.environ:
|
|
||||||
auth_password = os.environ['VMWARE_PASSWORD']
|
|
||||||
|
|
||||||
# Create the VMware client.
|
|
||||||
client = Client(auth_host, auth_user, auth_password)
|
|
||||||
|
|
||||||
# Actually do the work.
|
|
||||||
if hostname is None:
|
|
||||||
inventory = get_inventory(client, config)
|
|
||||||
else:
|
|
||||||
inventory = get_single_host(client, config, hostname)
|
|
||||||
|
|
||||||
# Return to Ansible.
|
|
||||||
print inventory
|
|
||||||
|
|||||||
@@ -399,11 +399,11 @@ VMWARE_REGIONS_BLACKLIST = []
|
|||||||
|
|
||||||
# Inventory variable name/values for determining whether a host is
|
# Inventory variable name/values for determining whether a host is
|
||||||
# active in vSphere.
|
# active in vSphere.
|
||||||
VMWARE_ENABLED_VAR = 'status'
|
VMWARE_ENABLED_VAR = 'vmware_powerState'
|
||||||
VMWARE_ENABLED_VALUE = 'POWERED ON'
|
VMWARE_ENABLED_VALUE = 'poweredOn'
|
||||||
|
|
||||||
# Inventory variable name containing the unique instance ID.
|
# Inventory variable name containing the unique instance ID.
|
||||||
VMWARE_INSTANCE_ID_VAR = 'guest_id'
|
VMWARE_INSTANCE_ID_VAR = 'vmware_uuid'
|
||||||
|
|
||||||
# Filter for allowed group and host names when importing inventory
|
# Filter for allowed group and host names when importing inventory
|
||||||
# from EC2.
|
# from EC2.
|
||||||
|
|||||||
@@ -484,3 +484,8 @@ TEST_AWS_REGIONS = 'all'
|
|||||||
TEST_RACKSPACE_USERNAME = ''
|
TEST_RACKSPACE_USERNAME = ''
|
||||||
TEST_RACKSPACE_API_KEY = ''
|
TEST_RACKSPACE_API_KEY = ''
|
||||||
TEST_RACKSPACE_REGIONS = 'all'
|
TEST_RACKSPACE_REGIONS = 'all'
|
||||||
|
|
||||||
|
# VMware credentials
|
||||||
|
TEST_VMWARE_HOST = ''
|
||||||
|
TEST_VMWARE_USER = ''
|
||||||
|
TEST_VMWARE_PASSWORD = ''
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
tooltip_delay: {show: 500, hide: 100}, // Default number of milliseconds to delay displaying/hiding tooltips
|
tooltip_delay: {show: 500, hide: 100}, // Default number of milliseconds to delay displaying/hiding tooltips
|
||||||
|
|
||||||
debug_mode: false, // Enable console logging messages
|
debug_mode: true, // Enable console logging messages
|
||||||
|
|
||||||
password_strength: 45, // User password strength. Integer between 0 and 100, 100 being impossibly strong.
|
password_strength: 45, // User password strength. Integer between 0 and 100, 100 being impossibly strong.
|
||||||
// This value controls progress bar colors:
|
// This value controls progress bar colors:
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
function JobTemplatesList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobTemplateList,
|
function JobTemplatesList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobTemplateList,
|
||||||
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors,
|
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors,
|
||||||
GetBasePath, JobTemplateForm, CredentialList, LookUpInit, PlaybookRun, Wait, Stream) {
|
GetBasePath, JobTemplateForm, CredentialList, LookUpInit, PlaybookRun, Wait, Stream, CreateDialog, $compile) {
|
||||||
|
|
||||||
ClearScope();
|
ClearScope();
|
||||||
|
|
||||||
@@ -97,6 +97,138 @@ function JobTemplatesList($scope, $rootScope, $location, $log, $routeParams, Res
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.copyJobTemplate = function(id, name){
|
||||||
|
var element,
|
||||||
|
buttons = [{
|
||||||
|
"label": "Cancel",
|
||||||
|
"onClick": function() {
|
||||||
|
$(this).dialog('close');
|
||||||
|
},
|
||||||
|
"icon": "fa-times",
|
||||||
|
"class": "btn btn-default",
|
||||||
|
"id": "copy-close-button"
|
||||||
|
},{
|
||||||
|
"label": "Copy",
|
||||||
|
"onClick": function() {
|
||||||
|
copyAction();
|
||||||
|
// setTimeout(function(){
|
||||||
|
// scope.$apply(function(){
|
||||||
|
// if(mode==='survey-taker'){
|
||||||
|
// scope.$emit('SurveyTakerCompleted');
|
||||||
|
// } else{
|
||||||
|
// scope.saveSurvey();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
},
|
||||||
|
"icon": "fa-copy",
|
||||||
|
"class": "btn btn-primary",
|
||||||
|
"id": "job-copy-button"
|
||||||
|
}],
|
||||||
|
copyAction = function () {
|
||||||
|
// retrieve the copy of the job template object from the api, then overwrite the name and throw away the id
|
||||||
|
Wait('start');
|
||||||
|
var url = defaultUrl + id + '/';
|
||||||
|
Rest.setUrl(url);
|
||||||
|
Rest.get()
|
||||||
|
.success(function (data) {
|
||||||
|
data.name = $scope.new_copy_name;
|
||||||
|
delete data.id;
|
||||||
|
$scope.$emit('GoToCopy', data);
|
||||||
|
})
|
||||||
|
.error(function (data) {
|
||||||
|
Wait('stop');
|
||||||
|
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||||
|
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
CreateDialog({
|
||||||
|
id: 'copy-job-modal' ,
|
||||||
|
title: "Copy",
|
||||||
|
scope: $scope,
|
||||||
|
buttons: buttons,
|
||||||
|
width: 500,
|
||||||
|
height: 300,
|
||||||
|
minWidth: 200,
|
||||||
|
callback: 'CopyDialogReady'
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#job_name').text(name);
|
||||||
|
$('#copy-job-modal').show();
|
||||||
|
|
||||||
|
|
||||||
|
if ($scope.removeCopyDialogReady) {
|
||||||
|
$scope.removeCopyDialogReady();
|
||||||
|
}
|
||||||
|
$scope.removeCopyDialogReady = $scope.$on('CopyDialogReady', function() {
|
||||||
|
$('#copy-job-modal').dialog('open');
|
||||||
|
$('#job-copy-button').attr('ng-disabled', "!copy_form.$valid");
|
||||||
|
element = angular.element(document.getElementById('job-copy-button'));
|
||||||
|
$compile(element)($scope);
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($scope.removeGoToCopy) {
|
||||||
|
$scope.removeGoToCopy();
|
||||||
|
}
|
||||||
|
$scope.removeGoToCopy = $scope.$on('GoToCopy', function(e, data) {
|
||||||
|
var url = defaultUrl,
|
||||||
|
old_survey_url = (data.related.survey_spec) ? data.related.survey_spec : "" ;
|
||||||
|
Rest.setUrl(url);
|
||||||
|
Rest.post(data)
|
||||||
|
.success(function (data) {
|
||||||
|
if(data.survey_enabled===true){
|
||||||
|
$scope.$emit("CopySurvey", data, old_survey_url);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('#copy-job-modal').dialog('close');
|
||||||
|
Wait('stop');
|
||||||
|
$location.path($location.path() + '/' + data.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
.error(function (data) {
|
||||||
|
Wait('stop');
|
||||||
|
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||||
|
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($scope.removeCopySurvey) {
|
||||||
|
$scope.removeCopySurvey();
|
||||||
|
}
|
||||||
|
$scope.removeCopySurvey = $scope.$on('CopySurvey', function(e, new_data, old_url) {
|
||||||
|
// var url = data.related.survey_spec;
|
||||||
|
Rest.setUrl(old_url);
|
||||||
|
Rest.get()
|
||||||
|
.success(function (survey_data) {
|
||||||
|
|
||||||
|
Rest.setUrl(new_data.related.survey_spec);
|
||||||
|
Rest.post(survey_data)
|
||||||
|
.success(function () {
|
||||||
|
$('#copy-job-modal').dialog('close');
|
||||||
|
Wait('stop');
|
||||||
|
$location.path($location.path() + '/' + new_data.id);
|
||||||
|
})
|
||||||
|
.error(function (data) {
|
||||||
|
Wait('stop');
|
||||||
|
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||||
|
msg: 'Call to ' + new_data.related.survey_spec + ' failed. DELETE returned status: ' + status });
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
.error(function (data) {
|
||||||
|
Wait('stop');
|
||||||
|
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||||
|
msg: 'Call to ' + old_url + ' failed. DELETE returned status: ' + status });
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
$scope.submitJob = function (id) {
|
$scope.submitJob = function (id) {
|
||||||
PlaybookRun({ scope: $scope, id: id });
|
PlaybookRun({ scope: $scope, id: id });
|
||||||
};
|
};
|
||||||
@@ -105,7 +237,7 @@ function JobTemplatesList($scope, $rootScope, $location, $log, $routeParams, Res
|
|||||||
JobTemplatesList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobTemplateList',
|
JobTemplatesList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobTemplateList',
|
||||||
'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope',
|
'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope',
|
||||||
'ProcessErrors', 'GetBasePath', 'JobTemplateForm', 'CredentialList', 'LookUpInit',
|
'ProcessErrors', 'GetBasePath', 'JobTemplateForm', 'CredentialList', 'LookUpInit',
|
||||||
'PlaybookRun', 'Wait', 'Stream'
|
'PlaybookRun', 'Wait', 'Stream', 'CreateDialog' , '$compile'
|
||||||
];
|
];
|
||||||
|
|
||||||
function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $routeParams, JobTemplateForm,
|
function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $routeParams, JobTemplateForm,
|
||||||
@@ -339,18 +471,21 @@ function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $routePa
|
|||||||
.success(function(data) {
|
.success(function(data) {
|
||||||
$scope.$emit('templateSaveSuccess', data);
|
$scope.$emit('templateSaveSuccess', data);
|
||||||
|
|
||||||
//once the job template information is saved we submit the survey info to the correct endpoint
|
if(data.survey_enabled===true){
|
||||||
var url = data.url+ 'survey_spec/';
|
//once the job template information is saved we submit the survey info to the correct endpoint
|
||||||
Rest.setUrl(url);
|
var url = data.url+ 'survey_spec/';
|
||||||
Rest.post({ name: $scope.survey_name, description: $scope.survey_description, spec: $scope.survey_questions })
|
Rest.setUrl(url);
|
||||||
.success(function () {
|
Rest.post({ name: $scope.survey_name, description: $scope.survey_description, spec: $scope.survey_questions })
|
||||||
Wait('stop');
|
.success(function () {
|
||||||
|
Wait('stop');
|
||||||
|
|
||||||
|
})
|
||||||
|
.error(function (data, status) {
|
||||||
|
ProcessErrors($scope, data, status, form, { hdr: 'Error!',
|
||||||
|
msg: 'Failed to add new survey. Post returned status: ' + status });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
})
|
|
||||||
.error(function (data, status) {
|
|
||||||
ProcessErrors($scope, data, status, form, { hdr: 'Error!',
|
|
||||||
msg: 'Failed to add new survey. Post returned status: ' + status });
|
|
||||||
});
|
|
||||||
|
|
||||||
})
|
})
|
||||||
.error(function (data, status) {
|
.error(function (data, status) {
|
||||||
@@ -413,8 +548,7 @@ function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeP
|
|||||||
Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, InventoryList,
|
Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, InventoryList,
|
||||||
CredentialList, ProjectList, LookUpInit, GetBasePath, md5Setup, ParseTypeChange, JobStatusToolTip, FormatDate,
|
CredentialList, ProjectList, LookUpInit, GetBasePath, md5Setup, ParseTypeChange, JobStatusToolTip, FormatDate,
|
||||||
Wait, Stream, Empty, Prompt, ParseVariableString, ToJSON, SchedulesControllerInit, JobsControllerInit, JobsListUpdate,
|
Wait, Stream, Empty, Prompt, ParseVariableString, ToJSON, SchedulesControllerInit, JobsControllerInit, JobsListUpdate,
|
||||||
GetChoices, SchedulesListInit, SchedulesList, CallbackHelpInit, PlaybookRun, SurveyControllerInit)
|
GetChoices, SchedulesListInit, SchedulesList, CallbackHelpInit, PlaybookRun, SurveyControllerInit){
|
||||||
{
|
|
||||||
|
|
||||||
ClearScope();
|
ClearScope();
|
||||||
|
|
||||||
@@ -429,6 +563,7 @@ function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeP
|
|||||||
checkSCMStatus, getPlaybooks, callback,
|
checkSCMStatus, getPlaybooks, callback,
|
||||||
choicesCount = 0;
|
choicesCount = 0;
|
||||||
|
|
||||||
|
|
||||||
CallbackHelpInit({ scope: $scope });
|
CallbackHelpInit({ scope: $scope });
|
||||||
|
|
||||||
SchedulesList.well = false;
|
SchedulesList.well = false;
|
||||||
@@ -703,122 +838,7 @@ function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeP
|
|||||||
$scope.rmoveLoadJobs();
|
$scope.rmoveLoadJobs();
|
||||||
}
|
}
|
||||||
$scope.removeLoadJobs = $scope.$on('LoadJobs', function() {
|
$scope.removeLoadJobs = $scope.$on('LoadJobs', function() {
|
||||||
// Retrieve detail record and prepopulate the form
|
$scope.fillJobTemplate();
|
||||||
Rest.setUrl(defaultUrl + id);
|
|
||||||
Rest.get()
|
|
||||||
.success(function (data) {
|
|
||||||
var fld, i;
|
|
||||||
LoadBreadCrumbs({ path: '/job_templates/' + id, title: data.name });
|
|
||||||
for (fld in form.fields) {
|
|
||||||
if (fld !== 'variables' && data[fld] !== null && data[fld] !== undefined) {
|
|
||||||
if (form.fields[fld].type === 'select') {
|
|
||||||
if ($scope[fld + '_options'] && $scope[fld + '_options'].length > 0) {
|
|
||||||
for (i = 0; i < $scope[fld + '_options'].length; i++) {
|
|
||||||
if (data[fld] === $scope[fld + '_options'][i].value) {
|
|
||||||
$scope[fld] = $scope[fld + '_options'][i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$scope[fld] = data[fld];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$scope[fld] = data[fld];
|
|
||||||
if(fld ==='survey_enabled'){
|
|
||||||
// $scope.$emit('EnableSurvey', fld);
|
|
||||||
$('#job_templates_survey_enabled_chbox').attr('checked', $scope[fld]);
|
|
||||||
if(Empty(data.summary_fields.survey)) {
|
|
||||||
$('#job_templates_delete_survey_btn').hide();
|
|
||||||
$('#job_templates_edit_survey_btn').hide();
|
|
||||||
$('#job_templates_create_survey_btn').show();
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
$('#job_templates_delete_survey_btn').show();
|
|
||||||
$('#job_templates_edit_survey_btn').show();
|
|
||||||
$('#job_templates_create_survey_btn').hide();
|
|
||||||
$scope.survey_exists = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
master[fld] = $scope[fld];
|
|
||||||
}
|
|
||||||
if (fld === 'variables') {
|
|
||||||
// Parse extra_vars, converting to YAML.
|
|
||||||
$scope.variables = ParseVariableString(data.extra_vars);
|
|
||||||
master.variables = $scope.variables;
|
|
||||||
}
|
|
||||||
if (form.fields[fld].type === 'lookup' && data.summary_fields[form.fields[fld].sourceModel]) {
|
|
||||||
$scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
|
|
||||||
data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
|
|
||||||
master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
|
|
||||||
$scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.url = data.url;
|
|
||||||
|
|
||||||
$scope.ask_variables_on_launch = (data.ask_variables_on_launch) ? 'true' : 'false';
|
|
||||||
master.ask_variables_on_launch = $scope.ask_variables_on_launch;
|
|
||||||
|
|
||||||
relatedSets = form.relatedSets(data.related);
|
|
||||||
|
|
||||||
if (data.host_config_key) {
|
|
||||||
$scope.example_config_key = data.host_config_key;
|
|
||||||
}
|
|
||||||
$scope.example_template_id = id;
|
|
||||||
$scope.setCallbackHelp();
|
|
||||||
|
|
||||||
$scope.callback_url = $scope.callback_server_path + ((data.related.callback) ? data.related.callback :
|
|
||||||
GetBasePath('job_templates') + id + '/callback/');
|
|
||||||
master.callback_url = $scope.callback_url;
|
|
||||||
|
|
||||||
LookUpInit({
|
|
||||||
scope: $scope,
|
|
||||||
form: form,
|
|
||||||
current_item: data.inventory,
|
|
||||||
list: InventoryList,
|
|
||||||
field: 'inventory',
|
|
||||||
input_type: "radio"
|
|
||||||
});
|
|
||||||
|
|
||||||
LookUpInit({
|
|
||||||
url: GetBasePath('credentials') + '?kind=ssh',
|
|
||||||
scope: $scope,
|
|
||||||
form: form,
|
|
||||||
current_item: data.credential,
|
|
||||||
list: CredentialList,
|
|
||||||
field: 'credential',
|
|
||||||
hdr: 'Select Machine Credential',
|
|
||||||
input_type: "radio"
|
|
||||||
});
|
|
||||||
|
|
||||||
LookUpInit({
|
|
||||||
scope: $scope,
|
|
||||||
form: form,
|
|
||||||
current_item: data.project,
|
|
||||||
list: ProjectList,
|
|
||||||
field: 'project',
|
|
||||||
input_type: "radio"
|
|
||||||
});
|
|
||||||
|
|
||||||
RelatedSearchInit({
|
|
||||||
scope: $scope,
|
|
||||||
form: form,
|
|
||||||
relatedSets: relatedSets
|
|
||||||
});
|
|
||||||
|
|
||||||
RelatedPaginateInit({
|
|
||||||
scope: $scope,
|
|
||||||
relatedSets: relatedSets
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.$emit('jobTemplateLoaded', data.related.cloud_credential);
|
|
||||||
})
|
|
||||||
.error(function (data, status) {
|
|
||||||
ProcessErrors($scope, data, status, form, {
|
|
||||||
hdr: 'Error!',
|
|
||||||
msg: 'Failed to retrieve job template: ' + $routeParams.template_id + '. GET status: ' + status
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if ($scope.removeChoicesReady) {
|
if ($scope.removeChoicesReady) {
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ function JobsListController ($rootScope, $log, $scope, $compile, $routeParams, C
|
|||||||
queued_scope.search('queued_job');
|
queued_scope.search('queued_job');
|
||||||
break;
|
break;
|
||||||
case 'successful':
|
case 'successful':
|
||||||
|
completed_scope.search('completed_job');
|
||||||
|
break;
|
||||||
case 'failed':
|
case 'failed':
|
||||||
case 'error':
|
case 'error':
|
||||||
case 'canceled':
|
case 'canceled':
|
||||||
|
|||||||
@@ -31,8 +31,7 @@ function PortalController($scope, $compile, $routeParams, $rootScope, $location,
|
|||||||
|
|
||||||
var html,
|
var html,
|
||||||
e,
|
e,
|
||||||
// winHeight,
|
jobs_scope,
|
||||||
// available_height,
|
|
||||||
list = PortalJobTemplateList,
|
list = PortalJobTemplateList,
|
||||||
view= GenerateList,
|
view= GenerateList,
|
||||||
defaultUrl = GetBasePath('job_templates'),
|
defaultUrl = GetBasePath('job_templates'),
|
||||||
@@ -112,12 +111,60 @@ function PortalController($scope, $compile, $routeParams, $rootScope, $location,
|
|||||||
if ($scope.removeWidgetLoaded) {
|
if ($scope.removeWidgetLoaded) {
|
||||||
$scope.removeWidgetLoaded();
|
$scope.removeWidgetLoaded();
|
||||||
}
|
}
|
||||||
$scope.removeWidgetLoaded = $scope.$on('WidgetLoaded', function () {
|
$scope.removeWidgetLoaded = $scope.$on('WidgetLoaded', function (e, label, jobscope) {
|
||||||
|
if(label==="portal_jobs"){
|
||||||
|
jobs_scope = jobscope;
|
||||||
|
}
|
||||||
$('.actions-column:eq(0)').text('Launch');
|
$('.actions-column:eq(0)').text('Launch');
|
||||||
$('.actions-column:eq(1)').text('Details');
|
$('.actions-column:eq(1)').text('Details');
|
||||||
$('.list-well:eq(1)').css('margin-top' , '0px');
|
$('.list-well:eq(1)').css('margin-top' , '0px');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// function processEvent(event) {
|
||||||
|
// switch(event.status) {
|
||||||
|
// case 'running':
|
||||||
|
// jobs_scope.search('running_job');
|
||||||
|
// jobs_scope.search('queued_job');
|
||||||
|
|
||||||
|
// break;
|
||||||
|
// case 'new':
|
||||||
|
// case 'pending':
|
||||||
|
// case 'waiting':
|
||||||
|
// jobs_scope.search('queued_job');
|
||||||
|
|
||||||
|
// break;
|
||||||
|
// case 'successful':
|
||||||
|
// jobs_scope.search('completed_job');
|
||||||
|
// case 'failed':
|
||||||
|
// case 'error':
|
||||||
|
// case 'canceled':
|
||||||
|
// jobs_scope.search('completed_job');
|
||||||
|
// jobs_scope.search('running_job');
|
||||||
|
// jobs_scope.search('queued_job');
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
if ($rootScope.removeJobStatusChange) {
|
||||||
|
$rootScope.removeJobStatusChange();
|
||||||
|
}
|
||||||
|
$rootScope.removeJobStatusChange = $rootScope.$on('JobStatusChange', function() {
|
||||||
|
jobs_scope.refreshJobs();
|
||||||
|
// if(data.status==='pending'){
|
||||||
|
// // $scope.refresh();
|
||||||
|
// $('#portal-jobs').empty();
|
||||||
|
// // $rootScope.flashMessage = null;
|
||||||
|
// PortalJobsWidget({
|
||||||
|
// scope: $scope,
|
||||||
|
// target: 'portal-jobs',
|
||||||
|
// searchSize: 'col-lg-6 col-md-6'
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
//x`processEvent(data);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
$scope.submitJob = function (id) {
|
$scope.submitJob = function (id) {
|
||||||
PlaybookRun({ scope: $scope, id: id });
|
PlaybookRun({ scope: $scope, id: id });
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -760,7 +760,7 @@ function($location, Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialLi
|
|||||||
}
|
}
|
||||||
scope.removePlaybookLaunchFinished = scope.$on('PlaybookLaunchFinished', function(e, data) {
|
scope.removePlaybookLaunchFinished = scope.$on('PlaybookLaunchFinished', function(e, data) {
|
||||||
//var base = $location.path().replace(/^\//, '').split('/')[0];
|
//var base = $location.path().replace(/^\//, '').split('/')[0];
|
||||||
if(scope.portalMode===false){
|
if(scope.portalMode===false || scope.$parent.portalMode===false){
|
||||||
$location.path('/jobs/' + data.job);
|
$location.path('/jobs/' + data.job);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,10 +19,24 @@ angular.module('JobTemplatesHelper', ['Utilities'])
|
|||||||
* Add bits to $scope for handling callback url help
|
* Add bits to $scope for handling callback url help
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
.factory('CallbackHelpInit', ['$location', 'GetBasePath', function($location, GetBasePath) {
|
|
||||||
|
.factory('CallbackHelpInit', ['$location', 'GetBasePath', 'Rest', 'JobTemplateForm', 'GenerateForm', '$routeParams', 'LoadBreadCrumbs', 'ProcessErrors', 'ParseTypeChange',
|
||||||
|
'ParseVariableString', 'Empty', 'LookUpInit', 'InventoryList', 'CredentialList','ProjectList', 'RelatedSearchInit', 'RelatedPaginateInit',
|
||||||
|
function($location, GetBasePath, Rest, JobTemplateForm, GenerateForm, $routeParams, LoadBreadCrumbs, ProcessErrors,ParseTypeChange,
|
||||||
|
ParseVariableString, Empty, LookUpInit, InventoryList, CredentialList, ProjectList, RelatedSearchInit, RelatedPaginateInit) {
|
||||||
return function(params) {
|
return function(params) {
|
||||||
|
|
||||||
var scope = params.scope;
|
var scope = params.scope,
|
||||||
|
defaultUrl = GetBasePath('job_templates'),
|
||||||
|
// generator = GenerateForm,
|
||||||
|
form = JobTemplateForm(),
|
||||||
|
// loadingFinishedCount = 0,
|
||||||
|
// base = $location.path().replace(/^\//, '').split('/')[0],
|
||||||
|
master = {},
|
||||||
|
id = $routeParams.template_id,
|
||||||
|
relatedSets = {};
|
||||||
|
// checkSCMStatus, getPlaybooks, callback,
|
||||||
|
// choicesCount = 0;
|
||||||
|
|
||||||
// The form uses awPopOverWatch directive to 'watch' scope.callback_help for changes. Each time the
|
// The form uses awPopOverWatch directive to 'watch' scope.callback_help for changes. Each time the
|
||||||
// popover is activated, a function checks the value of scope.callback_help before constructing the content.
|
// popover is activated, a function checks the value of scope.callback_help before constructing the content.
|
||||||
@@ -56,8 +70,132 @@ angular.module('JobTemplatesHelper', ['Utilities'])
|
|||||||
scope.example_config_key = '5a8ec154832b780b9bdef1061764ae5a';
|
scope.example_config_key = '5a8ec154832b780b9bdef1061764ae5a';
|
||||||
scope.example_template_id = 'N';
|
scope.example_template_id = 'N';
|
||||||
scope.setCallbackHelp();
|
scope.setCallbackHelp();
|
||||||
|
|
||||||
|
scope.fillJobTemplate = function(){
|
||||||
|
// id = id || $rootScope.copy.id;
|
||||||
|
// Retrieve detail record and prepopulate the form
|
||||||
|
Rest.setUrl(defaultUrl + id);
|
||||||
|
Rest.get()
|
||||||
|
.success(function (data) {
|
||||||
|
var fld, i;
|
||||||
|
LoadBreadCrumbs({ path: '/job_templates/' + id, title: data.name });
|
||||||
|
for (fld in form.fields) {
|
||||||
|
if (fld !== 'variables' && data[fld] !== null && data[fld] !== undefined) {
|
||||||
|
if (form.fields[fld].type === 'select') {
|
||||||
|
if (scope[fld + '_options'] && scope[fld + '_options'].length > 0) {
|
||||||
|
for (i = 0; i < scope[fld + '_options'].length; i++) {
|
||||||
|
if (data[fld] === scope[fld + '_options'][i].value) {
|
||||||
|
scope[fld] = scope[fld + '_options'][i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scope[fld] = data[fld];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scope[fld] = data[fld];
|
||||||
|
if(fld ==='survey_enabled'){
|
||||||
|
// $scope.$emit('EnableSurvey', fld);
|
||||||
|
$('#job_templates_survey_enabled_chbox').attr('checked', scope[fld]);
|
||||||
|
if(Empty(data.summary_fields.survey)) {
|
||||||
|
$('#job_templates_delete_survey_btn').hide();
|
||||||
|
$('#job_templates_edit_survey_btn').hide();
|
||||||
|
$('#job_templates_create_survey_btn').show();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$('#job_templates_delete_survey_btn').show();
|
||||||
|
$('#job_templates_edit_survey_btn').show();
|
||||||
|
$('#job_templates_create_survey_btn').hide();
|
||||||
|
scope.survey_exists = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
master[fld] = scope[fld];
|
||||||
|
}
|
||||||
|
if (fld === 'variables') {
|
||||||
|
// Parse extra_vars, converting to YAML.
|
||||||
|
scope.variables = ParseVariableString(data.extra_vars);
|
||||||
|
master.variables = scope.variables;
|
||||||
|
}
|
||||||
|
if (form.fields[fld].type === 'lookup' && data.summary_fields[form.fields[fld].sourceModel]) {
|
||||||
|
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
|
||||||
|
data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
|
||||||
|
master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
|
||||||
|
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scope.url = data.url;
|
||||||
|
|
||||||
|
scope.ask_variables_on_launch = (data.ask_variables_on_launch) ? 'true' : 'false';
|
||||||
|
master.ask_variables_on_launch = scope.ask_variables_on_launch;
|
||||||
|
|
||||||
|
relatedSets = form.relatedSets(data.related);
|
||||||
|
|
||||||
|
if (data.host_config_key) {
|
||||||
|
scope.example_config_key = data.host_config_key;
|
||||||
|
}
|
||||||
|
scope.example_template_id = id;
|
||||||
|
scope.setCallbackHelp();
|
||||||
|
|
||||||
|
scope.callback_url = scope.callback_server_path + ((data.related.callback) ? data.related.callback :
|
||||||
|
GetBasePath('job_templates') + id + '/callback/');
|
||||||
|
master.callback_url = scope.callback_url;
|
||||||
|
|
||||||
|
LookUpInit({
|
||||||
|
scope: scope,
|
||||||
|
form: form,
|
||||||
|
current_item: data.inventory,
|
||||||
|
list: InventoryList,
|
||||||
|
field: 'inventory',
|
||||||
|
input_type: "radio"
|
||||||
|
});
|
||||||
|
|
||||||
|
LookUpInit({
|
||||||
|
url: GetBasePath('credentials') + '?kind=ssh',
|
||||||
|
scope: scope,
|
||||||
|
form: form,
|
||||||
|
current_item: data.credential,
|
||||||
|
list: CredentialList,
|
||||||
|
field: 'credential',
|
||||||
|
hdr: 'Select Machine Credential',
|
||||||
|
input_type: "radio"
|
||||||
|
});
|
||||||
|
|
||||||
|
LookUpInit({
|
||||||
|
scope: scope,
|
||||||
|
form: form,
|
||||||
|
current_item: data.project,
|
||||||
|
list: ProjectList,
|
||||||
|
field: 'project',
|
||||||
|
input_type: "radio"
|
||||||
|
});
|
||||||
|
|
||||||
|
RelatedSearchInit({
|
||||||
|
scope: scope,
|
||||||
|
form: form,
|
||||||
|
relatedSets: relatedSets
|
||||||
|
});
|
||||||
|
|
||||||
|
RelatedPaginateInit({
|
||||||
|
scope: scope,
|
||||||
|
relatedSets: relatedSets
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
scope.$emit('jobTemplateLoaded', data.related.cloud_credential);
|
||||||
|
})
|
||||||
|
.error(function (data, status) {
|
||||||
|
ProcessErrors(scope, data, status, form, {
|
||||||
|
hdr: 'Error!',
|
||||||
|
msg: 'Failed to retrieve job template: ' + $routeParams.template_id + '. GET status: ' + status
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ angular.module('VariablesHelper', ['Utilities'])
|
|||||||
json_obj = JSON.parse(variables);
|
json_obj = JSON.parse(variables);
|
||||||
json_obj = SortVariables(json_obj);
|
json_obj = SortVariables(json_obj);
|
||||||
result = jsyaml.safeDump(json_obj);
|
result = jsyaml.safeDump(json_obj);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
$log.info('Attempt to parse extra_vars as JSON failed. Attempting to parse as YAML');
|
$log.info('Attempt to parse extra_vars as JSON failed. Attempting to parse as YAML');
|
||||||
@@ -56,6 +57,7 @@ angular.module('VariablesHelper', ['Utilities'])
|
|||||||
try {
|
try {
|
||||||
json_obj = SortVariables(variables);
|
json_obj = SortVariables(variables);
|
||||||
result = jsyaml.safeDump(json_obj);
|
result = jsyaml.safeDump(json_obj);
|
||||||
|
// result = variables;
|
||||||
}
|
}
|
||||||
catch(e3) {
|
catch(e3) {
|
||||||
ProcessErrors(null, variables, e3.message, null, { hdr: 'Error!',
|
ProcessErrors(null, variables, e3.message, null, { hdr: 'Error!',
|
||||||
@@ -78,7 +80,11 @@ angular.module('VariablesHelper', ['Utilities'])
|
|||||||
**/
|
**/
|
||||||
.factory('ToJSON', ['$log', 'ProcessErrors', function($log, ProcessErrors) {
|
.factory('ToJSON', ['$log', 'ProcessErrors', function($log, ProcessErrors) {
|
||||||
return function(parseType, variables, stringify, reviver) {
|
return function(parseType, variables, stringify, reviver) {
|
||||||
var json_data, result;
|
var json_data,
|
||||||
|
result;
|
||||||
|
// bracketVar,
|
||||||
|
// key,
|
||||||
|
// lines, i, newVars = [];
|
||||||
if (parseType === 'json') {
|
if (parseType === 'json') {
|
||||||
try {
|
try {
|
||||||
//parse a JSON string
|
//parse a JSON string
|
||||||
@@ -97,7 +103,30 @@ angular.module('VariablesHelper', ['Utilities'])
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
|
// if(variables.indexOf('{{')>-1){
|
||||||
|
// lines = variables.split(/\n/);
|
||||||
|
// for(i=0; i<lines.length; i++){
|
||||||
|
// if(lines[i].indexOf('{{')>-1){
|
||||||
|
// lines[i] = lines[i].replace('{{', '"{{');
|
||||||
|
// // lines[i] = lines[i].replace(lines[i].lastIndexOf('}}'), '}}"');
|
||||||
|
// lines[i] = lines[i]+'"';
|
||||||
|
// // newVars = newVars+ lines[i];
|
||||||
|
// newVars.push(lines[i])
|
||||||
|
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// json_data = jsyaml.load(newVars.toString());
|
||||||
|
|
||||||
|
// bracketVar = variables.substr(variables.indexOf('{{'), variables.indexOf('}}'));
|
||||||
|
// bracketVar = bracketVar.trimRight();
|
||||||
|
// key = variables.substr(0, variables.indexOf(':'));
|
||||||
|
// json_data = jsyaml.load(variables);
|
||||||
|
// json_data[key] = bracketVar;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
json_data = jsyaml.load(variables);
|
json_data = jsyaml.load(variables);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch(e) {
|
||||||
json_data = {};
|
json_data = {};
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ angular.module('JobTemplatesListDefinition', [])
|
|||||||
ngHref: '#/job_templates/{{ job_template.id }}/schedules',
|
ngHref: '#/job_templates/{{ job_template.id }}/schedules',
|
||||||
awToolTip: 'Schedule future job template runs',
|
awToolTip: 'Schedule future job template runs',
|
||||||
dataPlacement: 'top',
|
dataPlacement: 'top',
|
||||||
ngHide: 'portalMode===true'
|
|
||||||
},
|
},
|
||||||
edit: {
|
edit: {
|
||||||
label: 'Edit',
|
label: 'Edit',
|
||||||
@@ -72,7 +71,6 @@ angular.module('JobTemplatesListDefinition', [])
|
|||||||
awToolTip: 'Edit template',
|
awToolTip: 'Edit template',
|
||||||
"class": 'btn-default btn-xs',
|
"class": 'btn-default btn-xs',
|
||||||
dataPlacement: 'top',
|
dataPlacement: 'top',
|
||||||
ngHide: 'portalMode===true'
|
|
||||||
},
|
},
|
||||||
"delete": {
|
"delete": {
|
||||||
label: 'Delete',
|
label: 'Delete',
|
||||||
@@ -80,7 +78,14 @@ angular.module('JobTemplatesListDefinition', [])
|
|||||||
"class": 'btn-danger btn-xs',
|
"class": 'btn-danger btn-xs',
|
||||||
awToolTip: 'Delete template',
|
awToolTip: 'Delete template',
|
||||||
dataPlacement: 'top',
|
dataPlacement: 'top',
|
||||||
ngHide: 'portalMode===true'
|
},
|
||||||
|
copy: {
|
||||||
|
label: 'Copy',
|
||||||
|
ngClick: "copyJobTemplate(job_template.id, job_template.name)",
|
||||||
|
"class": 'btn-danger btn-xs',
|
||||||
|
awToolTip: 'Copy template',
|
||||||
|
dataPlacement: 'top',
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ angular.module('PortalJobsWidget', ['RestServices', 'Utilities'])
|
|||||||
choicesCount = 0,
|
choicesCount = 0,
|
||||||
listCount = 0,
|
listCount = 0,
|
||||||
jobs_scope = scope.$new(true),
|
jobs_scope = scope.$new(true),
|
||||||
|
// completed_scope = scope.$new(true),
|
||||||
|
// running_scope = scope.$new(true),
|
||||||
|
// queued_scope = scope.$new(true),
|
||||||
// scheduled_scope = scope.$new(true),
|
// scheduled_scope = scope.$new(true),
|
||||||
max_rows,
|
max_rows,
|
||||||
html, e;
|
html, e;
|
||||||
@@ -56,7 +59,7 @@ angular.module('PortalJobsWidget', ['RestServices', 'Utilities'])
|
|||||||
listCount++;
|
listCount++;
|
||||||
if (listCount === 1) {
|
if (listCount === 1) {
|
||||||
//api_complete = true;
|
//api_complete = true;
|
||||||
scope.$emit('WidgetLoaded', jobs_scope);
|
scope.$emit('WidgetLoaded', "portal_jobs", jobs_scope);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -75,16 +78,36 @@ angular.module('PortalJobsWidget', ['RestServices', 'Utilities'])
|
|||||||
id: 'active-jobs',
|
id: 'active-jobs',
|
||||||
url: GetBasePath('unified_jobs') + '?status__in=running,completed,failed,successful,error,canceled',
|
url: GetBasePath('unified_jobs') + '?status__in=running,completed,failed,successful,error,canceled',
|
||||||
pageSize: max_rows,
|
pageSize: max_rows,
|
||||||
spinner: false
|
spinner: true
|
||||||
});
|
});
|
||||||
// LoadSchedulesScope({
|
|
||||||
|
// completed_scope.showJobType = true;
|
||||||
|
// LoadJobsScope({
|
||||||
// parent_scope: scope,
|
// parent_scope: scope,
|
||||||
// scope: scheduled_scope,
|
// scope: completed_scope,
|
||||||
// list: ScheduledJobsList,
|
// list: PortalJobsList,
|
||||||
// id: 'scheduled-jobs-tab',
|
// id: 'active-jobs',
|
||||||
// url: GetBasePath('schedules') + '?next_run__isnull=false',
|
// url: GetBasePath('unified_jobs') + '?or__status=successful&or__status=failed&or__status=error&or__status=canceled',
|
||||||
// pageSize: max_rows,
|
// // searchParams: search_params,
|
||||||
// spinner: false
|
// pageSize: max_rows
|
||||||
|
// });
|
||||||
|
|
||||||
|
// LoadJobsScope({
|
||||||
|
// parent_scope: scope,
|
||||||
|
// scope: running_scope,
|
||||||
|
// list: PortalJobsList,
|
||||||
|
// id: 'active-jobs',
|
||||||
|
// url: GetBasePath('unified_jobs') + '?status=running',
|
||||||
|
// pageSize: max_rows
|
||||||
|
// });
|
||||||
|
|
||||||
|
// LoadJobsScope({
|
||||||
|
// parent_scope: scope,
|
||||||
|
// scope: queued_scope,
|
||||||
|
// list: PortalJobsList,
|
||||||
|
// id: 'active-jobs',
|
||||||
|
// url: GetBasePath('unified_jobs') + '?or__status=pending&or__status=waiting&or__status=new',
|
||||||
|
// pageSize: max_rows
|
||||||
// });
|
// });
|
||||||
|
|
||||||
$(window).resize(_.debounce(function() {
|
$(window).resize(_.debounce(function() {
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ angular.module('SocketIO', ['AuthService', 'Utilities'])
|
|||||||
host = $location.host(),
|
host = $location.host(),
|
||||||
endpoint = params.endpoint,
|
endpoint = params.endpoint,
|
||||||
protocol = $location.protocol(),
|
protocol = $location.protocol(),
|
||||||
config, socketPort, url;
|
config, socketPort,
|
||||||
|
// handshakeData,
|
||||||
|
url;
|
||||||
|
|
||||||
// Since some pages are opened in a new tab, we might get here before AnsibleConfig is available.
|
// Since some pages are opened in a new tab, we might get here before AnsibleConfig is available.
|
||||||
// In that case, load from local storage.
|
// In that case, load from local storage.
|
||||||
@@ -61,14 +63,23 @@ angular.module('SocketIO', ['AuthService', 'Utilities'])
|
|||||||
scope: scope,
|
scope: scope,
|
||||||
url: url,
|
url: url,
|
||||||
socket: null,
|
socket: null,
|
||||||
|
|
||||||
init: function() {
|
init: function() {
|
||||||
var self = this,
|
var self = this,
|
||||||
token = Authorization.getToken();
|
token = Authorization.getToken();
|
||||||
if (!$rootScope.sessionTimer || ($rootScope.sessionTimer && !$rootScope.sessionTimer.isExpired())) {
|
if (!$rootScope.sessionTimer || ($rootScope.sessionTimer && !$rootScope.sessionTimer.isExpired())) {
|
||||||
// We have a valid session token, so attmempt socket connection
|
// We have a valid session token, so attempt socket connection
|
||||||
$log.debug('Socket connecting to: ' + url);
|
$log.debug('Socket connecting to: ' + url);
|
||||||
self.scope.socket_url = url;
|
self.scope.socket_url = url;
|
||||||
self.socket = io.connect(url, { headers:
|
// handshakeData = {
|
||||||
|
// headers: {
|
||||||
|
// 'Authorization': 'Token ' + token,
|
||||||
|
// 'X-Auth-Token': 'Token ' + token
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
self.socket = io.connect(url, {
|
||||||
|
headers:
|
||||||
{
|
{
|
||||||
'Authorization': 'Token ' + token,
|
'Authorization': 'Token ' + token,
|
||||||
'X-Auth-Token': 'Token ' + token
|
'X-Auth-Token': 'Token ' + token
|
||||||
@@ -77,7 +88,9 @@ angular.module('SocketIO', ['AuthService', 'Utilities'])
|
|||||||
'try multiple transports': false,
|
'try multiple transports': false,
|
||||||
'max reconneciton attemps': 3,
|
'max reconneciton attemps': 3,
|
||||||
'reconnection limit': 3000,
|
'reconnection limit': 3000,
|
||||||
|
'force new connection': true,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.socket.on('connection', function() {
|
self.socket.on('connection', function() {
|
||||||
$log.debug('Socket connecting...');
|
$log.debug('Socket connecting...');
|
||||||
self.scope.$apply(function () {
|
self.scope.$apply(function () {
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ angular.module('GeneratorHelpers', [])
|
|||||||
icon = 'fa-list-ul';
|
icon = 'fa-list-ul';
|
||||||
break;
|
break;
|
||||||
case 'copy':
|
case 'copy':
|
||||||
icon = "fa-cut";
|
icon = "fa-copy";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
icon += (size) ? " " + size : "";
|
icon += (size) ? " " + size : "";
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
<a href="/#/jobs/{{ job_id }}/stdout" id="view-stdout-button" target="_blank" type="button" class="btn btn-primary btn-xs" aw-tool-tip="View standard out. Opens in new tab or window." data-placement="top"><i class="fa fa-external-link"></i></a>
|
<a href="/#/jobs/{{ job_id }}/stdout" id="view-stdout-button" target="_blank" type="button" class="btn btn-primary btn-xs" aw-tool-tip="View standard out. Opens in new tab or window." data-placement="top"><i class="fa fa-external-link"></i></a>
|
||||||
<button type="button" class="btn btn-xs btn-primary ng-hide" ng-click="refresh()" id="refresh_btn" aw-tool-tip="Refresh the page" data-placement="top" ng-show="socketStatus == 'error'"
|
<button type="button" class="btn btn-xs btn-primary ng-hide" ng-click="refresh()" id="refresh_btn" aw-tool-tip="Refresh the page" data-placement="top" ng-show="socketStatus == 'error'"
|
||||||
data-original-title="" title=""><i class="fa fa-refresh"></i></button>
|
data-original-title="" title=""><i class="fa fa-refresh"></i></button>
|
||||||
<a href="" ng-click="deleteJob()" id="cancel-job-button" ng-show="job_status.status == 'running'" type="button" class="btn btn-primary btn-xs" aw-tool-tip="Cancel" data-placement="top"><i class="fa fa-minus-circle"></i></a>
|
<a href="" ng-click="deleteJob()" id="cancel-job-button" ng-show="job_status.status == 'running' || job_status.status=='pending' " type="button" class="btn btn-primary btn-xs" aw-tool-tip="Cancel" data-placement="top"><i class="fa fa-minus-circle"></i></a>
|
||||||
<a href="" ng-click="deleteJob()" id="delete-job-button" ng-show="job_status.status != 'running'" type="button" class="btn btn-primary btn-xs" aw-tool-tip="Delete" data-placement="top"><i class="fa fa-trash-o"></i></a>
|
<a href="" ng-click="deleteJob()" id="delete-job-button" ng-hide="job_status.status == 'running' || job_status.status == 'pending' " type="button" class="btn btn-primary btn-xs" aw-tool-tip="Delete" data-placement="top"><i class="fa fa-trash-o"></i></a>
|
||||||
<a href="" ng-click="relaunchJob()" id="relaunch-job-button" type="button" class="btn btn-primary btn-xs" aw-tool-tip="Relaunch using the same parameters" data-placement="top"><i class="fa fa-rocket"></i></a>
|
<a href="" ng-click="relaunchJob()" id="relaunch-job-button" type="button" class="btn btn-primary btn-xs" aw-tool-tip="Relaunch using the same parameters" data-placement="top"><i class="fa fa-rocket"></i></a>
|
||||||
<button type="button" id="summary-button" class="btn btn-primary btn-xs" ng-click="toggleSummary()" aw-tool-tip="View summary" data-placement="top"><i class="fa fa-arrow-circle-left"></i></button>
|
<button type="button" id="summary-button" class="btn btn-primary btn-xs" ng-click="toggleSummary()" aw-tool-tip="View summary" data-placement="top"><i class="fa fa-arrow-circle-left"></i></button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,4 +3,12 @@
|
|||||||
<div ng-include="'/static/partials/schedule_dialog.html'"></div>
|
<div ng-include="'/static/partials/schedule_dialog.html'"></div>
|
||||||
<div ng-include="'/static/partials/logviewer.html'"></div>
|
<div ng-include="'/static/partials/logviewer.html'"></div>
|
||||||
<div id="survey-modal-dialog"></div>
|
<div id="survey-modal-dialog"></div>
|
||||||
|
|
||||||
|
<div id="copy-job-modal" style="display:none">
|
||||||
|
<form name="copy_form" id="copy_form">
|
||||||
|
What would you like to name the copy of job template <b><span id=job_name></span></b>?<br>
|
||||||
|
<input id="new_copy_name" name="new_copy_name" ng-model ="new_copy_name" ng-required="true" class="form-control ng-pristine ng-invalid-required ng-invalid" style="margin-top:10px;">
|
||||||
|
<div class="error survey_error ng-hide" ng-show="copy_form.new_copy_name.$dirty && copy_form.new_copy_name.$error.required">A value is required!</div></input>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
Reference in New Issue
Block a user