Get full build interface working

This commit is contained in:
Joseph Schorr 2014-02-10 22:43:48 -05:00
parent 7c081f029c
commit ea45c3b77f
7 changed files with 326 additions and 35 deletions

View file

@ -529,13 +529,11 @@ function RepoCtrl($scope, $sanitize, Restangular, ImageMetadataService, ApiServi
};
var getBuildInfo = function(repo) {
// Note: We use restangular manually here because we need to turn off the loading bar.
var buildInfo = Restangular.one('repository/' + repo.namespace + '/' + repo.name + '/build/');
buildInfo.withHttpConfig({
'ignoreLoadingBar': true
});
var params = {
'repository': repo.namespace + '/' + repo.name
};
buildInfo.get().then(function(resp) {
ApiService.getRepoBuilds(null, params, true).then(function(resp) {
var runningBuilds = [];
for (var i = 0; i < resp.builds.length; ++i) {
var build = resp.builds[i];
@ -621,11 +619,41 @@ function RepoCtrl($scope, $sanitize, Restangular, ImageMetadataService, ApiServi
loadViewInfo();
}
function RepoBuildCtrl($scope, Restangular, ApiService, $routeParams, $rootScope, $location, $interval) {
function RepoBuildCtrl($scope, Restangular, ApiService, $routeParams, $rootScope, $location, $interval, $sanitize) {
var namespace = $routeParams.namespace;
var name = $routeParams.name;
var pollTimerHandle = null;
var registryHandlers = {
'quay.io': function(pieces) {
var rnamespace = pieces[pieces.length - 2];
var rname = pieces[pieces.length - 1];
return '/repository/' + rnamespace + '/' + rname + '/';
},
'': function(pieces) {
var rnamespace = pieces.length == 1 ? '_' : pieces[0];
var rname = pieces[pieces.length - 1];
return 'https://index.docker.io/' + rnamespace + '/' + rname + '/';
}
};
var kindHandlers = {
'FROM': function(title) {
var pieces = title.split('/');
var registry = pieces.length < 2 ? '' : pieces[0];
if (!registryHandlers[registry]) {
return title;
}
return '<i class="fa fa-hdd-o"></i> <a href="' + registryHandlers[registry](pieces) + '">' + title + '</a>';
}
};
$scope.$on('$destroy', function() {
stopPollTimer();
});
// Watch for changes to the current parameter.
$scope.$on('$routeUpdate', function(){
if ($location.search().current) {
@ -645,6 +673,44 @@ function RepoBuildCtrl($scope, Restangular, ApiService, $routeParams, $rootScope
return id.substr(lastIndex + 1);
};
$scope.getCommandKind = function(fullTitle) {
var colon = fullTitle.indexOf(':');
var title = getTitleWithoutStep(fullTitle);
if (!title) {
return null;
}
var space = title.indexOf(' ');
return title.substring(0, space);
};
$scope.getCommandTitleHtml = function(fullTitle) {
var title = getTitleWithoutStep(fullTitle) || fullTitle;
var space = title.indexOf(' ');
if (space <= 0) {
return $sanitize(title);
}
var kind = $scope.getCommandKind(fullTitle);
var sanitized = $sanitize(title.substring(space + 1));
var handler = kindHandlers[kind || ''];
if (handler) {
return handler(sanitized);
} else {
return sanitized;
}
};
$scope.toggleCommand = function(command) {
command.expanded = !command.expanded;
if (command.expanded && !command.logs) {
// Load the logs for the command.
loadCommandLogs(command);
}
};
$scope.setCurrentBuild = function(buildId, opt_updateURL) {
// Find the build.
for (var i = 0; i < $scope.builds.length; ++i) {
@ -656,9 +722,16 @@ function RepoBuildCtrl($scope, Restangular, ApiService, $routeParams, $rootScope
};
$scope.setCurrentBuildInternal = function(build, opt_updateURL) {
if (build == $scope.currentBuild) { return; }
stopPollTimer();
$scope.commands = null;
$scope.commandMap = {};
$scope.logs = null;
$scope.logStartIndex = 0;
$scope.currentBuild = build;
if (opt_updateURL) {
if (build) {
$location.search('current', build.id);
@ -677,6 +750,15 @@ function RepoBuildCtrl($scope, Restangular, ApiService, $routeParams, $rootScope
checkPollTimer();
};
var getTitleWithoutStep = function(fullTitle) {
var colon = fullTitle.indexOf(':');
if (colon <= 0) {
return null;
}
return $.trim(fullTitle.substring(colon + 1));
}
var checkPollTimer = function() {
var build = $scope.currentBuild;
if (!build) {
@ -686,8 +768,10 @@ function RepoBuildCtrl($scope, Restangular, ApiService, $routeParams, $rootScope
if (build['phase'] != 'complete' && build['phase'] != 'error') {
startPollTimer();
return true;
} else {
stopPollTimer();
return false;
}
};
@ -697,25 +781,99 @@ function RepoBuildCtrl($scope, Restangular, ApiService, $routeParams, $rootScope
var startPollTimer = function() {
stopPollTimer();
pollTimerHandle = $interval(getBuildStatus, 1000);
pollTimerHandle = $interval(getBuildStatusAndLogs, 2000);
};
var getBuildStatus = function() {
if (!$scope.currentBuild) { return; }
var processLogs = function(logs, startIndex) {
var currentCommand = $scope.commands.length > 0 ? $scope.commands[$scope.commands.length - 1] : null;
for (var i = 0; i < logs.length; ++i) {
var entry = logs[i];
if (entry['is_command']) {
var existing = $scope.commandMap[entry['message']];
if (existing) {
currentCommand = existing;
continue;
}
// Note: We use restangular manually here because we need to turn off the loading bar.
var buildStatus = Restangular.one('repository/' + namespace + '/' + name + '/build/' + $scope.currentBuild.id + '/status');
buildStatus.withHttpConfig({
'ignoreLoadingBar': true
currentCommand = {
'message': entry['message'],
'index': startIndex + i
};
$scope.commands.push(currentCommand);
$scope.commandMap[entry['message']] = currentCommand;
continue;
}
if (!currentCommand.logs) {
currentCommand.logs = [];
}
currentCommand.logs.push(entry);
}
if (currentCommand.expanded == null) {
currentCommand.expanded = true;
}
};
var loadCommandLogs = function(command) {
var start = command['index'] + 1;
var end = null;
var currentCommandIndex = jQuery.inArray(command, $scope.commands);
if (currentCommandIndex >= 0 && currentCommandIndex < $scope.commands.length - 1) {
var nextCommand = $scope.commands[currentCommandIndex + 1];
end = nextCommand.index ? nextCommand.index - 1 : null;
}
var params = {
'repository': namespace + '/' + name,
'build_uuid': $scope.currentBuild.id
};
var options = {
'start': start
};
if (end != null) {
options['end'] = end;
}
ApiService.getRepoBuildLogsAsResource(params, true).withOptions(options).get(function(resp) {
if (resp['logs']) {
command.logs = resp['logs'];
}
});
};
var getBuildStatusAndLogs = function() {
if (!$scope.currentBuild || $scope.polling) { return; }
$scope.polling = true;
buildStatus.get().then(function(resp) {
var params = {
'repository': namespace + '/' + name,
'build_uuid': $scope.currentBuild.id
};
ApiService.getRepoBuildStatus(null, params, true).then(function(resp) {
// Note: We use extend here rather than replacing as Angular is depending on the
// root build object to remain the same object.
$.extend(true, $scope.currentBuild, resp);
$scope.polling = false;
checkPollTimer();
// Load the updated logs for the build.
var options = {
'commands': $scope.commands == null,
'start': $scope.logStartIndex
};
ApiService.getRepoBuildLogsAsResource(params, true).withOptions(options).get(function(resp) {
if (resp['commands']) {
$scope.commands = resp['commands'];
}
processLogs(resp.logs, $scope.logStartIndex);
$scope.logStartIndex = resp['total'];
$scope.polling = false;
});
});
};
@ -725,18 +883,15 @@ function RepoBuildCtrl($scope, Restangular, ApiService, $routeParams, $rootScope
$scope.repository = ApiService.getRepoAsResource(params).get(function(repo) {
$rootScope.title = 'Repository Builds';
$scope.repo = repo;
getBuildInfo();
});
};
var getBuildInfo = function(repo) {
// Note: We use restangular manually here because we need to turn off the loading bar.
var buildInfo = Restangular.one('repository/' + namespace + '/' + name + '/build/');
buildInfo.withHttpConfig({
'ignoreLoadingBar': true
});
var params = {
'repository': namespace + '/' + name
};
buildInfo.get().then(function(resp) {
ApiService.getRepoBuilds(null, params).then(function(resp) {
$scope.builds = resp.builds;
if ($location.search().current) {
@ -748,6 +903,7 @@ function RepoBuildCtrl($scope, Restangular, ApiService, $routeParams, $rootScope
};
fetchRepository();
getBuildInfo();
}
function RepoAdminCtrl($scope, Restangular, ApiService, $routeParams, $rootScope) {