Merge branch 'dev'

pull/2/head
Michael Crosby 12 years ago
commit b77fb1ad03

@ -5,19 +5,40 @@ DockerUI is a web interface to interact with the Remote API. The goal is to pro
![Container](/container.png) ![Container](/container.png)
###Goals
* Little to no dependencies - I really want to keep this project a pure html/js app. You can drop the docker binary on your server run so I want to be able to drop these html files on your server and go.
###Installation ###Installation
Open js/app.js and change the DOCKER_ENDPOINT constant to your docker ip and port. Then host the site like any other html/js application. Open js/app.js and change the DOCKER_ENDPOINT constant to your docker ip and port. Then host the site like any other html/js application.
.constant('DOCKER_ENDPOINT', 'http://192.168.1.9:4243\:4243'); .constant('DOCKER_ENDPOINT', 'http://192.168.1.9:4243\:4243');
###Remote API Version
DockerUI currently supports the v1.1 Remote API
###Stack ###Stack
* Angular.js * Angular.js
* Flatstrap ( Flat Twitter Bootstrap ) * Flatstrap ( Flat Twitter Bootstrap )
###Todo:
I work fast so it will not be long before these changes are impelmented.
* Multiple endpoints
* Full repository support
* Search
* Create images via Dockerfile
* Push files to a container
* Unit tests
###License - MIT ###License - MIT
The DockerUI code is licensed under the MIT license. Flatstrap(bootstrap) is licensed under the Apache License v2.0 and Angular.js is licensed under MIT.
**DockerUI:**
Copyright (c) 2013 Michael Crosby. crosbymichael.com Copyright (c) 2013 Michael Crosby. crosbymichael.com
Permission is hereby granted, free of charge, to any person Permission is hereby granted, free of charge, to any person

@ -70,6 +70,11 @@
margin: 0 auto; margin: 0 auto;
} }
.center {
width: 80%;
margin: 0 auto;
}
.btn-remove { .btn-remove {
margin: 0 auto; margin: 0 auto;
max-width: 70%; max-width: 70%;
@ -78,3 +83,7 @@
.actions { .actions {
margin: 0 auto; margin: 0 auto;
} }
.container-bottom {
height: 50px;
}

@ -29,12 +29,13 @@
<div class="container"> <div class="container">
<div ng-include="template" ng-controller="MastheadController" ></div> <div ng-include="template" ng-controller="MastheadController" ></div>
<div id="view" ng-view> <div id="view" ng-view>
</div> </div>
<div class="footer"> <div class="container-bottom"></div>
<p>Created by:<a href="http://crosbymichael.com">Michael Crosby</a></p> <div class="footer center well">
<p>Created by: <a href="http://crosbymichael.com">crosbymichael</a></p>
</div> </div>
</div> </div>

@ -2,7 +2,7 @@
angular.module('dockerui', ['dockerui.services', 'dockerui.filters']) angular.module('dockerui', ['dockerui.services', 'dockerui.filters'])
.config(['$routeProvider', function ($routeProvider) { .config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/', {templateUrl: 'partials/home.html', controller: 'HomeController'}); $routeProvider.when('/', {templateUrl: 'partials/dashboard.html', controller: 'DashboardController'});
$routeProvider.when('/containers/', {templateUrl: 'partials/containers.html', controller: 'ContainersController'}); $routeProvider.when('/containers/', {templateUrl: 'partials/containers.html', controller: 'ContainersController'});
$routeProvider.when('/containers/:id/', {templateUrl: 'partials/container.html', controller: 'ContainerController'}); $routeProvider.when('/containers/:id/', {templateUrl: 'partials/container.html', controller: 'ContainerController'});
$routeProvider.when('/images/', {templateUrl: 'partials/images.html', controller: 'ImagesController'}); $routeProvider.when('/images/', {templateUrl: 'partials/images.html', controller: 'ImagesController'});
@ -10,4 +10,6 @@ angular.module('dockerui', ['dockerui.services', 'dockerui.filters'])
$routeProvider.when('/settings', {templateUrl: 'partials/settings.html', controller: 'SettingsController'}); $routeProvider.when('/settings', {templateUrl: 'partials/settings.html', controller: 'SettingsController'});
$routeProvider.otherwise({redirectTo: '/'}); $routeProvider.otherwise({redirectTo: '/'});
}]) }])
.constant('DOCKER_ENDPOINT', 'http://192.168.1.9:4243\:4243'); // This is your docker url that the api will use to make requests
.constant('DOCKER_ENDPOINT', 'http://192.168.1.9:4243\:4243')
.constant('DOCKER_API_VERSION', '/v1.1');

