Get end-to-end configuration setup working, including verification (except for Github, which is in progress)
This commit is contained in:
parent
825455ea6c
commit
63504c87fb
14 changed files with 611 additions and 206 deletions
|
@ -10,8 +10,137 @@ angular.module("core-config-setup", ['angularFileUpload'])
|
|||
'isActive': '=isActive'
|
||||
},
|
||||
controller: function($rootScope, $scope, $element, $timeout, ApiService) {
|
||||
$scope.SERVICES = [
|
||||
{'id': 'redis', 'title': 'Redis'},
|
||||
|
||||
{'id': 'registry-storage', 'title': 'Registry Storage'},
|
||||
|
||||
{'id': 'ssl', 'title': 'SSL certificate and key', 'condition': function(config) {
|
||||
return config.PREFERRED_URL_SCHEME == 'https';
|
||||
}},
|
||||
|
||||
{'id': 'ldap', 'title': 'LDAP Authentication', 'condition': function(config) {
|
||||
return config.AUTHENTICATION_TYPE == 'LDAP';
|
||||
}},
|
||||
|
||||
{'id': 'mail', 'title': 'E-mail Support', 'condition': function(config) {
|
||||
return config.FEATURE_MAILING;
|
||||
}},
|
||||
|
||||
{'id': 'github-login', 'title': 'Github (Enterprise) Authentication', 'condition': function(config) {
|
||||
return config.FEATURE_GITHUB_LOGIN;
|
||||
}}
|
||||
];
|
||||
|
||||
$scope.STORAGE_CONFIG_FIELDS = {
|
||||
'LocalStorage': [
|
||||
{'name': 'storage_path', 'title': 'Storage Directory', 'placeholder': '/some/directory', 'kind': 'text'}
|
||||
],
|
||||
|
||||
'S3Storage': [
|
||||
{'name': 's3_access_key', 'title': 'AWS Access Key', 'placeholder': 'accesskeyhere', 'kind': 'text'},
|
||||
{'name': 's3_secret_key', 'title': 'AWS Secret Key', 'placeholder': 'secretkeyhere', 'kind': 'text'},
|
||||
{'name': 's3_bucket', 'title': 'S3 Bucket', 'placeholder': 'my-cool-bucket', 'kind': 'text'},
|
||||
{'name': 'storage_path', 'title': 'Storage Directory', 'placeholder': '/path/inside/bucket', 'kind': 'text'}
|
||||
],
|
||||
|
||||
'GoogleCloudStorage': [
|
||||
{'name': 'access_key', 'title': 'Cloud Access Key', 'placeholder': 'accesskeyhere', 'kind': 'text'},
|
||||
{'name': 'secret_key', 'title': 'Cloud Secret Key', 'placeholder': 'secretkeyhere', 'kind': 'text'},
|
||||
{'name': 'bucket_name', 'title': 'GCS Bucket', 'placeholder': 'my-cool-bucket', 'kind': 'text'},
|
||||
{'name': 'storage_path', 'title': 'Storage Directory', 'placeholder': '/path/inside/bucket', 'kind': 'text'}
|
||||
],
|
||||
|
||||
'RadosGWStorage': [
|
||||
{'name': 'hostname', 'title': 'Rados Server Hostname', 'placeholder': 'my.rados.hostname', 'kind': 'text'},
|
||||
{'name': 'is_secure', 'title': 'Is Secure', 'placeholder': 'Require SSL', 'kind': 'bool'},
|
||||
{'name': 'access_key', 'title': 'Access Key', 'placeholder': 'accesskeyhere', 'kind': 'text', 'help_url': 'http://ceph.com/docs/master/radosgw/admin/'},
|
||||
{'name': 'secret_key', 'title': 'Secret Key', 'placeholder': 'secretkeyhere', 'kind': 'text'},
|
||||
{'name': 'bucket_name', 'title': 'Bucket Name', 'placeholder': 'my-cool-bucket', 'kind': 'text'},
|
||||
{'name': 'storage_path', 'title': 'Storage Directory', 'placeholder': '/path/inside/bucket', 'kind': 'text'}
|
||||
]
|
||||
};
|
||||
|
||||
$scope.config = null;
|
||||
$scope.mapped = {};
|
||||
$scope.mapped = {
|
||||
'$hasChanges': false
|
||||
};
|
||||
|
||||
$scope.validating = null;
|
||||
$scope.savingConfiguration = false;
|
||||
|
||||
$scope.getServices = function(config) {
|
||||
var services = [];
|
||||
if (!config) { return services; }
|
||||
|
||||
for (var i = 0; i < $scope.SERVICES.length; ++i) {
|
||||
var service = $scope.SERVICES[i];
|
||||
if (!service.condition || service.condition(config)) {
|
||||
services.push({
|
||||
'service': service,
|
||||
'status': 'validating'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return services;
|
||||
};
|
||||
|
||||
$scope.validationStatus = function(serviceInfos) {
|
||||
if (!serviceInfos) { return 'validating'; }
|
||||
|
||||
var hasError = false;
|
||||
for (var i = 0; i < serviceInfos.length; ++i) {
|
||||
if (serviceInfos[i].status == 'validating') {
|
||||
return 'validating';
|
||||
}
|
||||
if (serviceInfos[i].status == 'error') {
|
||||
hasError = true;
|
||||
}
|
||||
}
|
||||
|
||||
return hasError ? 'failed' : 'success';
|
||||
};
|
||||
|
||||
$scope.validateService = function(serviceInfo) {
|
||||
var params = {
|
||||
'service': serviceInfo.service.id
|
||||
};
|
||||
|
||||
ApiService.scValidateConfig({'config': $scope.config}, params).then(function(resp) {
|
||||
serviceInfo.status = resp.status ? 'success' : 'error';
|
||||
serviceInfo.errorMessage = $.trim(resp.reason || '');
|
||||
}, ApiService.errorDisplay('Could not validate configuration. Please report this error.'));
|
||||
};
|
||||
|
||||
$scope.validateAndSave = function() {
|
||||
$scope.savingConfiguration = false;
|
||||
$scope.validating = $scope.getServices($scope.config);
|
||||
|
||||
$('#validateAndSaveModal').modal({
|
||||
keyboard: false,
|
||||
backdrop: 'static'
|
||||
});
|
||||
|
||||
for (var i = 0; i < $scope.validating.length; ++i) {
|
||||
var serviceInfo = $scope.validating[i];
|
||||
$scope.validateService(serviceInfo);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.saveConfiguration = function() {
|
||||
$scope.savingConfiguration = true;
|
||||
|
||||
var data = {
|
||||
'config': $scope.config,
|
||||
'hostname': window.location.host
|
||||
};
|
||||
|
||||
ApiService.scUpdateConfig(data).then(function(resp) {
|
||||
$scope.savingConfiguration = false;
|
||||
$scope.mapped.$hasChanges = false
|
||||
}, ApiService.errorDisplay('Could not save configuration. Please report this error.'));
|
||||
};
|
||||
|
||||
var githubSelector = function(key) {
|
||||
return function(value) {
|
||||
|
@ -36,8 +165,8 @@ angular.module("core-config-setup", ['angularFileUpload'])
|
|||
var current = config;
|
||||
for (var i = 0; i < parts.length; ++i) {
|
||||
var part = parts[i];
|
||||
if (!config[part]) { return null; }
|
||||
current = config[part];
|
||||
if (!current[part]) { return null; }
|
||||
current = current[part];
|
||||
}
|
||||
return current;
|
||||
};
|
||||
|
@ -86,7 +215,36 @@ angular.module("core-config-setup", ['angularFileUpload'])
|
|||
$scope.$watch('mapped.redis.port', redisSetter('port'));
|
||||
$scope.$watch('mapped.redis.password', redisSetter('password'));
|
||||
|
||||
// Add a watch to remove any fields not allowed by the current storage configuration.
|
||||
// We have to do this otherwise extra fields (which are not allowed) can end up in the
|
||||
// configuration.
|
||||
$scope.$watch('config.DISTRIBUTED_STORAGE_CONFIG.local[0]', function(value) {
|
||||
// Remove any fields not associated with the current kind.
|
||||
if (!value || !$scope.STORAGE_CONFIG_FIELDS[value]
|
||||
|| !$scope.config.DISTRIBUTED_STORAGE_CONFIG
|
||||
|| !$scope.config.DISTRIBUTED_STORAGE_CONFIG.local
|
||||
|| !$scope.config.DISTRIBUTED_STORAGE_CONFIG.local[1]) { return; }
|
||||
|
||||
var allowedFields = $scope.STORAGE_CONFIG_FIELDS[value];
|
||||
var configObject = $scope.config.DISTRIBUTED_STORAGE_CONFIG.local[1];
|
||||
|
||||
for (var fieldName in configObject) {
|
||||
if (!configObject.hasOwnProperty(fieldName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var isValidField = $.grep(allowedFields, function(field) {
|
||||
return field.name == fieldName;
|
||||
}).length > 0;
|
||||
|
||||
if (!isValidField) {
|
||||
delete configObject[fieldName];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$watch('config', function(value) {
|
||||
$scope.mapped['$hasChanges'] = true;
|
||||
}, true);
|
||||
|
||||
$scope.$watch('isActive', function(value) {
|
||||
|
@ -95,6 +253,7 @@ angular.module("core-config-setup", ['angularFileUpload'])
|
|||
ApiService.scGetConfig().then(function(resp) {
|
||||
$scope.config = resp['config'];
|
||||
initializeMappedLogic($scope.config);
|
||||
$scope.mapped['$hasChanges'] = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -376,9 +535,7 @@ angular.module("core-config-setup", ['angularFileUpload'])
|
|||
'binding': '=binding'
|
||||
},
|
||||
controller: function($scope, $element) {
|
||||
$scope.$watch('items', function(items) {
|
||||
if (!items) { return; }
|
||||
|
||||
var padItems = function(items) {
|
||||
// Remove the last item if both it and the second to last items are empty.
|
||||
if (items.length > 1 && !items[items.length - 2].value && !items[items.length - 1].value) {
|
||||
items.splice(items.length - 1, 1);
|
||||
|
@ -386,14 +543,45 @@ angular.module("core-config-setup", ['angularFileUpload'])
|
|||
}
|
||||
|
||||
// If the last item is non-empty, add a new item.
|
||||
if (items[items.length - 1].value) {
|
||||
if (items.length == 0 || items[items.length - 1].value) {
|
||||
items.push({'value': ''});
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.itemHash = null;
|
||||
$scope.$watch('items', function(items) {
|
||||
if (!items) { return; }
|
||||
padItems(items);
|
||||
|
||||
var itemHash = '';
|
||||
var binding = [];
|
||||
for (var i = 0; i < items.length; ++i) {
|
||||
var item = items[i];
|
||||
if (item.value && (URI(item.value).host() || URI(item.value).path())) {
|
||||
binding.push(item.value);
|
||||
itemHash += item.value;
|
||||
}
|
||||
}
|
||||
|
||||
$scope.itemHash = itemHash;
|
||||
$scope.binding = binding;
|
||||
}, true);
|
||||
|
||||
$scope.$watch('binding', function(binding) {
|
||||
$scope.items = [];
|
||||
$scope.items.push({'value': ''});
|
||||
if (!binding) { return; }
|
||||
|
||||
var current = binding;
|
||||
var items = [];
|
||||
var itemHash = '';
|
||||
for (var i = 0; i < current.length; ++i) {
|
||||
items.push({'value': current[i]})
|
||||
itemHash += current[i];
|
||||
}
|
||||
|
||||
if ($scope.itemHash != itemHash) {
|
||||
$scope.items = items;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -416,6 +604,7 @@ angular.module("core-config-setup", ['angularFileUpload'])
|
|||
$scope.value = null;
|
||||
|
||||
var updateBinding = function() {
|
||||
if ($scope.value == null) { return; }
|
||||
var value = $scope.value || '';
|
||||
|
||||
switch ($scope.kind) {
|
||||
|
|
Reference in a new issue