Merge branch 'bobthe' of ssh://bitbucket.org/yackob03/quay into bobthe

This commit is contained in:
yackob03 2014-02-11 12:10:09 -05:00
commit dc1737e0da
11 changed files with 623 additions and 55 deletions

View file

@ -524,7 +524,7 @@ i.toggle-icon:hover {
border-bottom: 1px solid #eee;
}
.build-info:hover {
.build-info.clickable:hover {
background: rgba(66, 139, 202, 0.2);
cursor: pointer;
border-radius: 4px;
@ -535,33 +535,36 @@ i.toggle-icon:hover {
border-bottom: 0px;
}
.build-status .phase-icon {
.phase-icon {
border-radius: 50%;
display: inline-block;
width: 12px;
height: 12px;
margin-right: 6px;
}
.build-status .phase-icon {
margin-top: 4px;
float: left;
}
.build-status .phase-icon.error {
.phase-icon.error {
background-color: red;
}
.build-status .phase-icon.waiting, .build-status .phase-icon.starting, .build-status .phase-icon.initializing {
.phase-icon.waiting, .phase-icon.starting, .phase-icon.initializing {
background-color: #ddd;
}
.build-status .phase-icon.building {
.phase-icon.building {
background-color: #f0ad4e;
}
.build-status .phase-icon.pushing {
.phase-icon.pushing {
background-color: #5cb85c;
}
.build-status .phase-icon.complete {
.phase-icon.complete {
background-color: #428bca;
}
@ -1694,6 +1697,141 @@ p.editable:hover i {
padding-left: 44px;
}
.repo-build .build-id:before {
content: "Build ID: "
}
.repo-build .build-id {
float: right;
font-size: 12px;
color: #aaa;
padding: 10px;
}
.repo-build .build-pane .timing {
float: right;
}
.repo-build .build-tab-link {
white-space: nowrap;
}
.repo-build .build-pane .build-header {
padding-top: 10px;
border-bottom: 1px solid #eee;
padding-bottom: 10px;
}
.repo-build .build-pane .build-progress {
margin-top: 16px;
margin-bottom: 10px;
}
.repo-build .build-pane .build-progress .progress {
height: 14px;
margin-bottom: 0px;
}
.repo-build .build-pane .quay-spinner {
margin-top: 4px;
display: inline-block;
}
.repo-build .build-pane .build-logs {
background: #222;
color: white;
padding: 10px;
overflow: auto;
}
.repo-build .build-pane .build-logs .command-logs {
margin: 10px;
padding-right: 10px;
}
.repo-build .build-pane .build-logs .command-entry,
.repo-build .build-pane .build-logs .log-entry {
font-family: Consolas, "Lucida Console", Monaco, monospace;
}
.repo-build .build-pane .build-logs .command-entry {
cursor: pointer;
position: relative;
}
.repo-build .build-pane .build-logs .command-entry i.fa.chevron {
color: #666;
margin-right: 4px;
width: 14px;
text-align: center;
position: absolute;
top: 2px;
left: 0px;
}
.repo-build .build-pane .build-logs .command-entry .label {
text-align: center;
margin-right: 4px;
vertical-align: middle;
width: 86px;
display: inline-block;
background-color: #aaa;
position: absolute;
top: 2px;
left: 24px;
}
.repo-build .build-pane .build-logs .command-entry .command-title {
display: block;
padding-left: 120px;
}
.label.FROM {
background-color: #5bc0de !important;
}
.label.CMD, .label.EXPOSE, .label.ENTRYPOINT {
background-color: #428bca !important;
}
.label.RUN, .label.ADD {
background-color: #5cb85c !important;
}
.label.ENV, .label.VOLUME, .label.USER, .label.WORKDIR {
background-color: #f0ad4e !important;
}
.label.MAINTAINER {
background-color: #aaa !important;
}
.repo-build .build-pane .build-logs .log-entry {
position: relative;
}
.repo-build .build-pane .build-logs .log-entry .message {
display: inline-block;
margin-left: 46px;
}
.repo-build .build-pane .build-logs .log-entry .id {
color: #aaa;
padding-right: 6px;
margin-right: 6px;
text-align: right;
font-size: 12px;
width: 40px;
position: absolute;
top: 4px;
left: 4px;
}
.repo-admin .right-info {
font-size: 11px;
margin-top: 10px;

View file

@ -0,0 +1 @@
<span class="build-message-element">{{ getBuildMessage(build) }}</span>

View file

@ -0,0 +1,6 @@
<div class="build-progress-element">
<div class="progress" ng-class="getPercentage(build) < 100 ? 'active progress-striped' : ''" ng-show="getPercentage(build) > 0 && getPercentage(build) < 100">
<div class="progress-bar" role="progressbar" aria-valuenow="{{ getPercentage(build) }}" aria-valuemin="0" aria-valuemax="100" style="{{ 'width: ' + getPercentage(build) + '%' }}">
</div>
</div>
</div>

View file

@ -1,14 +1,11 @@
<div id="build-status-container" class="build-status-container">
<div>
<span class="phase-icon" ng-class="build.phase"></span>
<span class="build-message">{{ getBuildMessage(build) }}</span>
<span class="build-message" build="build"></span>
</div>
<div class="timing">
<i class="fa fa-clock-o"></i>
Started: <span am-time-ago="build.started || 0"></span>
</div>
<div class="progress" ng-class="getBuildProgress(build) < 100 ? 'active progress-striped' : ''" ng-show="getBuildProgress(build) > 0 && getBuildProgress(build) < 100">
<div class="progress-bar" role="progressbar" aria-valuenow="{{ getBuildProgress(build) }}" aria-valuemin="0" aria-valuemax="100" style="{{ 'width: ' + getBuildProgress(build) + '%' }}">
</div>
</div>
<div class="build-progress" build="build"></div>
</div>

View file

@ -103,7 +103,7 @@ function getMarkedDown(string) {
}
// Start the application code itself.
quayApp = angular.module('quay', ['ngRoute', 'chieffancypants.loadingBar', 'restangular', 'angularMoment', 'angulartics', /*'angulartics.google.analytics',*/ 'angulartics.mixpanel', '$strap.directives', 'ngCookies', 'ngSanitize', 'angular-md5'], function($provide, cfpLoadingBarProvider) {
quayApp = angular.module('quay', ['ngRoute', 'chieffancypants.loadingBar', 'restangular', 'angularMoment', 'angulartics', /*'angulartics.google.analytics',*/ 'angulartics.mixpanel', '$strap.directives', 'ngCookies', 'ngSanitize', 'angular-md5', 'pasvaz.bindonce'], function($provide, cfpLoadingBarProvider) {
cfpLoadingBarProvider.includeSpinner = false;
$provide.factory('UtilService', ['$sanitize', function($sanitize) {
@ -151,7 +151,7 @@ quayApp = angular.module('quay', ['ngRoute', 'chieffancypants.loadingBar', 'rest
$provide.factory('ApiService', ['Restangular', function(Restangular) {
var apiService = {};
var getResource = function(path) {
var getResource = function(path, opt_background) {
var resource = {};
resource.url = path;
resource.withOptions = function(options) {
@ -169,6 +169,12 @@ quayApp = angular.module('quay', ['ngRoute', 'chieffancypants.loadingBar', 'rest
'hasError': false
};
if (opt_background) {
performer.withHttpConfig({
'ignoreLoadingBar': true
});
}
performer.get(options).then(function(resp) {
result.value = processor(resp);
result.loading = false;
@ -240,27 +246,33 @@ quayApp = angular.module('quay', ['ngRoute', 'chieffancypants.loadingBar', 'rest
var buildMethodsForEndpoint = function(endpoint) {
var method = endpoint.methods[0].toLowerCase();
var methodName = formatMethodName(endpoint['name']);
apiService[methodName] = function(opt_options, opt_parameters) {
return Restangular.one(buildUrl(endpoint['path'], opt_parameters))['custom' + method.toUpperCase()](opt_options);
apiService[methodName] = function(opt_options, opt_parameters, opt_background) {
var one = Restangular.one(buildUrl(endpoint['path'], opt_parameters));
if (opt_background) {
one.withHttpConfig({
'ignoreLoadingBar': true
});
}
return one['custom' + method.toUpperCase()](opt_options);
};
if (method == 'get') {
apiService[methodName + 'AsResource'] = function(opt_parameters) {
return getResource(buildUrl(endpoint['path'], opt_parameters));
apiService[methodName + 'AsResource'] = function(opt_parameters, opt_background) {
return getResource(buildUrl(endpoint['path'], opt_parameters), opt_background);
};
}
if (endpoint['user_method']) {
apiService[getGenericMethodName(endpoint['user_method'])] = function(orgname, opt_options, opt_parameters) {
apiService[getGenericMethodName(endpoint['user_method'])] = function(orgname, opt_options, opt_parameters, opt_background) {
if (orgname) {
if (orgname.name) {
orgname = orgname.name;
}
var params = jQuery.extend({'orgname' : orgname}, opt_parameters || {});
var params = jQuery.extend({'orgname' : orgname}, opt_parameters || {}, opt_background);
return apiService[methodName](opt_options, params);
} else {
return apiService[formatMethodName(endpoint['user_method'])](opt_options, opt_parameters);
return apiService[formatMethodName(endpoint['user_method'])](opt_options, opt_parameters, opt_background);
}
};
}
@ -774,6 +786,7 @@ quayApp = angular.module('quay', ['ngRoute', 'chieffancypants.loadingBar', 'rest
fixFooter: false}).
when('/repository/:namespace/:name/image/:image', {templateUrl: '/static/partials/image-view.html', controller: ImageViewCtrl, reloadOnSearch: false}).
when('/repository/:namespace/:name/admin', {templateUrl: '/static/partials/repo-admin.html', controller:RepoAdminCtrl, reloadOnSearch: false}).
when('/repository/:namespace/:name/build', {templateUrl: '/static/partials/repo-build.html', controller:RepoBuildCtrl, reloadOnSearch: false}).
when('/repository/', {title: 'Repositories', description: 'Public and private docker repositories list',
templateUrl: '/static/partials/repo-list.html', controller: RepoListCtrl}).
when('/user/', {title: 'Account Settings', description:'Account settings for Quay.io', templateUrl: '/static/partials/user-admin.html',
@ -2474,7 +2487,63 @@ quayApp.directive('buildStatus', function () {
'build': '=build'
},
controller: function($scope, $element) {
$scope.getBuildProgress = function(buildInfo) {
}
};
return directiveDefinitionObject;
});
quayApp.directive('buildMessage', function () {
var directiveDefinitionObject = {
priority: 0,
templateUrl: '/static/directives/build-message.html',
replace: false,
transclude: false,
restrict: 'C',
scope: {
'build': '=build'
},
controller: function($scope, $element) {
$scope.getBuildMessage = function (buildInfo) {
switch (buildInfo.phase) {
case 'starting':
case 'initializing':
return 'Starting Dockerfile build';
case 'waiting':
return 'Waiting for available build worker.';
case 'building':
return 'Building image from Dockerfile';
case 'pushing':
return 'Pushing image built from Dockerfile';
case 'complete':
return 'Dockerfile build completed and pushed';
case 'error':
return 'Dockerfile build failed.';
}
};
}
};
return directiveDefinitionObject;
});
quayApp.directive('buildProgress', function () {
var directiveDefinitionObject = {
priority: 0,
templateUrl: '/static/directives/build-progress.html',
replace: false,
transclude: false,
restrict: 'C',
scope: {
'build': '=build'
},
controller: function($scope, $element) {
$scope.getPercentage = function(buildInfo) {
switch (buildInfo.phase) {
case 'building':
return (buildInfo.status.current_command / buildInfo.status.total_commands) * 100;
@ -2497,29 +2566,6 @@ quayApp.directive('buildStatus', function () {
return -1;
};
$scope.getBuildMessage = function(buildInfo) {
switch (buildInfo.phase) {
case 'starting':
case 'initializing':
return 'Starting Dockerfile build';
case 'waiting':
return 'Waiting for available build worker.';
case 'building':
return 'Building image from Dockerfile';
case 'pushing':
return 'Pushing image built from Dockerfile';
case 'complete':
return 'Dockerfile build completed and pushed';
case 'error':
return 'Dockerfile build failed.';
}
};
}
};
return directiveDefinitionObject;

View file

@ -197,6 +197,11 @@ function RepoCtrl($scope, $sanitize, Restangular, ImageMetadataService, ApiServi
$scope.getFormattedCommand = ImageMetadataService.getFormattedCommand;
$scope.showBuild = function(buildInfo) {
$location.path('/repository/' + namespace + '/' + name + '/build');
$location.search('current', buildInfo.id);
};
$scope.getTooltipCommand = function(image) {
var sanitized = ImageMetadataService.getEscapedFormattedCommand(image);
return '<span class=\'codetooltip\'>' + sanitized + '</span>';
@ -524,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];
@ -616,6 +619,293 @@ function RepoCtrl($scope, $sanitize, Restangular, ImageMetadataService, ApiServi
loadViewInfo();
}
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) {
$scope.setCurrentBuild($location.search().current, false);
}
});
$scope.builds = [];
$scope.polling = false;
$scope.adjustLogHeight = function() {
$('.build-logs').height($(window).height() - 365);
};
$scope.getShortId = function(id) {
var lastIndex = id.lastIndexOf('-');
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) {
if ($scope.builds[i].id == buildId) {
$scope.setCurrentBuildInternal($scope.builds[i], opt_updateURL);
return;
}
}
};
$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);
} else {
$location.search('current', null);
}
}
// Timeout needed to ensure the log element has been created
// before its height is adjusted.
setTimeout(function() {
$scope.adjustLogHeight();
}, 1);
// If the build is currently processing, start the build timer.
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) {
stopPollTimer();
return;
}
if (build['phase'] != 'complete' && build['phase'] != 'error') {
startPollTimer();
return true;
} else {
stopPollTimer();
return false;
}
};
var stopPollTimer = function() {
$interval.cancel(pollTimerHandle);
};
var startPollTimer = function() {
stopPollTimer();
pollTimerHandle = $interval(getBuildStatusAndLogs, 2000);
};
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;
}
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;
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);
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;
});
});
};
var fetchRepository = function() {
var params = {'repository': namespace + '/' + name};
$rootScope.title = 'Loading Repository...';
$scope.repository = ApiService.getRepoAsResource(params).get(function(repo) {
$rootScope.title = 'Repository Builds';
$scope.repo = repo;
});
};
var getBuildInfo = function(repo) {
var params = {
'repository': namespace + '/' + name
};
ApiService.getRepoBuilds(null, params).then(function(resp) {
$scope.builds = resp.builds;
if ($location.search().current) {
$scope.setCurrentBuild($location.search().current, false);
} else if ($scope.builds.length > 0) {
$scope.setCurrentBuild($scope.builds[0].id, true);
}
});
};
fetchRepository();
getBuildInfo();
}
function RepoAdminCtrl($scope, Restangular, ApiService, $routeParams, $rootScope) {
var namespace = $routeParams.namespace;
var name = $routeParams.name;

1
static/lib/bindonce.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,75 @@
<div class="resource-view" resource="repository" error-message="'No repository found'"></div>
<div class="container repo repo-build" ng-show="repo && !deleting">
<div class="header row">
<a href="{{ '/repository/' + repo.namespace + '/' + repo.name }}" class="back"><i class="fa fa-chevron-left"></i></a>
<h3>
<span class="repo-circle no-background" repo="repo"></span>
<span class="repo-breadcrumb" repo="repo"></span>
</h3>
</div>
<div class="row" ng-show="!repo.is_building">
There are no active builds for this repository
</div>
<div class="row" ng-show="repo.is_building">
<!-- Side tabs -->
<div class="col-sm-2">
<ul class="nav nav-pills nav-stacked">
<li ng-class="currentBuild == build ? 'active' : ''" ng-repeat="build in builds">
<a class="build-tab-link" href="javascript:void(0)" ng-click="setCurrentBuild(build.id, true)">
<span class="phase-icon" ng-class="build.phase"></span>
<span>{{ getShortId(build.id) }}</span>
</a>
</li>
</ul>
</div>
<!-- Content -->
<div class="col-sm-10">
<div class="tab-content" onresize="adjustLogHeight()">
<div ng-repeat="build in builds" class="tab-pane build-pane" ng-class="currentBuild == build ? 'active' : ''">
<div class="build-header">
<div class="timing">
<i class="fa fa-clock-o"></i>
Started: <span am-time-ago="build.started || 0"></span>
</div>
<span class="phase-icon" ng-class="build.phase"></span>
<span class="build-message" build="build"></span>
<div class="build-progress" build="build"></div>
</div>
<div class="build-logs">
<div ng-show="!commands">
<span class="quay-spinner"></span>
</div>
<div class="command" ng-repeat="command in commands">
<div class="command-entry" ng-click="toggleCommand(command)">
<i class="fa chevron" ng-class="command.expanded ? 'fa-chevron-down' : 'fa-chevron-right'"></i>
<span bindonce>
<span class="label" bo-class="getCommandKind(command.message)" bo-show="getCommandKind(command.message)"
bo-text="getCommandKind(command.message)">
</span>
<span class="command-title" bo-html="getCommandTitleHtml(command.message)"></span>
</span>
</div>
<div class="command-logs panel-collapse collapse" ng-class="command.expanded ? 'in' : 'out'">
<div class="log-entry" bindonce ng-repeat="log in command.logs">
<span class="id" bo-text="$index + command.index + 1"></span>
<span class="message" bo-text="log.message"></span>
</div>
<div ng-show="!command.logs">
<span class="quay-spinner"></span>
</div>
</div>
</div>
</div>
<div>
<span class="quay-spinner" ng-show="polling"></span>
<span class="build-id">{{ build.id }}</span>
</div>
</div>
</div>
</div>
</div>
</div>

View file

@ -42,14 +42,14 @@
<div class="dropdown" data-placement="top">
<span class="count" ng-class="buildsInfo ? 'visible' : ''"><span>{{ buildsInfo ? buildsInfo.length : '-' }}</span></span>
<a href="javascript:void(0)" class="dropdown-toggle" data-toggle="dropdown">Building Dockerfile<span ng-show="buildsInfo.length > 1">s</span> <b class="caret"></b></a>
<ul class="dropdown-menu pull-right">
<ul class="dropdown-menu pull-right">
<li ng-repeat="buildInfo in buildsInfo">
<div class="build-info">
<div class="build-info" ng-class="repo.can_write ? 'clickable' : ''" ng-click="showBuild(buildInfo)">
<span class="build-status" build="buildInfo"></span>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>

View file

@ -53,6 +53,7 @@
<script src="static/lib/angulartics-mixpanel.js"></script>
<script src="static/lib/angulartics-google-analytics.js"></script>
<script src="static/lib/angular-md5.js"></script>
<script src="static/lib/bindonce.min.js"></script>
<script src="static/lib/angular-moment.min.js"></script>
<script src="static/lib/angular-cookies.min.js"></script>

View file

@ -5,6 +5,7 @@ from random import SystemRandom
from loremipsum import get_sentence
from data.buildlogs import BuildLogs
from random import choice
logger = logging.getLogger(__name__)
@ -26,10 +27,22 @@ class TestBuildLogs(BuildLogs):
self._generate_logs()
self._status = {}
def _get_random_command(self):
COMMANDS = ['FROM', 'MAINTAINER', 'RUN', 'CMD', 'EXPOSE', 'ENV', 'ADD',
'ENTRYPOINT', 'VOLUME', 'USER', 'WORKDIR']
return choice(COMMANDS)
def _generate_command(self):
self.last_command += 1
sentence = get_sentence()
command = self._get_random_command()
if command == 'FROM':
sentence = choice(['ubuntu', 'quay.io/devtable/simple', 'quay.io/buynlarge/orgrepo', 'stackbrew/ubuntu:precise'])
return {
'message': 'Step %s : %s' % (self.last_command, get_sentence()),
'message': 'Step %s: %s %s' % (self.last_command, command, sentence),
'is_command': True,
}