mirror of
https://github.com/ansible/awx.git
synced 2026-05-08 09:57:35 -02:30
Merge branch 'master' into expunge-zeromq-unstable
Conflicts: setup/roles/awx_install/handlers/main.yml
This commit is contained in:
@@ -41,7 +41,7 @@ from awx.main.utils import update_scm_url, get_type_for_model, get_model_for_typ
|
|||||||
logger = logging.getLogger('awx.api.serializers')
|
logger = logging.getLogger('awx.api.serializers')
|
||||||
|
|
||||||
# Fields that should be summarized regardless of object type.
|
# Fields that should be summarized regardless of object type.
|
||||||
DEFAULT_SUMMARY_FIELDS = ('name', 'description')#, 'type')
|
DEFAULT_SUMMARY_FIELDS = ('name', 'description')#, 'created_by', 'modified_by')#, 'type')
|
||||||
|
|
||||||
# Keys are fields (foreign keys) where, if found on an instance, summary info
|
# Keys are fields (foreign keys) where, if found on an instance, summary info
|
||||||
# should be added to the serialized data. Values are a tuple of field names on
|
# should be added to the serialized data. Values are a tuple of field names on
|
||||||
@@ -49,7 +49,7 @@ DEFAULT_SUMMARY_FIELDS = ('name', 'description')#, 'type')
|
|||||||
# the related object).
|
# the related object).
|
||||||
SUMMARIZABLE_FK_FIELDS = {
|
SUMMARIZABLE_FK_FIELDS = {
|
||||||
'organization': DEFAULT_SUMMARY_FIELDS,
|
'organization': DEFAULT_SUMMARY_FIELDS,
|
||||||
'user': ('username', 'first_name', 'last_name'),
|
'user': ('id', 'username', 'first_name', 'last_name'),
|
||||||
'team': DEFAULT_SUMMARY_FIELDS,
|
'team': DEFAULT_SUMMARY_FIELDS,
|
||||||
'inventory': DEFAULT_SUMMARY_FIELDS + ('has_active_failures',
|
'inventory': DEFAULT_SUMMARY_FIELDS + ('has_active_failures',
|
||||||
'total_hosts',
|
'total_hosts',
|
||||||
@@ -289,6 +289,15 @@ class BaseSerializer(serializers.ModelSerializer):
|
|||||||
# Can be raised by the reverse accessor for a OneToOneField.
|
# Can be raised by the reverse accessor for a OneToOneField.
|
||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
if getattr(obj, 'created_by', None) and obj.created_by.is_active:
|
||||||
|
summary_fields['created_by'] = SortedDict()
|
||||||
|
for field in SUMMARIZABLE_FK_FIELDS['user']:
|
||||||
|
summary_fields['created_by'][field] = getattr(obj.created_by, field)
|
||||||
|
if getattr(obj, 'modified_by', None) and obj.modified_by.is_active:
|
||||||
|
summary_fields['modified_by'] = SortedDict()
|
||||||
|
for field in SUMMARIZABLE_FK_FIELDS['user']:
|
||||||
|
summary_fields['modified_by'][field] = getattr(obj.modified_by, field)
|
||||||
|
print summary_fields
|
||||||
return summary_fields
|
return summary_fields
|
||||||
|
|
||||||
def get_created(self, obj):
|
def get_created(self, obj):
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
# Python
|
# Python
|
||||||
import datetime
|
import datetime
|
||||||
import dateutil
|
import dateutil
|
||||||
|
import functools
|
||||||
import time
|
import time
|
||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
@@ -431,30 +432,32 @@ class DashboardInventoryGraphView(APIView):
|
|||||||
return Response(dashboard_data)
|
return Response(dashboard_data)
|
||||||
|
|
||||||
|
|
||||||
class UserCreateAPIMixin(object):
|
def disallow_superuser_escalation(cls):
|
||||||
"""A mixin subclass that ensures that only a superuser is able to create
|
"""Decorator that ensures that the post, put, and patch methods on the
|
||||||
another superuser.
|
class, if they exist, perform a sanity check and disallow superuser
|
||||||
|
escalation by non-superusers.
|
||||||
"""
|
"""
|
||||||
def post(self, request, pk=None):
|
# Create a method decorator that ensures superuser escalation by
|
||||||
self._superuser_sanity_check(request)
|
# non-superusers is disallowed.
|
||||||
return super(UserCreateAPIMixin, self).post(request, pk=pk)
|
def superuser_lockdown(method):
|
||||||
|
@functools.wraps(method)
|
||||||
|
def fx(self, request, *a, **kw):
|
||||||
|
if not request.user.is_superuser:
|
||||||
|
if request.DATA.get('is_superuser', False):
|
||||||
|
raise PermissionDenied('Only superusers may create '
|
||||||
|
'other superusers.')
|
||||||
|
return method(self, request, *a, **kw)
|
||||||
|
return fx
|
||||||
|
|
||||||
# def put(self, request, pk=None):
|
# Ensure that if post, put, or patch methods exist, that they are decorated
|
||||||
# self._superuser_sanity_check(request)
|
# with the sanity check decorator.
|
||||||
# return super(UserCreateAPIMixin, self).put(request, pk=pk)
|
for vuln_method in ('post', 'put', 'patch'):
|
||||||
|
original_method = getattr(cls, vuln_method, None)
|
||||||
|
if original_method is not None:
|
||||||
|
setattr(cls, vuln_method, superuser_lockdown(original_method))
|
||||||
|
|
||||||
# def patch(self, request, pk=None):
|
# Return the class object.
|
||||||
# self._superuser_sanity_check(request)
|
return cls
|
||||||
# return super(UserCreateAPIMixin, self).patch(request, pk=pk)
|
|
||||||
|
|
||||||
def _superuser_sanity_check(self, request):
|
|
||||||
"""Ensure that if a non-superuser tries to create a superuser,
|
|
||||||
that the request is rejected.
|
|
||||||
"""
|
|
||||||
if not request.user.is_superuser:
|
|
||||||
if request.DATA.get('is_superuser', False):
|
|
||||||
raise PermissionDenied('Only superusers may create '
|
|
||||||
'other superusers.')
|
|
||||||
|
|
||||||
|
|
||||||
class ScheduleList(ListAPIView):
|
class ScheduleList(ListAPIView):
|
||||||
@@ -518,14 +521,16 @@ class OrganizationInventoriesList(SubListAPIView):
|
|||||||
parent_model = Organization
|
parent_model = Organization
|
||||||
relationship = 'inventories'
|
relationship = 'inventories'
|
||||||
|
|
||||||
class OrganizationUsersList(UserCreateAPIMixin, SubListCreateAPIView):
|
@disallow_superuser_escalation
|
||||||
|
class OrganizationUsersList(SubListCreateAPIView):
|
||||||
|
|
||||||
model = User
|
model = User
|
||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
parent_model = Organization
|
parent_model = Organization
|
||||||
relationship = 'users'
|
relationship = 'users'
|
||||||
|
|
||||||
class OrganizationAdminsList(UserCreateAPIMixin, SubListCreateAPIView):
|
@disallow_superuser_escalation
|
||||||
|
class OrganizationAdminsList(SubListCreateAPIView):
|
||||||
|
|
||||||
model = User
|
model = User
|
||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
@@ -565,7 +570,8 @@ class TeamDetail(RetrieveUpdateDestroyAPIView):
|
|||||||
model = Team
|
model = Team
|
||||||
serializer_class = TeamSerializer
|
serializer_class = TeamSerializer
|
||||||
|
|
||||||
class TeamUsersList(UserCreateAPIMixin, SubListCreateAPIView):
|
@disallow_superuser_escalation
|
||||||
|
class TeamUsersList(SubListCreateAPIView):
|
||||||
|
|
||||||
model = User
|
model = User
|
||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
@@ -762,7 +768,9 @@ class ProjectUpdateCancel(GenericAPIView):
|
|||||||
else:
|
else:
|
||||||
return self.http_method_not_allowed(request, *args, **kwargs)
|
return self.http_method_not_allowed(request, *args, **kwargs)
|
||||||
|
|
||||||
class UserList(UserCreateAPIMixin, ListCreateAPIView):
|
|
||||||
|
@disallow_superuser_escalation
|
||||||
|
class UserList(ListCreateAPIView):
|
||||||
|
|
||||||
model = User
|
model = User
|
||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
@@ -841,6 +849,7 @@ class UserActivityStreamList(SubListAPIView):
|
|||||||
return qs.filter(Q(actor=parent) | Q(user__in=[parent]))
|
return qs.filter(Q(actor=parent) | Q(user__in=[parent]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class UserDetail(RetrieveUpdateDestroyAPIView):
|
class UserDetail(RetrieveUpdateDestroyAPIView):
|
||||||
|
|
||||||
model = User
|
model = User
|
||||||
@@ -1467,6 +1476,7 @@ class JobTemplateLaunch(GenericAPIView):
|
|||||||
data['passwords_needed_to_start'] = obj.passwords_needed_to_start
|
data['passwords_needed_to_start'] = obj.passwords_needed_to_start
|
||||||
data['ask_variables_on_launch'] = obj.ask_variables_on_launch
|
data['ask_variables_on_launch'] = obj.ask_variables_on_launch
|
||||||
data['variables_needed_to_start'] = obj.variables_needed_to_start
|
data['variables_needed_to_start'] = obj.variables_needed_to_start
|
||||||
|
data['credential_needed_to_start'] = obj.credential is None
|
||||||
data['survey_enabled'] = obj.survey_enabled
|
data['survey_enabled'] = obj.survey_enabled
|
||||||
return Response(data)
|
return Response(data)
|
||||||
|
|
||||||
|
|||||||
@@ -826,41 +826,56 @@ class JobTemplateAccess(BaseAccess):
|
|||||||
org_admin_qs = base_qs.filter(
|
org_admin_qs = base_qs.filter(
|
||||||
project__organizations__admins__in=[self.user]
|
project__organizations__admins__in=[self.user]
|
||||||
)
|
)
|
||||||
allowed = [PERM_JOBTEMPLATE_CREATE, PERM_INVENTORY_CHECK, PERM_INVENTORY_DEPLOY]
|
allowed = [PERM_INVENTORY_CHECK, PERM_INVENTORY_DEPLOY]
|
||||||
perm_qs = base_qs.filter(
|
allowed_deploy = [PERM_JOBTEMPLATE_CREATE, PERM_INVENTORY_DEPLOY]
|
||||||
|
allowed_check = [PERM_JOBTEMPLATE_CREATE, PERM_INVENTORY_DEPLOY, PERM_INVENTORY_CHECK]
|
||||||
|
|
||||||
|
# perm_qs = base_qs.filter(
|
||||||
|
# Q(inventory__permissions__user=self.user) | Q(inventory__permissions__team__users__in=[self.user]),
|
||||||
|
# Q(project__permissions__user=self.user) | Q(project__permissions__team__users__in=[self.user]),
|
||||||
|
# inventory__permissions__permission_type__in=allowed,
|
||||||
|
# project__permissions__permission_type__in=allowed,
|
||||||
|
# inventory__permissions__active=True,
|
||||||
|
# project__permissions__active=True,
|
||||||
|
# inventory__permissions__pk=F('project__permissions__pk'),
|
||||||
|
# )
|
||||||
|
|
||||||
|
perm_deploy_qs = base_qs.filter(
|
||||||
Q(inventory__permissions__user=self.user) | Q(inventory__permissions__team__users__in=[self.user]),
|
Q(inventory__permissions__user=self.user) | Q(inventory__permissions__team__users__in=[self.user]),
|
||||||
Q(project__permissions__user=self.user) | Q(project__permissions__team__users__in=[self.user]),
|
Q(project__permissions__user=self.user) | Q(project__permissions__team__users__in=[self.user]),
|
||||||
inventory__permissions__permission_type__in=allowed,
|
job_type=PERM_INVENTORY_DEPLOY,
|
||||||
project__permissions__permission_type__in=allowed,
|
inventory__permissions__permission_type__in=allowed_deploy,
|
||||||
|
project__permissions__permission_type__in=allowed_deploy,
|
||||||
inventory__permissions__active=True,
|
inventory__permissions__active=True,
|
||||||
project__permissions__active=True,
|
project__permissions__active=True,
|
||||||
inventory__permissions__pk=F('project__permissions__pk'),
|
inventory__permissions__pk=F('project__permissions__pk'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
perm_check_qs = base_qs.filter(
|
||||||
|
Q(inventory__permissions__user=self.user) | Q(inventory__permissions__team__users__in=[self.user]),
|
||||||
|
Q(project__permissions__user=self.user) | Q(project__permissions__team__users__in=[self.user]),
|
||||||
|
job_type=PERM_INVENTORY_CHECK,
|
||||||
|
inventory__permissions__permission_type__in=allowed_check,
|
||||||
|
project__permissions__permission_type__in=allowed_check,
|
||||||
|
inventory__permissions__active=True,
|
||||||
|
project__permissions__active=True,
|
||||||
|
inventory__permissions__pk=F('project__permissions__pk'),
|
||||||
|
)
|
||||||
|
|
||||||
# FIXME: I *think* this should work... needs more testing.
|
# FIXME: I *think* this should work... needs more testing.
|
||||||
return org_admin_qs | perm_qs
|
return org_admin_qs | perm_deploy_qs | perm_check_qs
|
||||||
|
|
||||||
def can_read(self, obj):
|
def can_read(self, obj):
|
||||||
# you can only see the job templates that you have permission to launch.
|
# you can only see the job templates that you have permission to launch.
|
||||||
data = {
|
return self.can_start(obj)
|
||||||
'job_type': obj.job_type,
|
|
||||||
}
|
|
||||||
if obj.inventory and obj.inventory.pk:
|
|
||||||
data['inventory'] = obj.inventory.pk
|
|
||||||
if obj.project and obj.project.pk:
|
|
||||||
data['project'] = obj.project.pk
|
|
||||||
if obj.credential:
|
|
||||||
data['credential'] = obj.credential.pk
|
|
||||||
if obj.cloud_credential:
|
|
||||||
data['cloud_credential'] = obj.cloud_credential.pk
|
|
||||||
return self.can_add(data)
|
|
||||||
|
|
||||||
def can_add(self, data):
|
def can_add(self, data):
|
||||||
'''
|
'''
|
||||||
a user can create a job template if they are a superuser, an org admin
|
a user can create a job template if they are a superuser, an org admin
|
||||||
of any org that the project is a member, or if they have user or team
|
of any org that the project is a member, or if they have user or team
|
||||||
based permissions tying the project to the inventory source for the
|
based permissions tying the project to the inventory source for the
|
||||||
given action. users who are able to create deploy jobs can also make
|
given action as well as the 'create' deploy permission.
|
||||||
check (dry run) jobs.
|
Users who are able to create deploy jobs can also run normal and check (dry run) jobs.
|
||||||
'''
|
'''
|
||||||
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
|
||||||
@@ -950,29 +965,32 @@ class JobTemplateAccess(BaseAccess):
|
|||||||
if obj.inventory is None or obj.project is None:
|
if obj.inventory is None or obj.project is None:
|
||||||
return False
|
return False
|
||||||
# If the user has admin access to the project they can start a job
|
# If the user has admin access to the project they can start a job
|
||||||
if self.user.can_access(Project, 'admin', obj.project):
|
if self.user.can_access(Project, 'admin', obj.project, None):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Otherwise check for explicitly granted permissions
|
# Otherwise check for explicitly granted permissions
|
||||||
permission_qs = Permission.objects.filter(
|
permission_qs = Permission.objects.filter(
|
||||||
Q(user=self.user) | Q(team__users__in=[self.user]),
|
Q(user=self.user) | Q(team__users__in=[self.user]),
|
||||||
inventory=inventory,
|
inventory=obj.inventory,
|
||||||
project=project,
|
project=obj.project,
|
||||||
permission_type__in=[PERM_JOBTEMPLATE_CREATE, PERM_INVENTORY_CHECK, PERM_INVENTORY_DEPLOY],
|
permission_type__in=[PERM_JOBTEMPLATE_CREATE, PERM_INVENTORY_CHECK, PERM_INVENTORY_DEPLOY],
|
||||||
)
|
)
|
||||||
|
|
||||||
has_perm = False
|
has_perm = False
|
||||||
for perm in permission_qs:
|
for perm in permission_qs:
|
||||||
# If you have job template create permission that implies both CHECK and DEPLOY
|
# If you have job template create permission that implies both CHECK and DEPLOY
|
||||||
# If you have DEPLOY permissions you can run both CHECK and DEPLOY
|
# If you have DEPLOY permissions you can run both CHECK and DEPLOY
|
||||||
if perm.permission_type in [PERM_JOBTEMPLATE_CREATE, PERM_INVENTORY_DEPLOY]:
|
if perm.permission_type in [PERM_JOBTEMPLATE_CREATE, PERM_INVENTORY_DEPLOY] and \
|
||||||
|
obj.job_type == PERM_INVENTORY_DEPLOY:
|
||||||
has_perm = True
|
has_perm = True
|
||||||
# If you only have CHECK permission then you can only run CHECK
|
# If you only have CHECK permission then you can only run CHECK
|
||||||
if perm.permission_type == PERM_INVENTORY_CHECK and perm.permission_type == PERM_INVENTORY_CHECK:
|
if perm.permission_type in [PERM_JOBTEMPLATE_CREATE, PERM_INVENTORY_DEPLOY, PERM_INVENTORY_CHECK] and \
|
||||||
|
obj.job_type == PERM_INVENTORY_CHECK:
|
||||||
has_perm = True
|
has_perm = True
|
||||||
|
|
||||||
dep_access = self.user.can_access(Inventory, 'read', obj.inventory) and \
|
dep_access = self.user.can_access(Inventory, 'read', obj.inventory) and \
|
||||||
self.user.can_access(Project, 'read', obj.project)
|
self.user.can_access(Project, 'read', obj.project)
|
||||||
return self.can_read(obj) and dep_access and has_perm
|
return dep_access and has_perm
|
||||||
|
|
||||||
def can_change(self, obj, data):
|
def can_change(self, obj, data):
|
||||||
return self.can_read(obj) and self.can_add(data)
|
return self.can_read(obj) and self.can_add(data)
|
||||||
@@ -998,17 +1016,44 @@ class JobAccess(BaseAccess):
|
|||||||
project__organizations__admins__in=[self.user]
|
project__organizations__admins__in=[self.user]
|
||||||
)
|
)
|
||||||
allowed = [PERM_INVENTORY_CHECK, PERM_INVENTORY_DEPLOY]
|
allowed = [PERM_INVENTORY_CHECK, PERM_INVENTORY_DEPLOY]
|
||||||
perm_qs = base_qs.filter(
|
|
||||||
|
allowed_deploy = [PERM_JOBTEMPLATE_CREATE, PERM_INVENTORY_DEPLOY]
|
||||||
|
allowed_check = [PERM_JOBTEMPLATE_CREATE, PERM_INVENTORY_DEPLOY, PERM_INVENTORY_CHECK]
|
||||||
|
|
||||||
|
# perm_qs = base_qs.filter(
|
||||||
|
# Q(inventory__permissions__user=self.user) | Q(inventory__permissions__team__users__in=[self.user]),
|
||||||
|
# Q(project__permissions__user=self.user) | Q(project__permissions__team__users__in=[self.user]),
|
||||||
|
# inventory__permissions__permission_type__in=allowed,
|
||||||
|
# project__permissions__permission_type__in=allowed,
|
||||||
|
# inventory__permissions__active=True,
|
||||||
|
# project__permissions__active=True,
|
||||||
|
# inventory__permissions__pk=F('project__permissions__pk'),
|
||||||
|
# )
|
||||||
|
|
||||||
|
perm_deploy_qs = base_qs.filter(
|
||||||
Q(inventory__permissions__user=self.user) | Q(inventory__permissions__team__users__in=[self.user]),
|
Q(inventory__permissions__user=self.user) | Q(inventory__permissions__team__users__in=[self.user]),
|
||||||
Q(project__permissions__user=self.user) | Q(project__permissions__team__users__in=[self.user]),
|
Q(project__permissions__user=self.user) | Q(project__permissions__team__users__in=[self.user]),
|
||||||
inventory__permissions__permission_type__in=allowed,
|
job_type=PERM_INVENTORY_DEPLOY,
|
||||||
project__permissions__permission_type__in=allowed,
|
inventory__permissions__permission_type__in=allowed_deploy,
|
||||||
|
project__permissions__permission_type__in=allowed_deploy,
|
||||||
inventory__permissions__active=True,
|
inventory__permissions__active=True,
|
||||||
project__permissions__active=True,
|
project__permissions__active=True,
|
||||||
inventory__permissions__pk=F('project__permissions__pk'),
|
inventory__permissions__pk=F('project__permissions__pk'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
perm_check_qs = base_qs.filter(
|
||||||
|
Q(inventory__permissions__user=self.user) | Q(inventory__permissions__team__users__in=[self.user]),
|
||||||
|
Q(project__permissions__user=self.user) | Q(project__permissions__team__users__in=[self.user]),
|
||||||
|
job_type=PERM_INVENTORY_CHECK,
|
||||||
|
inventory__permissions__permission_type__in=allowed_check,
|
||||||
|
project__permissions__permission_type__in=allowed_check,
|
||||||
|
inventory__permissions__active=True,
|
||||||
|
project__permissions__active=True,
|
||||||
|
inventory__permissions__pk=F('project__permissions__pk'),
|
||||||
|
)
|
||||||
|
|
||||||
# FIXME: I *think* this should work... needs more testing.
|
# FIXME: I *think* this should work... needs more testing.
|
||||||
return org_admin_qs | perm_qs
|
return org_admin_qs | perm_deploy_qs | perm_check_qs
|
||||||
|
|
||||||
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?
|
||||||
|
|||||||
@@ -339,12 +339,13 @@ class BaseTask(Task):
|
|||||||
- /etc/tower (to prevent obtaining db info or secret key)
|
- /etc/tower (to prevent obtaining db info or secret key)
|
||||||
- /var/lib/awx (except for current project)
|
- /var/lib/awx (except for current project)
|
||||||
- /var/log/tower
|
- /var/log/tower
|
||||||
|
- /var/log/supervisor
|
||||||
- /tmp (except for own tmp files)
|
- /tmp (except for own tmp files)
|
||||||
'''
|
'''
|
||||||
new_args = [getattr(settings, 'AWX_PROOT_CMD', 'proot'), '-r', '/']
|
new_args = [getattr(settings, 'AWX_PROOT_CMD', 'proot'), '-r', '/']
|
||||||
hide_paths = ['/etc/tower', '/var/lib/awx', '/var/log/tower',
|
hide_paths = ['/etc/tower', '/var/lib/awx', '/var/log/tower',
|
||||||
tempfile.gettempdir(), settings.PROJECTS_ROOT,
|
'/var/log/supervisor', tempfile.gettempdir(),
|
||||||
settings.JOBOUTPUT_ROOT]
|
settings.PROJECTS_ROOT, settings.JOBOUTPUT_ROOT]
|
||||||
hide_paths.extend(getattr(settings, 'AWX_PROOT_HIDE_PATHS', None) or [])
|
hide_paths.extend(getattr(settings, 'AWX_PROOT_HIDE_PATHS', None) or [])
|
||||||
for path in sorted(set(hide_paths)):
|
for path in sorted(set(hide_paths)):
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
@@ -1052,7 +1053,7 @@ 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 str(env_k) not in os.environ:
|
if str(env_k) not in os.environ and str(env_k) not in settings.INV_ENV_VARIABLE_BLACKLIST:
|
||||||
env[str(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
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
# Python
|
# Python
|
||||||
from distutils.version import StrictVersion as Version
|
from distutils.version import StrictVersion as Version
|
||||||
|
import glob
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
@@ -176,6 +177,15 @@ TEST_PROOT_PLAYBOOK = '''
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "not temp_stat.stat.exists"
|
- "not temp_stat.stat.exists"
|
||||||
|
- name: check for supervisor log path
|
||||||
|
stat: path={{ supervisor_log_path }}
|
||||||
|
register: supervisor_log_stat
|
||||||
|
when: supervisor_log_path is defined
|
||||||
|
- name: check that supervisor log path was not found
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- "not supervisor_log_stat.stat.exists"
|
||||||
|
when: supervisor_log_path is defined
|
||||||
- name: try to run a tower-manage command
|
- name: try to run a tower-manage command
|
||||||
command: tower-manage validate
|
command: tower-manage validate
|
||||||
ignore_errors: true
|
ignore_errors: true
|
||||||
@@ -1353,6 +1363,11 @@ class RunJobTest(BaseCeleryTest):
|
|||||||
# Create a temp directory that should not be visible to the playbook.
|
# Create a temp directory that should not be visible to the playbook.
|
||||||
temp_path = tempfile.mkdtemp()
|
temp_path = tempfile.mkdtemp()
|
||||||
self._temp_paths.append(temp_path)
|
self._temp_paths.append(temp_path)
|
||||||
|
# Find a file in supervisor logs that should not be visible.
|
||||||
|
try:
|
||||||
|
supervisor_log_path = glob.glob('/var/log/supervisor/*')[0]
|
||||||
|
except IndexError:
|
||||||
|
supervisor_log_path = None
|
||||||
# Create our test project and job template.
|
# Create our test project and job template.
|
||||||
self.create_test_project(TEST_PROOT_PLAYBOOK)
|
self.create_test_project(TEST_PROOT_PLAYBOOK)
|
||||||
project_path = self.project.local_path
|
project_path = self.project.local_path
|
||||||
@@ -1364,6 +1379,8 @@ class RunJobTest(BaseCeleryTest):
|
|||||||
'other_project_path': other_project_path,
|
'other_project_path': other_project_path,
|
||||||
'temp_path': temp_path,
|
'temp_path': temp_path,
|
||||||
}
|
}
|
||||||
|
if supervisor_log_path:
|
||||||
|
extra_vars['supervisor_log_path'] = supervisor_log_path
|
||||||
job = self.create_test_job(job_template=job_template, verbosity=3,
|
job = self.create_test_job(job_template=job_template, verbosity=3,
|
||||||
extra_vars=json.dumps(extra_vars))
|
extra_vars=json.dumps(extra_vars))
|
||||||
self.assertEqual(job.status, 'new')
|
self.assertEqual(job.status, 'new')
|
||||||
|
|||||||
@@ -193,10 +193,13 @@ class VMwareInventory(object):
|
|||||||
host_info = {
|
host_info = {
|
||||||
'name': host.name,
|
'name': host.name,
|
||||||
'tag': host.tag,
|
'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 attr in ('datastore', 'network', 'vm'):
|
||||||
|
try:
|
||||||
|
value = getattr(host, attr)
|
||||||
|
host_info['%ss' % attr] = self._get_obj_info(value, depth=0)
|
||||||
|
except AttributeError:
|
||||||
|
host_info['%ss' % attr] = []
|
||||||
for k, v in self._get_obj_info(host.summary, depth=0).items():
|
for k, v in self._get_obj_info(host.summary, depth=0).items():
|
||||||
if isinstance(v, collections.MutableMapping):
|
if isinstance(v, collections.MutableMapping):
|
||||||
for k2, v2 in v.items():
|
for k2, v2 in v.items():
|
||||||
@@ -219,11 +222,21 @@ class VMwareInventory(object):
|
|||||||
vm_info = {
|
vm_info = {
|
||||||
'name': vm.name,
|
'name': vm.name,
|
||||||
'tag': vm.tag,
|
'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 attr in ('datastore', 'network'):
|
||||||
|
try:
|
||||||
|
value = getattr(vm, attr)
|
||||||
|
vm_info['%ss' % attr] = self._get_obj_info(value, depth=0)
|
||||||
|
except AttributeError:
|
||||||
|
vm_info['%ss' % attr] = []
|
||||||
|
try:
|
||||||
|
vm_info['resourcePool'] = self._get_obj_info(vm.resourcePool, depth=0)
|
||||||
|
except AttributeError:
|
||||||
|
vm_info['resourcePool'] = ''
|
||||||
|
try:
|
||||||
|
vm_info['guestState'] = vm.guest.guestState
|
||||||
|
except AttributeError:
|
||||||
|
vm_info['guestState'] = ''
|
||||||
for k, v in self._get_obj_info(vm.summary, depth=0).items():
|
for k, v in self._get_obj_info(vm.summary, depth=0).items():
|
||||||
if isinstance(v, collections.MutableMapping):
|
if isinstance(v, collections.MutableMapping):
|
||||||
for k2, v2 in v.items():
|
for k2, v2 in v.items():
|
||||||
|
|||||||
@@ -351,6 +351,8 @@ RAX_GROUP_FILTER = r'^(?!instance-.+).+$'
|
|||||||
RAX_HOST_FILTER = r'^.+$'
|
RAX_HOST_FILTER = r'^.+$'
|
||||||
RAX_EXCLUDE_EMPTY_GROUPS = True
|
RAX_EXCLUDE_EMPTY_GROUPS = True
|
||||||
|
|
||||||
|
INV_ENV_VARIABLE_BLACKLIST = ("HOME", "_")
|
||||||
|
|
||||||
# ----------------
|
# ----------------
|
||||||
# -- Amazon EC2 --
|
# -- Amazon EC2 --
|
||||||
# ----------------
|
# ----------------
|
||||||
|
|||||||
@@ -649,6 +649,10 @@ angular.module('Tower', [
|
|||||||
$AnsibleConfig = Store('AnsibleConfig');
|
$AnsibleConfig = Store('AnsibleConfig');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//the authorization controller redirects to the home page automatcially if there is no last path defined. in order to override
|
||||||
|
// this, set the last path to /portal for instances where portal is visited for the first time.
|
||||||
|
$rootScope.lastPath = ($location.path() === "/portal") ? 'portal' : undefined;
|
||||||
|
|
||||||
LoadConfig();
|
LoadConfig();
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -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: true, // Enable console logging messages
|
debug_mode: false, // 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:
|
||||||
|
|||||||
@@ -77,10 +77,9 @@ function JobsListController ($rootScope, $log, $scope, $compile, $routeParams, C
|
|||||||
case 'pending':
|
case 'pending':
|
||||||
case 'waiting':
|
case 'waiting':
|
||||||
queued_scope.search('queued_job');
|
queued_scope.search('queued_job');
|
||||||
break;
|
|
||||||
case 'successful':
|
|
||||||
completed_scope.search('completed_job');
|
completed_scope.search('completed_job');
|
||||||
break;
|
break;
|
||||||
|
case 'successful':
|
||||||
case 'failed':
|
case 'failed':
|
||||||
case 'error':
|
case 'error':
|
||||||
case 'canceled':
|
case 'canceled':
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ function PortalController($scope, $compile, $routeParams, $rootScope, $location,
|
|||||||
searchSize: 'col-lg-6 col-md-6'
|
searchSize: 'col-lg-6 col-md-6'
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootScope.flashMessage = null;
|
|
||||||
|
|
||||||
SearchInit({
|
SearchInit({
|
||||||
scope: $scope,
|
scope: $scope,
|
||||||
@@ -120,49 +119,11 @@ function PortalController($scope, $compile, $routeParams, $rootScope, $location,
|
|||||||
$('.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) {
|
if ($rootScope.removeJobStatusChange) {
|
||||||
$rootScope.removeJobStatusChange();
|
$rootScope.removeJobStatusChange();
|
||||||
}
|
}
|
||||||
$rootScope.removeJobStatusChange = $rootScope.$on('JobStatusChange', function() {
|
$rootScope.removeJobStatusChange = $rootScope.$on('JobStatusChange', function() {
|
||||||
jobs_scope.refreshJobs();
|
jobs_scope.search('portal_job'); //processEvent(event);
|
||||||
// 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) {
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential
|
|||||||
$('#password-modal').dialog('close');
|
$('#password-modal').dialog('close');
|
||||||
}
|
}
|
||||||
scope.$emit(callback, data);
|
scope.$emit(callback, data);
|
||||||
scope.$destroy();
|
|
||||||
})
|
})
|
||||||
.error(function(data, status) {
|
.error(function(data, status) {
|
||||||
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
|
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
|
||||||
@@ -241,7 +240,7 @@ function($location, Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialLi
|
|||||||
html += "<label for=\"" + fld + "\">" + field.label + "</label>\n";
|
html += "<label for=\"" + fld + "\">" + field.label + "</label>\n";
|
||||||
html += "<input type=\"password\" ";
|
html += "<input type=\"password\" ";
|
||||||
html += "ng-model=\"" + fld + '" ';
|
html += "ng-model=\"" + fld + '" ';
|
||||||
html += "ng-keydown=\"keydown($event)\" ";
|
// html += "ng-keydown=\"keydown($event)\" ";
|
||||||
html += 'name="' + fld + '" ';
|
html += 'name="' + fld + '" ';
|
||||||
html += "class=\"password-field form-control input-sm\" ";
|
html += "class=\"password-field form-control input-sm\" ";
|
||||||
html += (field.associated) ? "ng-change=\"clearPWConfirm('" + field.associated + "')\" " : "";
|
html += (field.associated) ? "ng-change=\"clearPWConfirm('" + field.associated + "')\" " : "";
|
||||||
@@ -262,7 +261,7 @@ function($location, Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialLi
|
|||||||
html += "<label for=\"" + fld + "\"> " + field.label + "</label>\n";
|
html += "<label for=\"" + fld + "\"> " + field.label + "</label>\n";
|
||||||
html += "<input type=\"password\" ";
|
html += "<input type=\"password\" ";
|
||||||
html += "ng-model=\"" + fld + '" ';
|
html += "ng-model=\"" + fld + '" ';
|
||||||
html += "ng-keydown=\"keydown($event)\" ";
|
// html += "ng-keydown=\"keydown($event)\" ";
|
||||||
html += 'name="' + fld + '" ';
|
html += 'name="' + fld + '" ';
|
||||||
html += "class=\"form-control input-sm\" ";
|
html += "class=\"form-control input-sm\" ";
|
||||||
html += "ng-change=\"checkStatus()\" ";
|
html += "ng-change=\"checkStatus()\" ";
|
||||||
@@ -323,11 +322,11 @@ function($location, Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialLi
|
|||||||
// $('#password-modal').dialog('open');
|
// $('#password-modal').dialog('open');
|
||||||
// $('#password-accept-button').attr({ "disabled": "disabled" });
|
// $('#password-accept-button').attr({ "disabled": "disabled" });
|
||||||
// });
|
// });
|
||||||
scope.keydown = function(e){
|
// scope.keydown = function(e){
|
||||||
if(e.keyCode===13){
|
// if(e.keyCode===13){
|
||||||
scope.passwordAccept();
|
// scope.passwordAccept();
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
// scope.passwordAccept = function() {
|
// scope.passwordAccept = function() {
|
||||||
// if (!scope.password_form.$invalid) {
|
// if (!scope.password_form.$invalid) {
|
||||||
@@ -764,7 +763,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 || scope.$parent.portalMode===false){
|
if(scope.portalMode===false || scope.$parent.portalMode===false ){
|
||||||
$location.path('/jobs/' + data.job);
|
$location.path('/jobs/' + data.job);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,6 +87,9 @@ angular.module('JobsHelper', ['Utilities', 'RestServices', 'FormGenerator', 'Job
|
|||||||
else if (scope.jobs) {
|
else if (scope.jobs) {
|
||||||
list = scope.jobs;
|
list = scope.jobs;
|
||||||
}
|
}
|
||||||
|
else if(scope.portal_jobs){
|
||||||
|
list=scope.portal_jobs;
|
||||||
|
}
|
||||||
job = Find({ list: list, key: 'id', val: id });
|
job = Find({ list: list, key: 'id', val: id });
|
||||||
if (job.type === 'job') {
|
if (job.type === 'job') {
|
||||||
if(scope.$parent.portalMode===true){
|
if(scope.$parent.portalMode===true){
|
||||||
@@ -405,6 +408,9 @@ angular.module('JobsHelper', ['Utilities', 'RestServices', 'FormGenerator', 'Job
|
|||||||
JobsControllerInit({ scope: scope, parent_scope: parent_scope });
|
JobsControllerInit({ scope: scope, parent_scope: parent_scope });
|
||||||
JobsListUpdate({ scope: scope, parent_scope: parent_scope, list: list });
|
JobsListUpdate({ scope: scope, parent_scope: parent_scope, list: list });
|
||||||
parent_scope.$emit('listLoaded');
|
parent_scope.$emit('listLoaded');
|
||||||
|
// setTimeout(function(){
|
||||||
|
// scope.$apply();
|
||||||
|
// }, 300);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (base === 'jobs' && list.name === 'completed_jobs') {
|
if (base === 'jobs' && list.name === 'completed_jobs') {
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
angular.module('PortalJobsListDefinition', [])
|
angular.module('PortalJobsListDefinition', [])
|
||||||
.value( 'PortalJobsList', {
|
.value( 'PortalJobsList', {
|
||||||
|
|
||||||
name: 'jobs',
|
name: 'portal_jobs',
|
||||||
iterator: 'job',
|
iterator: 'portal_job',
|
||||||
editTitle: 'Jobs',
|
editTitle: 'Jobs',
|
||||||
'class': 'table-condensed',
|
'class': 'table-condensed',
|
||||||
index: false,
|
index: false,
|
||||||
@@ -39,8 +39,8 @@ angular.module('PortalJobsListDefinition', [])
|
|||||||
columnClass: 'col-lg-1 col-md-2 col-sm-2 col-xs-2',
|
columnClass: 'col-lg-1 col-md-2 col-sm-2 col-xs-2',
|
||||||
// awToolTip: "{{ job.status_tip }}",
|
// awToolTip: "{{ job.status_tip }}",
|
||||||
// awTipPlacement: "top",
|
// awTipPlacement: "top",
|
||||||
dataTitle: "{{ job.status_popover_title }}",
|
dataTitle: "{{ portal_job.status_popover_title }}",
|
||||||
icon: 'icon-job-{{ job.status }}',
|
icon: 'icon-job-{{ portal_job.status }}',
|
||||||
iconOnly: true,
|
iconOnly: true,
|
||||||
// ngClick:"viewJobLog(job.id)",
|
// ngClick:"viewJobLog(job.id)",
|
||||||
searchable: true,
|
searchable: true,
|
||||||
@@ -73,7 +73,7 @@ angular.module('PortalJobsListDefinition', [])
|
|||||||
fieldActions: {
|
fieldActions: {
|
||||||
job_details: {
|
job_details: {
|
||||||
mode: 'all',
|
mode: 'all',
|
||||||
ngClick: "viewJobLog(job.id)",
|
ngClick: "viewJobLog(portal_job.id)",
|
||||||
awToolTip: 'View job details',
|
awToolTip: 'View job details',
|
||||||
dataPlacement: 'top'
|
dataPlacement: 'top'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,23 +19,12 @@ 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),
|
|
||||||
max_rows,
|
max_rows,
|
||||||
|
user,
|
||||||
html, e;
|
html, e;
|
||||||
|
|
||||||
html = '';
|
html = '';
|
||||||
html += "<div class=\"portal-job-template-container\">\n";
|
html += "<div class=\"portal-job-template-container\">\n";
|
||||||
// html+= "<span id='portal-job-template-header'>Job Templates </span>";
|
|
||||||
// html += "<ul id=\"job_status_tabs\" class=\"nav nav-tabs\">\n";
|
|
||||||
// html += "<li class=\"active\"><a id=\"active_jobs_link\" ng-click=\"toggleTab($event, 'active_jobs_link', 'job_status_tabs')\"\n";
|
|
||||||
// html += " href=\"#active-jobs-tab\" data-toggle=\"tab\">Jobs</a></li>\n";
|
|
||||||
// html += "<li><a id=\"scheduled_jobs_link\" ng-click=\"toggleTab($event, 'scheduled_jobs_link', 'job_status_tabs')\"\n";
|
|
||||||
// html += "href=\"#scheduled-jobs-tab\" data-toggle=\"tab\">Schedule</a></li>\n";
|
|
||||||
// html += "</ul>\n";
|
|
||||||
// html += "<div id=\"portal-job-template-tab-content\" class=\"tab-content \">\n";
|
|
||||||
html += "<div class=\"tab-pane active\" id=\"active-jobs-tab\">\n";
|
html += "<div class=\"tab-pane active\" id=\"active-jobs-tab\">\n";
|
||||||
html += "<div class=\"row search-row\" id='portal-job-template-search'>\n";
|
html += "<div class=\"row search-row\" id='portal-job-template-search'>\n";
|
||||||
html += "<div class=\"col-lg-6 col-md-6\" id=\"active-jobs-search-container\"></div>\n";
|
html += "<div class=\"col-lg-6 col-md-6\" id=\"active-jobs-search-container\"></div>\n";
|
||||||
@@ -44,8 +33,6 @@ angular.module('PortalJobsWidget', ['RestServices', 'Utilities'])
|
|||||||
html += "<div id=\"active-jobs\" class=\"job-list-target\"></div>\n";
|
html += "<div id=\"active-jobs\" class=\"job-list-target\"></div>\n";
|
||||||
html += "</div>\n"; //list
|
html += "</div>\n"; //list
|
||||||
html += "</div>\n"; //active-jobs-tab
|
html += "</div>\n"; //active-jobs-tab
|
||||||
// html += "<div class=\"tab-pane\" id=\"scheduled-jobs-tab\"></div>\n";
|
|
||||||
// html += "</div>\n"; // jobs-list-container
|
|
||||||
html += "</div>\n";
|
html += "</div>\n";
|
||||||
|
|
||||||
e = angular.element(document.getElementById(target));
|
e = angular.element(document.getElementById(target));
|
||||||
@@ -71,44 +58,17 @@ angular.module('PortalJobsWidget', ['RestServices', 'Utilities'])
|
|||||||
if (PortalJobsList.fields.type) {
|
if (PortalJobsList.fields.type) {
|
||||||
PortalJobsList.fields.type.searchOptions = scope.type_choices;
|
PortalJobsList.fields.type.searchOptions = scope.type_choices;
|
||||||
}
|
}
|
||||||
|
user = scope.$parent.current_user.id;
|
||||||
LoadJobsScope({
|
LoadJobsScope({
|
||||||
parent_scope: scope,
|
parent_scope: scope,
|
||||||
scope: jobs_scope,
|
scope: jobs_scope,
|
||||||
list: PortalJobsList,
|
list: PortalJobsList,
|
||||||
id: 'active-jobs',
|
id: 'active-jobs',
|
||||||
url: GetBasePath('unified_jobs') + '?status__in=running,completed,failed,successful,error,canceled',
|
url: GetBasePath('jobs')+'?created_by='+user,
|
||||||
pageSize: max_rows,
|
pageSize: max_rows,
|
||||||
spinner: true
|
spinner: true
|
||||||
});
|
});
|
||||||
|
|
||||||
// completed_scope.showJobType = true;
|
|
||||||
// LoadJobsScope({
|
|
||||||
// parent_scope: scope,
|
|
||||||
// scope: completed_scope,
|
|
||||||
// list: PortalJobsList,
|
|
||||||
// id: 'active-jobs',
|
|
||||||
// url: GetBasePath('unified_jobs') + '?or__status=successful&or__status=failed&or__status=error&or__status=canceled',
|
|
||||||
// // searchParams: search_params,
|
|
||||||
// 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() {
|
||||||
resizePortalJobsWidget();
|
resizePortalJobsWidget();
|
||||||
|
|||||||
@@ -64,7 +64,16 @@ angular.module('AuthService', ['ngCookies', 'Utilities'])
|
|||||||
//$rootScope.$destroy();
|
//$rootScope.$destroy();
|
||||||
$cookieStore.remove('token_expires');
|
$cookieStore.remove('token_expires');
|
||||||
$cookieStore.remove('current_user');
|
$cookieStore.remove('current_user');
|
||||||
$cookieStore.remove('lastPath');
|
|
||||||
|
if($cookieStore.get('lastPath')==='/portal'){
|
||||||
|
$cookieStore.put( 'lastPath', '/portal');
|
||||||
|
$rootScope.lastPath = '/portal';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$cookieStore.remove('lastPath');
|
||||||
|
$rootScope.lastPath = '/home';
|
||||||
|
}
|
||||||
|
|
||||||
$cookieStore.remove('token');
|
$cookieStore.remove('token');
|
||||||
$cookieStore.put('userLoggedIn', false);
|
$cookieStore.put('userLoggedIn', false);
|
||||||
$cookieStore.put('sessionExpired', false);
|
$cookieStore.put('sessionExpired', false);
|
||||||
@@ -75,7 +84,6 @@ angular.module('AuthService', ['ngCookies', 'Utilities'])
|
|||||||
$rootScope.sessionExpired = false;
|
$rootScope.sessionExpired = false;
|
||||||
$rootScope.token = null;
|
$rootScope.token = null;
|
||||||
$rootScope.token_expires = null;
|
$rootScope.token_expires = null;
|
||||||
$rootScope.lastPath = '/home';
|
|
||||||
$rootScope.login_username = null;
|
$rootScope.login_username = null;
|
||||||
$rootScope.login_password = null;
|
$rootScope.login_password = null;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ angular.module('SocketIO', ['AuthService', 'Utilities'])
|
|||||||
endpoint = params.endpoint,
|
endpoint = params.endpoint,
|
||||||
protocol = $location.protocol(),
|
protocol = $location.protocol(),
|
||||||
config, socketPort,
|
config, socketPort,
|
||||||
// handshakeData,
|
|
||||||
url;
|
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.
|
||||||
|
|||||||
Reference in New Issue
Block a user