@ -33,42 +33,42 @@ function MastheadController($scope) {
}; };
} }
function HomeController() { function DashboardController($scope, Container) {
} }
function SideBarController($scope, Container, Settings) {
$scope.template = 'partials/sidebar.html';
$scope.containers = [];
$scope.endpoint = Settings.endpoint;
Container.query({all: 0}, function(d) {
$scope.containers = d;
});
}
function SettingsController($scope, Auth, System, Docker, Settings) { function SettingsController($scope, Auth, System, Docker, Settings) {
$scope.auth = {}; $scope.auth = {};
$scope.info = {}; $scope.info = {};
$scope.docker = {}; $scope.docker = {};
$scope.endpoint = Settings.endpoint;
$scope.apiVersion = Settings.version;
$('#response').hide(); $('#response').hide();
$scope.alertClass = 'block'; $scope.alertClass = 'block';
var showAndHide = function(hide) {
$('#response').show();
if (hide) {
setTimeout(function() { $('#response').hide();}, 5000);
}
};
$scope.updateAuthInfo = function() { $scope.updateAuthInfo = function() {
if ($scope.auth.password != $scope.auth.cpassword) { if ($scope.auth.password != $scope.auth.cpassword) {
$scope.response = 'Your passwords do not match.'; setSuccessfulResponse($scope, 'Your passwords do not match.', '#response');
showAndHide(true);
return; return;
} }
Auth.update( Auth.update(
{username: $scope.auth.username, email: $scope.auth.email, password: $scope.auth.password}, function(d) { {username: $scope.auth.username, email: $scope.auth.email, password: $scope.auth.password}, function(d) {
console.log(d); console.log(d);
$scope.alertClass = 'success'; setSuccessfulResponse($scope, 'Auto information updated.', '#response');
$scope.response = 'Auth information updated.';
showAndHide(true);
}, function(e) { }, function(e) {
console.log(e); console.log(e);
$scope.alertClass = 'error'; setFailedResponse($scope, e.data, '#response');
$scope.response = e.data;
showAndHide(false);
}); });
}; };
@ -89,52 +89,33 @@ function ContainerController($scope, $routeParams, $location, Container) {
$('#response').hide(); $('#response').hide();
$scope.alertClass = 'block'; $scope.alertClass = 'block';
var showAndHide = function(hide) {
$('#response').show();
if (hide) {
setTimeout(function() { $('#response').hide();}, 5000);
}
};
$scope.start = function(){ $scope.start = function(){
Container.start({id: $routeParams.id}, function(d) { Container.start({id: $routeParams.id}, function(d) {
console.log(d); console.log(d);
$scope.alertClass = 'success'; setSuccessfulResponse($scope, 'Container started.', '#response');
$scope.response = 'Container started.';
showAndHide(true);
}, function(e) { }, function(e) {
console.log(e); console.log(e);
$scope.alertClass = 'error'; setFailedResponse($scope, e.data, '#response');
$scope.response = e.data;
showAndHide(false);
}); });
}; };
$scope.stop = function() { $scope.stop = function() {
Container.stop({id: $routeParams.id}, function(d) { Container.stop({id: $routeParams.id}, function(d) {
console.log(d); console.log(d);
$scope.alertClass = 'success'; setSuccessfulResponse($scope, 'Container stopped.', '#response');
$scope.response = 'Container stopped.';
showAndHide(true);
}, function(e) { }, function(e) {
console.log(e); console.log(e);
$scope.alertClass = 'error'; setFailedResponse($scope, e.data, '#response');
$scope.response = e.data;
showAndHide(false);
}); });
}; };
$scope.kill = function() { $scope.kill = function() {
Container.kill({id: $routeParams.id}, function(d) { Container.kill({id: $routeParams.id}, function(d) {
console.log(d); console.log(d);
$scope.alertClass = 'success'; setSuccessfulResponse($scope, 'Container killed.', '#response');
$scope.response = 'Container killed.';
showAndHide(true);
}, function(e) { }, function(e) {
console.log(e); console.log(e);
$scope.alertClass = 'error'; setFailedResponse($scope, e.data, '#response');
$scope.response = e.data;
showAndHide(false);
}); });
}; };
@ -142,14 +123,10 @@ function ContainerController($scope, $routeParams, $location, Container) {
if (confirm("Are you sure you want to remove the container?")) { if (confirm("Are you sure you want to remove the container?")) {
Container.remove({id: $routeParams.id}, function(d) { Container.remove({id: $routeParams.id}, function(d) {
console.log(d); console.log(d);
$scope.alertClass = 'success'; setSuccessfulResponse($scope, 'Container removed.', '#response');
$scope.response = 'Container removed.';
showAndHide(true);
}, function(e){ }, function(e){
console.log(e); console.log(e);
$scope.alertClass = 'error'; setFailedResponse($scope, e.data, '#response');
$scope.response = e.data;
showAndHide(false);
}); });
} }
}; };
@ -210,26 +187,15 @@ function ImageController($scope, $routeParams, $location, Image) {
$('#response').hide(); $('#response').hide();
$scope.alertClass = 'block'; $scope.alertClass = 'block';
var showAndHide = function(hide) {
$('#response').show();
if (hide) {
setTimeout(function() { $('#response').hide();}, 5000);
}
};
$scope.remove = function() { $scope.remove = function() {
if (confirm("Are you sure you want to delete this image?")) { if (confirm("Are you sure you want to delete this image?")) {
Image.remove({id: $routeParams.id}, function(d) { Image.remove({id: $routeParams.id}, function(d) {
console.log(d); console.log(d);
$scope.alertClass = 'success'; setSuccessfulResponse($scope, 'Image removed.', '#response');
$scope.response = 'Image removed.';
showAndHide(true);
}, function(e) { }, function(e) {
console.log(e); console.log(e);
$scope.alertClass = 'error'; setFailedResponse($scope, e.data, '#response');
$scope.response = e.data;
showAndHide(false);
}); });
} }
}; };
@ -244,14 +210,10 @@ function ImageController($scope, $routeParams, $location, Image) {
var tag = $scope.tag; var tag = $scope.tag;
Image.tag({id: $routeParams.id, repo: tag.repo, force: tag.force ? 1 : 0}, function(d) { Image.tag({id: $routeParams.id, repo: tag.repo, force: tag.force ? 1 : 0}, function(d) {
console.log(d); console.log(d);
$scope.alertClass = 'success'; setSuccessfulResponse($scope, 'Tag added.', '#response');
$scope.response = 'Tag added.';
showAndHide(true);
}, function(e) { }, function(e) {
console.log(e); console.log(e);
$scope.alertClass = 'error'; setFailedResponse($scope, e.data, '#response');
$scope.response = e.data;
showAndHide(false);
}); });
}; };
@ -307,3 +269,16 @@ function StartContainerController($scope, $routeParams, $location, Container) {
}); });
}; };
} }
function setSuccessfulResponse($scope, msg, msgId) {
$scope.alertClass = 'success';
$scope.response = msg;
$(msgId).show();
setTimeout(function() { $(msgId).hide();}, 5000);
}
function setFailedResponse($scope, msg, msgId) {
$scope.alertClass = 'error';
$scope.response = msg;
$(msgId).show();
}

