Merge branch 'downstream' into devel

This commit is contained in:
Ryan Petrello 2019-05-03 07:58:25 -04:00
commit 8d75fc5f56
No known key found for this signature in database
GPG Key ID: F2AA5F2122351777
33 changed files with 198 additions and 76 deletions

View File

@ -15,6 +15,7 @@ aim_inputs = {
'id': 'url',
'label': _('CyberArk AIM URL'),
'type': 'string',
'format': 'url',
}, {
'id': 'app_id',
'label': _('Application ID'),

View File

@ -10,6 +10,7 @@ azure_keyvault_inputs = {
'id': 'url',
'label': _('Vault URL (DNS Name)'),
'type': 'string',
'format': 'url',
}, {
'id': 'client',
'label': _('Client ID'),

View File

@ -16,6 +16,7 @@ conjur_inputs = {
'id': 'url',
'label': _('Conjur URL'),
'type': 'string',
'format': 'url',
}, {
'id': 'api_key',
'label': _('API Key'),

View File

@ -14,6 +14,7 @@ base_inputs = {
'id': 'url',
'label': _('Server URL'),
'type': 'string',
'format': 'url',
'help_text': _('The URL to the HashiCorp Vault'),
}, {
'id': 'token',

View File

@ -493,6 +493,23 @@ def format_ssh_private_key(value):
return True
@JSONSchemaField.format_checker.checks('url')
def format_url(value):
try:
parsed = urllib.parse.urlparse(value)
except Exception as e:
raise jsonschema.exceptions.FormatError(str(e))
if parsed.scheme == '':
raise jsonschema.exceptions.FormatError(
'Invalid URL: Missing url scheme (http, https, etc.)'
)
if parsed.netloc == '':
raise jsonschema.exceptions.FormatError(
'Invalid URL: {}'.format(value)
)
return True
class DynamicCredentialInputField(JSONSchemaField):
"""
Used to validate JSON for
@ -725,7 +742,7 @@ class CredentialTypeInputField(JSONSchemaField):
'type': 'object',
'properties': {
'type': {'enum': ['string', 'boolean']},
'format': {'enum': ['ssh_private_key']},
'format': {'enum': ['ssh_private_key', 'url']},
'choices': {
'type': 'array',
'minItems': 1,

View File

@ -1042,7 +1042,7 @@ class BaseTask(object):
AWX only saves the parent_uuid if the event is for a Job.
'''
if event_data.get(self.event_data_key, None):
if event_data[self.event_data_key] != 'job_id':
if self.event_data_key != 'job_id':
event_data.pop('parent_uuid', None)
should_write_event = False
event_data.setdefault(self.event_data_key, self.instance.id)

View File

@ -1942,3 +1942,39 @@ def test_create_credential_missing_user_team_org_xfail(post, admin, credentialty
admin
)
assert response.status_code == 400
@pytest.mark.parametrize('url, status, msg', [
('foo.com', 400, 'Invalid URL: Missing url scheme (http, https, etc.)'),
('https://[dead:beef', 400, 'Invalid IPv6 URL'),
('http:domain:8080', 400, 'Invalid URL: http:domain:8080'),
('http:/domain:8080', 400, 'Invalid URL: http:/domain:8080'),
('http://foo.com', 201, None)
])
@pytest.mark.django_db
def test_create_credential_with_invalid_url_xfail(post, organization, admin, url, status, msg):
credential_type = CredentialType(
kind='test',
name='MyTestCredentialType',
inputs = {
'fields': [{
'id': 'server_url',
'label': 'Server Url',
'type': 'string',
'format': 'url'
}]
}
)
credential_type.save()
params = {
'name': 'Second Best Credential Ever',
'organization': organization.pk,
'credential_type': credential_type.pk,
'inputs': {'server_url': url}
}
endpoint = reverse('api:credential_list', kwargs={'version': 'v2'})
response = post(endpoint, params, admin)
assert response.status_code == status
if status != 201:
assert response.data['inputs']['server_url'] == [msg]

View File

@ -38,13 +38,6 @@ function ApplicationsStrings (BaseString) {
ns.inputs = {
ORGANIZATION_PLACEHOLDER: t.s('SELECT AN ORGANIZATION')
};
ns.sort = {
NAME_ASCENDING: t.s('Name (Ascending)'),
NAME_DESCENDING: t.s('Name (Descending)'),
USERNAME_ASCENDING: t.s('Username (Ascending)'),
USERNAME_DESCENDING: t.s('Username (Descending)')
};
}
ApplicationsStrings.$inject = ['BaseStringService'];

View File

@ -41,10 +41,13 @@ function ListApplicationsUsersController (
vm.toolbarSortOptions = [
toolbarSortDefault,
{
label: `${strings.get('sort.USERNAME_DESCENDING')}`,
value: '-user__username'
}
{ label: `${strings.get('sort.USERNAME_DESCENDING')}`, value: '-user__username' },
{ label: `${strings.get('sort.CREATED_ASCENDING')}`, value: 'created' },
{ label: `${strings.get('sort.CREATED_DESCENDING')}`, value: '-created' },
{ label: `${strings.get('sort.MODIFIED_ASCENDING')}`, value: 'modified' },
{ label: `${strings.get('sort.MODIFIED_DESCENDING')}`, value: '-modified' },
{ label: `${strings.get('sort.EXPIRES_ASCENDING')}`, value: 'expires' },
{ label: `${strings.get('sort.EXPIRES_DESCENDING')}`, value: '-expires' }
];
function setToolbarSort () {

View File

@ -54,7 +54,9 @@ function ListApplicationsController (
vm.toolbarSortOptions = [
toolbarSortDefault,
{ label: `${strings.get('sort.NAME_DESCENDING')}`, value: '-name' }
{ label: `${strings.get('sort.NAME_DESCENDING')}`, value: '-name' },
{ label: `${strings.get('sort.CREATED_ASCENDING')}`, value: 'created' },
{ label: `${strings.get('sort.CREATED_DESCENDING')}`, value: '-created' }
];
vm.toolbarSortValue = toolbarSortDefault;

View File

@ -5,6 +5,10 @@ function ExternalTestModalController (strings) {
vm.strings = strings;
vm.title = strings.get('externalTest.TITLE');
vm.$onInit = () => {
vm.form.save = () => vm.onSubmit();
};
}
ExternalTestModalController.$inject = [

View File

@ -6,7 +6,10 @@ function InputSourceLookupController (strings, wait) {
vm.strings = strings;
vm.title = strings.get('inputSources.TITLE');
vm.$onInit = () => wait('start');
vm.$onInit = () => {
wait('start');
vm.form.save = () => vm.onTest();
};
vm.onReady = () => {
vm.isReady = true;

View File

@ -4,13 +4,6 @@ function JobsStrings (BaseString) {
const { t } = this;
const ns = this.jobs;
ns.sort = {
NAME_ASCENDING: t.s('Name (Ascending)'),
NAME_DESCENDING: t.s('Name (Descending)'),
START_TIME: t.s('Start Time'),
FINISH_TIME: t.s('Finish Time')
};
ns.list = {
PANEL_TITLE: t.s('JOBS'),
ROW_ITEM_LABEL_STARTED: t.s('Started'),

View File

@ -46,7 +46,7 @@ function ListJobsController (
}, true);
const toolbarSortDefault = {
label: `${strings.get('sort.FINISH_TIME')}`,
label: `${strings.get('sort.FINISH_TIME_DESCENDING')}`,
value: '-finished'
};
@ -63,7 +63,13 @@ function ListJobsController (
vm.toolbarSortOptions = [
{ label: `${strings.get('sort.NAME_ASCENDING')}`, value: 'name' },
{ label: `${strings.get('sort.NAME_DESCENDING')}`, value: '-name' },
{ label: `${strings.get('sort.START_TIME')}`, value: 'finished' },
{ label: `${strings.get('sort.FINISH_TIME_ASCENDING')}`, value: 'finished' },
{ label: `${strings.get('sort.START_TIME_ASCENDING')}`, value: 'started' },
{ label: `${strings.get('sort.START_TIME_DESCENDING')}`, value: '-started' },
{ label: `${strings.get('sort.LAUNCHED_BY_ASCENDING')}`, value: 'created_by__id' },
{ label: `${strings.get('sort.LAUNCHED_BY_DESCENDING')}`, value: '-created_by__id' },
{ label: `${strings.get('sort.PROJECT_ASCENDING')}`, value: 'unified_job_template__project__id' },
{ label: `${strings.get('sort.PROJECT_DESCENDING')}`, value: '-unified_job_template__project__id' },
toolbarSortDefault
];

View File

@ -79,6 +79,10 @@
&:hover div {
background-color: white;
}
&--hidden {
display: none;
}
}
&-row--clickable {

View File

@ -439,7 +439,7 @@ function togglePanelExpand () {
const iconCollapsed = 'fa-angle-right';
const iconExpanded = 'fa-angle-down';
const iconSelector = '.at-Stdout-toggle > i';
const lineCollapsed = 'hidden';
const lineCollapsed = 'at-Stdout-row--hidden';
function toggleCollapseAll () {
if (scroll.isPaused()) return;
@ -524,11 +524,15 @@ function togglePlayCollapse (uuid) {
taskIcons.addClass(iconCollapsed);
lines.addClass(lineCollapsed);
descendants
.map(item => $(`.child-of-${item}`))
.forEach(line => line.addClass(lineCollapsed));
}
descendants
.map(item => render.records[item])
.filter(({ name }) => name === EVENT_START_TASK)
.filter((descRecord) => descRecord && descRecord.name === EVENT_START_TASK)
.forEach(rec => { render.records[rec.uuid].isCollapsed = true; });
render.records[uuid].isCollapsed = !isCollapsed;

View File

@ -204,7 +204,7 @@ function JobRenderService ($q, $compile, $sce, $window, strings) {
return { html: '', count: 0 };
}
if (event.uuid && this.records[event.uuid]) {
if (event.uuid && this.records[event.uuid] && !this.records[event.uuid]._isIncomplete) {
return { html: '', count: 0 };
}
@ -272,6 +272,9 @@ function JobRenderService ($q, $compile, $sce, $window, strings) {
isClickable = true;
}
const children = (this.records[event.uuid] && this.records[event.uuid].children)
? this.records[event.uuid].children : [];
const record = {
isClickable,
id: event.id,
@ -285,6 +288,7 @@ function JobRenderService ($q, $compile, $sce, $window, strings) {
lineCount: lines.length,
isCollapsed: this.state.collapseAll,
counters: [event.counter],
children
};
if (event.parent_uuid) {
@ -307,12 +311,18 @@ function JobRenderService ($q, $compile, $sce, $window, strings) {
if (event.parent_uuid) {
if (this.records[event.parent_uuid]) {
if (this.records[event.parent_uuid].children &&
!this.records[event.parent_uuid].children.includes(event.uuid)) {
this.records[event.parent_uuid].children.push(event.uuid);
if (this.records[event.parent_uuid].children) {
if (!this.records[event.parent_uuid].children.includes(event.uuid)) {
this.records[event.parent_uuid].children.push(event.uuid);
}
} else {
this.records[event.parent_uuid].children = [event.uuid];
}
} else {
this.records[event.parent_uuid] = {
_isIncomplete: true,
children: [event.uuid]
};
}
}
}
@ -397,7 +407,7 @@ function JobRenderService ($q, $compile, $sce, $window, strings) {
if (record && record.isCollapsed) {
if (record.level === 3 || record.level === 0) {
classList += ' hidden';
classList += ' at-Stdout-row--hidden';
}
}

View File

@ -46,11 +46,6 @@ function ProjectsStrings (BaseString) {
HEADER: this.error.HEADER,
CALL: this.error.CALL,
};
ns.sort = {
NAME_ASCENDING: t.s('Name (Ascending)'),
NAME_DESCENDING: t.s('Name (Descending)')
};
}
ProjectsStrings.$inject = ['BaseStringService'];

View File

@ -68,10 +68,13 @@ function projectsListController (
vm.toolbarSortOptions = [
toolbarSortDefault,
{
label: `${strings.get('sort.NAME_DESCENDING')}`,
value: '-name'
}
{ label: `${strings.get('sort.NAME_DESCENDING')}`, value: '-name' },
{ label: `${strings.get('sort.MODIFIED_ASCENDING')}`, value: 'modified' },
{ label: `${strings.get('sort.MODIFIED_DESCENDING')}`, value: '-modified' },
{ label: `${strings.get('sort.LAST_USED_ASCENDING')}`, value: 'last_job_run' },
{ label: `${strings.get('sort.LAST_USED_DESCENDING')}`, value: '-last_job_run' },
{ label: `${strings.get('sort.ORGANIZATION_ASCENDING')}`, value: 'organization' },
{ label: `${strings.get('sort.ORGANIZATION_DESCENDING')}`, value: '-organization' }
];
vm.toolbarSortValue = toolbarSortDefault;

View File

@ -143,11 +143,6 @@ function TemplatesStrings (BaseString) {
CANCEL: t.s('CANCEL'),
SAVE_AND_EXIT: t.s('SAVE & EXIT')
};
ns.sort = {
NAME_ASCENDING: t.s('Name (Ascending)'),
NAME_DESCENDING: t.s('Name (Descending)')
};
}
TemplatesStrings.$inject = ['BaseStringService'];

View File

@ -71,7 +71,15 @@ function ListTemplatesController(
vm.toolbarSortOptions = [
toolbarSortDefault,
{ label: `${strings.get('sort.NAME_DESCENDING')}`, value: '-name' }
{ label: `${strings.get('sort.NAME_DESCENDING')}`, value: '-name' },
{ label: `${strings.get('sort.MODIFIED_ASCENDING')}`, value: 'modified' },
{ label: `${strings.get('sort.MODIFIED_DESCENDING')}`, value: '-modified' },
{ label: `${strings.get('sort.LAST_JOB_RUN_ASCENDING')}`, value: 'last_job_run' },
{ label: `${strings.get('sort.LAST_JOB_RUN_DESCENDING')}`, value: '-last_job_run' },
{ label: `${strings.get('sort.INVENTORY_ASCENDING')}`, value: 'job_template__inventory__id' },
{ label: `${strings.get('sort.INVENTORY_DESCENDING')}`, value: '-job_template__inventory__id' },
{ label: `${strings.get('sort.PROJECT_ASCENDING')}`, value: 'jobtemplate__project__id' },
{ label: `${strings.get('sort.PROJECT_DESCENDING')}`, value: '-jobtemplate__project__id' },
];
vm.toolbarSortValue = toolbarSortDefault;

View File

@ -41,11 +41,6 @@ function TokensStrings (BaseString) {
PERSONAL_ACCESS_TOKEN: t.s('Personal Access Token'),
HEADER: appName => t.s('{{ appName }} Token', { appName }),
};
ns.sort = {
NAME_ASCENDING: t.s('Name (Ascending)'),
NAME_DESCENDING: t.s('Name (Descending)')
};
}
TokensStrings.$inject = ['BaseStringService'];

View File

@ -50,10 +50,13 @@ function ListTokensController (
vm.toolbarSortOptions = [
toolbarSortDefault,
{
label: `${strings.get('sort.NAME_DESCENDING')}`,
value: '-application__name'
}
{ label: `${strings.get('sort.NAME_DESCENDING')}`, value: '-application__name' },
{ label: `${strings.get('sort.CREATED_ASCENDING')}`, value: 'created' },
{ label: `${strings.get('sort.CREATED_DESCENDING')}`, value: '-created' },
{ label: `${strings.get('sort.MODIFIED_ASCENDING')}`, value: 'modified' },
{ label: `${strings.get('sort.MODIFIED_DESCENDING')}`, value: '-modified' },
{ label: `${strings.get('sort.EXPIRES_ASCENDING')}`, value: 'expires' },
{ label: `${strings.get('sort.EXPIRES_DESCENDING')}`, value: '-expires' }
];
function setToolbarSort () {

View File

@ -103,6 +103,39 @@ function BaseStringService (namespace) {
CANCEL: resourceType => t.s('Cancel the {{resourceType}}', { resourceType })
};
this.sort = {
NAME_ASCENDING: t.s('Name (Ascending)'),
NAME_DESCENDING: t.s('Name (Descending)'),
CREATED_ASCENDING: t.s('Created (Ascending)'),
CREATED_DESCENDING: t.s('Created (Descending)'),
MODIFIED_ASCENDING: t.s('Modified (Ascending)'),
MODIFIED_DESCENDING: t.s('Modified (Descending)'),
EXPIRES_ASCENDING: t.s('Expires (Ascending)'),
EXPIRES_DESCENDING: t.s('Expires (Descending)'),
LAST_JOB_RUN_ASCENDING: t.s('Last Run (Ascending)'),
LAST_JOB_RUN_DESCENDING: t.s('Last Run (Descending)'),
LAST_USED_ASCENDING: t.s('Last Used (Ascending)'),
LAST_USED_DESCENDING: t.s('Last Used (Descending)'),
USERNAME_ASCENDING: t.s('Username (Ascending)'),
USERNAME_DESCENDING: t.s('Username (Descending)'),
START_TIME_ASCENDING: t.s('Start Time (Ascending)'),
START_TIME_DESCENDING: t.s('Start Time (Descending)'),
FINISH_TIME_ASCENDING: t.s('Finish Time (Ascending)'),
FINISH_TIME_DESCENDING: t.s('Finish Time (Descending)'),
UUID_ASCENDING: t.s('UUID (Ascending)'),
UUID_DESCENDING: t.s('UUID (Descending)'),
LAUNCHED_BY_ASCENDING: t.s('Launched By (Ascending)'),
LAUNCHED_BY_DESCENDING: t.s('Launched By (Descending)'),
INVENTORY_ASCENDING: t.s('Inventory (Ascending)'),
INVENTORY_DESCENDING: t.s('Inventory (Descending)'),
PROJECT_ASCENDING: t.s('Project (Ascending)'),
PROJECT_DESCENDING: t.s('Project (Descending)'),
ORGANIZATION_ASCENDING: t.s('Organization (Ascending)'),
ORGANIZATION_DESCENDING: t.s('Organization (Descending)'),
CAPACITY_ASCENDING: t.s('Capacity (Ascending)'),
CAPACITY_DESCENDING: t.s('Capacity (Descending)')
};
this.ALERT = ({ header, body }) => t.s('{{ header }} {{ body }}', { header, body });
/**

View File

@ -96,6 +96,11 @@ function JobStatusGraph($window, adjustGraphSize, templateUrl, i18n, moment, gra
job_status_chart.interactiveLayer.tooltip.fixedTop(-10); //distance from the top of the chart to tooltip
job_status_chart.interactiveLayer.tooltip.distance(-1); //distance from interactive line to tooltip
scope.$on('$destroy', function() {
job_status_chart.tooltip.hidden(true);
job_status_chart.interactiveLayer.tooltip.hidden(true);
});
job_status_chart.xAxis
.axisLabel(i18n._("TIME"))//.showMaxMin(true)
.tickFormat(function(d) {

View File

@ -62,11 +62,6 @@ function InstanceGroupsStrings (BaseString) {
ns.alert = {
MISSING_PARAMETER: t.s('Instance Group parameter is missing.'),
};
ns.sort = {
NAME_ASCENDING: t.s('Name (Ascending)'),
NAME_DESCENDING: t.s('Name (Descending)')
};
}
InstanceGroupsStrings.$inject = ['BaseStringService'];

View File

@ -42,10 +42,15 @@ function InstanceModalController ($scope, $state, Dataset, models, strings, Proc
vm.toolbarSortValue = toolbarSortDefault;
vm.toolbarSortOptions = [
toolbarSortDefault,
{
label: `${strings.get('sort.NAME_DESCENDING')}`,
value: '-hostname'
}
{ label: `${strings.get('sort.NAME_DESCENDING')}`, value: '-hostname' },
{ label: `${strings.get('sort.UUID_ASCENDING')}`, value: 'uuid' },
{ label: `${strings.get('sort.UUID_DESCENDING')}`, value: '-uuid' },
{ label: `${strings.get('sort.CREATED_ASCENDING')}`, value: 'created' },
{ label: `${strings.get('sort.CREATED_DESCENDING')}`, value: '-created' },
{ label: `${strings.get('sort.MODIFIED_ASCENDING')}`, value: 'modified' },
{ label: `${strings.get('sort.MODIFIED_DESCENDING')}`, value: '-modified' },
{ label: `${strings.get('sort.CAPACITY_ASCENDING')}`, value: 'capacity' },
{ label: `${strings.get('sort.CAPACITY_DESCENDING')}`, value: '-capacity' }
];
const removeStateParamsListener = $scope.$watchCollection('$state.params', () => {

View File

@ -24,10 +24,15 @@ function InstancesController ($scope, $state, $http, $transitions, models, strin
vm.toolbarSortValue = toolbarSortDefault;
vm.toolbarSortOptions = [
toolbarSortDefault,
{
label: `${strings.get('sort.NAME_DESCENDING')}`,
value: '-hostname'
}
{ label: `${strings.get('sort.NAME_DESCENDING')}`, value: '-hostname' },
{ label: `${strings.get('sort.UUID_ASCENDING')}`, value: 'uuid' },
{ label: `${strings.get('sort.UUID_DESCENDING')}`, value: '-uuid' },
{ label: `${strings.get('sort.CREATED_ASCENDING')}`, value: 'created' },
{ label: `${strings.get('sort.CREATED_DESCENDING')}`, value: '-created' },
{ label: `${strings.get('sort.MODIFIED_ASCENDING')}`, value: 'modified' },
{ label: `${strings.get('sort.MODIFIED_DESCENDING')}`, value: '-modified' },
{ label: `${strings.get('sort.CAPACITY_ASCENDING')}`, value: 'capacity' },
{ label: `${strings.get('sort.CAPACITY_DESCENDING')}`, value: '-capacity' }
];
const removeStateParamsListener = $scope.$watchCollection('$state.params', () => {

View File

@ -43,10 +43,11 @@ export default ['$scope', '$filter', '$state', 'Alert', 'resolvedModels', 'Datas
vm.toolbarSortOptions = [
toolbarSortDefault,
{
label: `${strings.get('sort.NAME_DESCENDING')}`,
value: '-name'
}
{ label: `${strings.get('sort.NAME_DESCENDING')}`, value: '-name' },
{ label: `${strings.get('sort.CREATED_ASCENDING')}`, value: 'created' },
{ label: `${strings.get('sort.CREATED_DESCENDING')}`, value: '-created' },
{ label: `${strings.get('sort.MODIFIED_ASCENDING')}`, value: 'modified' },
{ label: `${strings.get('sort.MODIFIED_DESCENDING')}`, value: '-modified' }
];
vm.toolbarSortValue = toolbarSortDefault;

View File

@ -154,7 +154,7 @@ export default [ 'ProcessErrors', 'CredentialTypeModel', 'TemplatesStrings', '$f
_disabled: (order === 1 || vm.readOnlyPrompts) ? false : true,
order: order
};
activeTab = activeTab || vm.steps.credentials.tab;
activeTab = activeTab || vm.steps.credential.tab;
order++;
}
if(vm.promptDataClone.launchConf.ask_verbosity_on_launch || vm.promptDataClone.launchConf.ask_job_type_on_launch || vm.promptDataClone.launchConf.ask_limit_on_launch || vm.promptDataClone.launchConf.ask_tags_on_launch || vm.promptDataClone.launchConf.ask_skip_tags_on_launch || (vm.promptDataClone.launchConf.ask_variables_on_launch && !vm.promptDataClone.launchConf.ignore_ask_variables) || vm.promptDataClone.launchConf.ask_diff_mode_on_launch) {

View File

@ -112,7 +112,7 @@ twilio==6.10.4
twisted==18.9.0 # via daphne
txaio==18.8.1 # via autobahn
typing==3.6.6 # via django-extensions
urllib3==1.24.1 # via requests
urllib3==1.24.3 # via requests
uwsgi==2.0.17
uwsgitop==0.10.0
vine==1.2.0 # via amqp

View File

@ -115,7 +115,7 @@ selectors2==2.0.1 # via ncclient
six==1.11.0 # via azure-cli-core, bcrypt, cryptography, google-auth, isodate, keystoneauth1, knack, munch, ncclient, ntlm-auth, openstacksdk, ovirt-engine-sdk-python, packaging, pynacl, pyopenssl, python-dateutil, pyvmomi, pywinrm, stevedore
stevedore==1.28.0 # via keystoneauth1
tabulate==0.7.7 # via azure-cli-core, knack
urllib3==1.24 # via requests
urllib3==1.24.3 # via requests
wheel==0.30.0 # via azure-cli-core
xmltodict==0.11.0 # via pywinrm

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/awx-python
import sys
import os
import signal