Merge pull request #3569 from ansible/inv_src_venv

Use inventory source model, as opposed to organization, for update custom virtualenv

Reviewed-by: https://github.com/softwarefactory-project-zuul[bot]
This commit is contained in:
softwarefactory-project-zuul[bot] 2019-04-02 12:16:50 +00:00 committed by GitHub
commit 8f096d11b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 87 additions and 19 deletions

View File

@ -1950,7 +1950,7 @@ class InventorySourceOptionsSerializer(BaseSerializer):
class Meta:
fields = ('*', 'source', 'source_path', 'source_script', 'source_vars', 'credential',
'source_regions', 'instance_filters', 'group_by', 'overwrite', 'overwrite_vars',
'timeout', 'verbosity')
'custom_virtualenv', 'timeout', 'verbosity')
def get_related(self, obj):
res = super(InventorySourceOptionsSerializer, self).get_related(obj)

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.16 on 2019-03-28 17:56
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('main', '0065_v350_index_job_status'),
]
operations = [
migrations.AddField(
model_name='inventorysource',
name='custom_virtualenv',
field=models.CharField(blank=True, default=None, help_text='Local absolute file path containing a custom Python virtualenv to use', max_length=100, null=True),
),
]

View File

@ -1429,7 +1429,7 @@ class InventorySourceOptions(BaseModel):
return ''
class InventorySource(UnifiedJobTemplate, InventorySourceOptions, RelatedJobsMixin):
class InventorySource(UnifiedJobTemplate, InventorySourceOptions, CustomVirtualEnvMixin, RelatedJobsMixin):
SOFT_UNIQUE_TOGETHER = [('polymorphic_ctype', 'name', 'inventory')]
@ -1776,14 +1776,12 @@ class InventoryUpdate(UnifiedJob, InventorySourceOptions, JobNotificationMixin,
@property
def ansible_virtualenv_path(self):
if self.inventory_source and self.inventory_source.custom_virtualenv:
return self.inventory_source.custom_virtualenv
if self.inventory_source and self.inventory_source.source_project:
project = self.inventory_source.source_project
if project and project.custom_virtualenv:
return project.custom_virtualenv
if self.inventory_source and self.inventory_source.inventory:
organization = self.inventory_source.inventory.organization
if organization and organization.custom_virtualenv:
return organization.custom_virtualenv
return settings.ANSIBLE_VENV_PATH
def cancel(self, job_explanation=None, is_chain=False):

View File

@ -4,16 +4,15 @@
* All Rights Reserved
*************************************************/
export default ['$state', '$stateParams', '$scope', 'SourcesFormDefinition',
'ParseTypeChange', 'GenerateForm', 'inventoryData', 'GroupsService',
'GetChoices', 'GetBasePath', 'CreateSelect2', 'GetSourceTypeOptions',
'rbacUiControlService', 'ToJSON', 'SourcesService', 'Empty',
'Wait', 'Rest', 'Alert', 'ProcessErrors', 'inventorySourcesOptions',
'$rootScope', 'i18n', 'InventorySourceModel', 'InventoryHostsStrings',
function($state, $stateParams, $scope, SourcesFormDefinition, ParseTypeChange,
GenerateForm, inventoryData, GroupsService, GetChoices,
GetBasePath, CreateSelect2, GetSourceTypeOptions, rbacUiControlService,
ToJSON, SourcesService, Empty, Wait, Rest, Alert, ProcessErrors,
export default ['$state', 'ConfigData', '$scope', 'SourcesFormDefinition', 'ParseTypeChange',
'GenerateForm', 'inventoryData', 'GetChoices',
'GetBasePath', 'CreateSelect2', 'GetSourceTypeOptions',
'SourcesService', 'Empty', 'Wait', 'Rest', 'Alert', 'ProcessErrors',
'inventorySourcesOptions', '$rootScope', 'i18n', 'InventorySourceModel', 'InventoryHostsStrings',
function($state, ConfigData, $scope, SourcesFormDefinition, ParseTypeChange,
GenerateForm, inventoryData, GetChoices,
GetBasePath, CreateSelect2, GetSourceTypeOptions,
SourcesService, Empty, Wait, Rest, Alert, ProcessErrors,
inventorySourcesOptions,$rootScope, i18n, InventorySource, InventoryHostsStrings) {
let form = SourcesFormDefinition;
@ -22,6 +21,8 @@ export default ['$state', '$stateParams', '$scope', 'SourcesFormDefinition',
GenerateForm.applyDefaults(form, $scope, true);
$scope.canAdd = inventorySourcesOptions.actions.POST;
$scope.envParseType = 'yaml';
const virtualEnvs = ConfigData.custom_virtualenvs || [];
$scope.custom_virtualenvs_options = virtualEnvs;
GetChoices({
scope: $scope,
@ -80,6 +81,12 @@ export default ['$state', '$stateParams', '$scope', 'SourcesFormDefinition',
$scope.verbosity = $scope.verbosity_options[1];
CreateSelect2({
element: '#inventory_source_custom_virtualenv',
multiple: false,
opts: $scope.custom_virtualenvs_options
});
GetSourceTypeOptions({
scope: $scope,
variable: 'source_type_options'
@ -279,9 +286,10 @@ export default ['$state', '$stateParams', '$scope', 'SourcesFormDefinition',
update_on_launch: $scope.update_on_launch,
verbosity: $scope.verbosity.value,
update_cache_timeout: $scope.update_cache_timeout || 0,
custom_virtualenv: $scope.custom_virtualenv || null,
// comma-delimited strings
group_by: SourcesService.encodeGroupBy($scope.source, $scope.group_by),
source_regions: _.map($scope.source_regions, 'value').join(',')
source_regions: _.map($scope.source_regions, 'value').join(','),
};
if ($scope.source) {

View File

@ -25,6 +25,16 @@ export default {
.then(function(res) {
return res.data;
});
}],
ConfigData: ['ConfigService', 'ProcessErrors', 'i18n', (ConfigService, ProcessErrors, i18n) => {
return ConfigService.getConfig()
.then(response => response)
.catch(({data, status}) => {
ProcessErrors(null, data, status, null, {
hdr: i18n._('Error!'),
msg: i18n._('Failed to get config. GET returned status: ') + status
});
});
}]
}
};

View File

@ -8,18 +8,20 @@ export default ['$state', '$scope', 'ParseVariableString', 'ParseTypeChange',
'GetChoices', 'GetBasePath', 'CreateSelect2', 'GetSourceTypeOptions',
'SourcesService', 'inventoryData', 'inventorySourcesOptions', 'Empty',
'Wait', 'Rest', 'Alert', '$rootScope', 'i18n', 'InventoryHostsStrings',
'ProcessErrors', 'inventorySource', 'isNotificationAdmin',
'ProcessErrors', 'inventorySource', 'isNotificationAdmin', 'ConfigData',
function($state, $scope, ParseVariableString, ParseTypeChange,
GetChoices, GetBasePath, CreateSelect2, GetSourceTypeOptions,
SourcesService, inventoryData, inventorySourcesOptions, Empty,
Wait, Rest, Alert, $rootScope, i18n, InventoryHostsStrings,
ProcessErrors, inventorySource, isNotificationAdmin) {
ProcessErrors, inventorySource, isNotificationAdmin, ConfigData) {
const inventorySourceData = inventorySource.get();
$scope.projectBasePath = GetBasePath('projects') + '?not__status=never updated';
$scope.canAdd = inventorySourcesOptions.actions.POST;
$scope.isNotificationAdmin = isNotificationAdmin || false;
const virtualEnvs = ConfigData.custom_virtualenvs || [];
$scope.custom_virtualenvs_options = virtualEnvs;
// instantiate expected $scope values from inventorySourceData
_.assign($scope,
{credential: inventorySourceData.credential},
@ -157,6 +159,12 @@ export default ['$state', '$scope', 'ParseVariableString', 'ParseTypeChange',
}
}
CreateSelect2({
element: '#inventory_source_custom_virtualenv',
multiple: false,
opts: $scope.custom_virtualenvs_options
});
initVerbositySelect();
$scope.$watch('verbosity', initVerbositySelect);
@ -329,6 +337,7 @@ export default ['$state', '$scope', 'ParseVariableString', 'ParseTypeChange',
update_on_launch: $scope.update_on_launch,
update_cache_timeout: $scope.update_cache_timeout || 0,
verbosity: $scope.verbosity.value,
custom_virtualenv: $scope.custom_virtualenv || null,
// comma-delimited strings
group_by: SourcesService.encodeGroupBy($scope.source, $scope.group_by),
source_regions: _.map($scope.source_regions, 'value').join(',')

View File

@ -38,6 +38,16 @@ export default {
msg: i18n._('Failed to get organizations for which this user is a notification administrator. GET returned ') + status
});
});
}],
ConfigData: ['ConfigService', 'ProcessErrors', 'i18n', (ConfigService, ProcessErrors, i18n) => {
return ConfigService.getConfig()
.then(response => response)
.catch(({data, status}) => {
ProcessErrors(null, data, status, null, {
hdr: i18n._('Error!'),
msg: i18n._('Failed to get config. GET returned status: ') + status
});
});
}]
}
};

View File

@ -56,6 +56,19 @@ export default ['NotificationsList', 'i18n', function(NotificationsList, i18n){
ngModel: 'source',
hasSubForm: true
},
custom_virtualenv: {
label: i18n._('Ansible Environment'),
type: 'select',
defaultText: i18n._('Use Default Environment'),
ngOptions: 'venv for venv in custom_virtualenvs_options track by venv',
awPopOver: "<p>" + i18n._("Select the custom Python virtual environment for this inventory source sync to run on.") + "</p>",
dataTitle: i18n._('Ansible Environment'),
dataContainer: 'body',
dataPlacement: 'right',
ngDisabled: '!(inventory_source_obj.summary_fields.user_capabilities.edit || canAdd)',
ngShow: 'custom_virtualenvs_options.length > 1'
},
credential: {
label: i18n._('Credential'),
type: 'lookup',