@ -1,10 +1,10 @@
'use strict'; 'use strict';
angular.module('dockerui.services', ['ngResource']) angular.module('dockerui.services', ['ngResource'])
.factory('Container', function($resource, DOCKER_ENDPOINT) { .factory('Container', function($resource, Settings) {
// Resource for interacting with the docker containers // Resource for interacting with the docker containers
// http://docs.docker.io/en/latest/api/docker_remote_api.html#containers // http://docs.docker.io/en/latest/api/docker_remote_api.html#containers
return $resource(DOCKER_ENDPOINT + '/containers/:id/:action', {}, { return $resource(Settings.url + '/containers/:id/:action', {}, {
query: {method: 'GET', params:{ all: 0, action: 'json'}, isArray: true}, query: {method: 'GET', params:{ all: 0, action: 'json'}, isArray: true},
get :{method: 'GET', params: { action:'json'}}, get :{method: 'GET', params: { action:'json'}},
start: {method: 'POST', params: {id: '@id', action: 'start'}}, start: {method: 'POST', params: {id: '@id', action: 'start'}},
@ -16,10 +16,10 @@ angular.module('dockerui.services', ['ngResource'])
remove :{method: 'DELETE', params: {id: '@id', v:0}} remove :{method: 'DELETE', params: {id: '@id', v:0}}
}); });
}) })
.factory('Image', function($resource, DOCKER_ENDPOINT) { .factory('Image', function($resource, Settings) {
// Resource for docker images // Resource for docker images
// http://docs.docker.io/en/latest/api/docker_remote_api.html#images // http://docs.docker.io/en/latest/api/docker_remote_api.html#images
return $resource(DOCKER_ENDPOINT + '/images/:id/:action', {}, { return $resource(Settings.url + '/images/:id/:action', {}, {
query: {method: 'GET', params:{ all: 0, action: 'json'}, isArray: true}, query: {method: 'GET', params:{ all: 0, action: 'json'}, isArray: true},
get :{method: 'GET', params: { action:'json'}}, get :{method: 'GET', params: { action:'json'}},
search :{method: 'GET', params: { action:'search'}}, search :{method: 'GET', params: { action:'search'}},
@ -31,30 +31,33 @@ angular.module('dockerui.services', ['ngResource'])
delete :{id: '@id', method: 'DELETE'} delete :{id: '@id', method: 'DELETE'}
}); });
}) })
.factory('Docker', function($resource, DOCKER_ENDPOINT) { .factory('Docker', function($resource, Settings) {
// Information for docker // Information for docker
// http://docs.docker.io/en/latest/api/docker_remote_api.html#display-system-wide-information // http://docs.docker.io/en/latest/api/docker_remote_api.html#display-system-wide-information
return $resource(DOCKER_ENDPOINT + '/version', {}, { return $resource(Settings.url + '/version', {}, {
get: {method: 'GET'} get: {method: 'GET'}
}); });
}) })
.factory('Auth', function($resource, DOCKER_ENDPOINT) { .factory('Auth', function($resource, Settings) {
// Auto Information for docker // Auto Information for docker
// http://docs.docker.io/en/latest/api/docker_remote_api.html#set-auth-configuration // http://docs.docker.io/en/latest/api/docker_remote_api.html#set-auth-configuration
return $resource(DOCKER_ENDPOINT + '/auth', {}, { return $resource(Settings.url + '/auth', {}, {
get: {method: 'GET'}, get: {method: 'GET'},
update: {method: 'POST'} update: {method: 'POST'}
}); });
}) })
.factory('System', function($resource, DOCKER_ENDPOINT) { .factory('System', function($resource, Settings) {
// System for docker // System for docker
// http://docs.docker.io/en/latest/api/docker_remote_api.html#display-system-wide-information // http://docs.docker.io/en/latest/api/docker_remote_api.html#display-system-wide-information
return $resource(DOCKER_ENDPOINT + '/info', {}, { return $resource(Settings.url + '/info', {}, {
get: {method: 'GET'} get: {method: 'GET'}
}); });
}) })
.factory('Settings', function() { .factory('Settings', function(DOCKER_ENDPOINT, DOCKER_API_VERSION) {
return { return {
displayAll: false displayAll: false,
endpoint: DOCKER_ENDPOINT,
version: DOCKER_API_VERSION,
url: DOCKER_ENDPOINT + DOCKER_API_VERSION
}; };
}); });

@ -0,0 +1,13 @@
<div class="row-fluid">
<!--<div class="sidebar span4">
<div ng-include="template" ng-controller="SideBarController"></div>
</div>-->
<div class="span12">
<div class="jumbotron">
<h1>DockerUI</h1>
<p class="lead">The Linux container engine</p>
<a class="btn btn-large btn-success" href="http://docker.io">Learn more.</a>
</div>
</div>
</div>

@ -1,7 +0,0 @@
<div class="jumbotron">
<h1>DockerUI</h1>
<p class="lead">The Linux container engine</p>
<a class="btn btn-large btn-success" href="http://docker.io">Learn more.</a>
</div>
<hr>

@ -4,7 +4,7 @@
<div class="navbar-inner"> <div class="navbar-inner">
<div class="container"> <div class="container">
<ul class="nav"> <ul class="nav">
<li class="{{ hclass }}" ng-click="linkChange('home')"><a href="#">Home</a></li> <li class="{{ hclass }}" ng-click="linkChange('home')"><a href="#">Dashboard</a></li>
<li class="{{ cclass }}" ng-click="linkChange('containers')"><a href="/#/containers/">Containers</a></li> <li class="{{ cclass }}" ng-click="linkChange('containers')"><a href="/#/containers/">Containers</a></li>
<li class="{{ iclass }}" ng-click="linkChange('images')"><a href="/#/images/">Images</a></li> <li class="{{ iclass }}" ng-click="linkChange('images')"><a href="/#/images/">Images</a></li>
<li class="{{ sclass }}" ng-click="linkChange('settings')"><a href="/#/settings/">Settings</a></li> <li class="{{ sclass }}" ng-click="linkChange('settings')"><a href="/#/settings/">Settings</a></li>

@ -6,9 +6,11 @@
<h3>Docker Information</h3> <h3>Docker Information</h3>
<div> <div>
<p class="lead"> <p class="lead">
<strong>Version</strong>{{ docker.Version }}<br /> <strong>Endpoint: </strong>{{ endpoint }}<br />
<strong>GitCommit</strong>{{ docker.GitCommit }}<br /> <strong>Api Version: </strong>{{ apiVersion }}<br />
<strong>GoVersion</strong>{{ docker.GoVersion }}<br /> <strong>Version: </strong>{{ docker.Version }}<br />
<strong>Git Commit: </strong>{{ docker.GitCommit }}<br />
<strong>Go Version: </strong>{{ docker.GoVersion }}<br />
</p> </p>
</div> </div>

@ -0,0 +1,11 @@
<div class="well">
<strong>Running containers:</strong>
<br />
<strong>Endpoint: </strong>{{ endpoint }}
<ul>
<li ng-repeat="container in containers">
<a href="/#/containers/{{ container.Id }}/">{{ container.Id|truncate:20 }}</a>
<span class="pull-right label label-{{ container.Status|statusbadge }}">{{ container.Status }}</span>
</li>
</ul>
</div>
Loading…
Cancel
Save