Merge branch 'server' into dev

pull/2/head
Michael Crosby 12 years ago
commit 95662bfd1a

1
.gitignore vendored

@ -0,0 +1 @@
dockerui

@ -0,0 +1,15 @@
# Dockerfile for DockerUI
FROM ubuntu
MAINTAINER Michael Crosby http://crosbymichael.com
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update
RUN apt-get upgrade
ADD . /app/
ADD dockerui dockerui
EXPOSE 9000:9000

@ -102,7 +102,7 @@
margin: 0 auto;
}
#editor {
#editor {
height: 300px;
width: 100%;
border: 1px solid #DDD;
@ -110,6 +110,7 @@
}
.messages {
overflow: scroll;
max-height: 50px;
overflow-y: scroll;
overflow-x: hidden;
}

@ -0,0 +1,71 @@
package main
import (
"flag"
"fmt"
"github.com/elazarl/goproxy"
"log"
"net/http"
"strings"
)
var (
endpoint = flag.String("e", "", "Docker d endpoint.")
verbose = flag.Bool("v", false, "Verbose logging.")
port = flag.String("p", "9000", "Port to serve dockerui.")
)
type multiHandler struct {
base http.Handler
proxy *goproxy.ProxyHttpServer
verbose bool
}
func (h *multiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if h.verbose {
log.Printf("%s: %s\n", r.Method, r.URL.String())
}
if isDockerRequest(r.URL.String()) {
h.proxy.ServeHTTP(w, r)
} else {
h.base.ServeHTTP(w, r)
}
}
func isDockerRequest(url string) bool {
return strings.Contains(url, "dockerapi/")
}
func createHandler(dir string) http.Handler {
fileHandler := http.FileServer(http.Dir(dir))
proxy := goproxy.NewProxyHttpServer()
proxy.Verbose = *verbose
proxy.OnRequest().DoFunc(func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
c := http.Client{}
path := strings.Replace(r.URL.RequestURI(), "dockerapi/", "", -1)
n, err := http.NewRequest(r.Method, *endpoint+path, r.Body)
n.Header = r.Header
if err != nil {
log.Fatal(err)
}
resp, err := c.Do(n)
if err != nil {
log.Fatal(err)
}
return r, resp
})
return &multiHandler{base: fileHandler, proxy: proxy, verbose: *verbose}
}
func main() {
flag.Parse()
path := fmt.Sprintf(":%s", *port)
handler := createHandler("/app")
log.Fatal(http.ListenAndServe(path, handler))
}

@ -11,7 +11,8 @@ angular.module('dockerui', ['dockerui.services', 'dockerui.filters'])
$routeProvider.otherwise({redirectTo: '/'});
}])
// This is your docker url that the api will use to make requests
.constant('DOCKER_ENDPOINT', 'http://192.168.1.9')
.constant('DOCKER_PORT', ':4243')
// You need to set this to the api endpoint without the port i.e. http://192.168.1.9
.constant('DOCKER_ENDPOINT', '/dockerapi')
.constant('DOCKER_PORT', '') // Docker port, leave as an empty string if no port is requred. i.e. 4243
.constant('UI_VERSION', 'v0.2')
.constant('DOCKER_API_VERSION', 'v1.1');
.constant('DOCKER_API_VERSION', 'v1.2');

@ -10,14 +10,14 @@ function MessageController($scope, Messages) {
$scope.template = 'partials/messages.html';
$scope.messages = [];
$scope.$watch('messages.length', function(o, n) {
$('#message-display').show();
$('#message-display').show();
});
$scope.$on(Messages.event, function(e, msg) {
$scope.messages.push(msg);
setTimeout(function() {
$('#message-display').hide('slow');
}, 10000);
$('#message-display').hide('slow');
}, 30000);
});
}
@ -38,70 +38,62 @@ function SideBarController($scope, Container, Settings) {
});
}
function SettingsController($scope, Auth, System, Docker, Settings, Messages) {
$scope.auth = {};
function SettingsController($scope, System, Docker, Settings, Messages) {
$scope.info = {};
$scope.docker = {};
$scope.endpoint = Settings.endpoint;
$scope.apiVersion = Settings.version;
$scope.updateAuthInfo = function() {
if ($scope.auth.password != $scope.auth.cpassword) {
alert('Your passwords do not match.');
return;
}
Auth.update({
username: $scope.auth.username,
email: $scope.auth.email,
password: $scope.auth.password
}, function(d) {
Messages.send({class: 'text-success', data: 'Auth information updated.'});
}, function(e) {
Messages.send({class: 'text-error', data: e.data});
});
};
Auth.get({}, function(d) { $scope.auth = d; });
Docker.get({}, function(d) { $scope.docker = d; });
System.get({}, function(d) { $scope.info = d; });
}
// Controls the page that displays a single container and actions on that container.
function ContainerController($scope, $routeParams, $location, Container, Messages) {
function ContainerController($scope, $routeParams, $location, Container, Messages, ViewSpinner) {
$scope.changes = [];
$scope.start = function(){
ViewSpinner.spin();
Container.start({id: $routeParams.id}, function(d) {
Messages.send({class: 'text-success', data: 'Container started.'});
ViewSpinner.stop();
}, function(e) {
failedRequestHandler(e, Messages);
ViewSpinner.stop();
});
};
$scope.stop = function() {
ViewSpinner.spin();
Container.stop({id: $routeParams.id}, function(d) {
Messages.send({class: 'text-success', data: 'Container stopped.'});
ViewSpinner.stop();
}, function(e) {
failedRequestHandler(e, Messages);
ViewSpinner.stop();
});
};
$scope.kill = function() {
ViewSpinner.spin();
Container.kill({id: $routeParams.id}, function(d) {
Messages.send({class: 'text-success', data: 'Container killed.'});
ViewSpinner.stop();
}, function(e) {
failedRequestHandler(e, Messages);
ViewSpinner.stop();
});
};
$scope.remove = function() {
if (confirm("Are you sure you want to remove the container?")) {
Container.remove({id: $routeParams.id}, function(d) {
Messages.send({class: 'text-success', data: 'Container removed.'});
}, function(e){
failedRequestHandler(e, Messages);
});
}
ViewSpinner.spin();
Container.remove({id: $routeParams.id}, function(d) {
Messages.send({class: 'text-success', data: 'Container removed.'});
ViewSpinner.stop();
}, function(e){
failedRequestHandler(e, Messages);
ViewSpinner.stop();
});
};
$scope.hasContent = function(data) {
@ -141,12 +133,25 @@ function ContainersController($scope, Container, Settings, Messages, ViewSpinner
};
var batch = function(items, action) {
ViewSpinner.spin();
var counter = 0;
var complete = function() {
counter = counter -1;
if (counter === 0) {
ViewSpinner.stop();
}
};
angular.forEach(items, function(c) {
if (c.Checked) {
counter = counter + 1;
action({id: c.Id}, function(d) {
Messages.send({class: 'text-success', data: d});
Messages.send({class: 'text-success', data: 'Container ' + c.Id + ' Removed.'});
var index = $scope.containers.indexOf(c);
$scope.containers.splice(index, 1);
complete();
}, function(e) {
failedRequestHandler(e, Messages);
complete();
});
}
});
@ -157,7 +162,7 @@ function ContainersController($scope, Container, Settings, Messages, ViewSpinner
i.Checked = $scope.toggle;
});
};
$scope.toggleGetAll = function() {
Settings.displayAll = $scope.displayAll;
var data = {all: 0};
@ -190,6 +195,7 @@ function ContainersController($scope, Container, Settings, Messages, ViewSpinner
// Controller for the list of images
function ImagesController($scope, Image, ViewSpinner, Messages) {
$scope.toggle = false;
$scope.predicate = '-Created';
$scope.showBuilder = function() {
$('#build-modal').modal('show');
@ -204,7 +210,7 @@ function ImagesController($scope, Image, ViewSpinner, Messages) {
ViewSpinner.stop();
}
};
angular.forEach($scope.images, function(i) {
angular.forEach($scope.images, function(i) {
if (i.Checked) {
counter = counter + 1;
Image.remove({id: i.Id}, function(d) {
@ -222,7 +228,7 @@ function ImagesController($scope, Image, ViewSpinner, Messages) {
}
});
};
$scope.toggleSelectAll = function() {
angular.forEach($scope.images, function(i) {
i.Checked = $scope.toggle;
@ -243,15 +249,13 @@ function ImagesController($scope, Image, ViewSpinner, Messages) {
function ImageController($scope, $routeParams, $location, Image, Messages) {
$scope.history = [];
$scope.tag = {repo: '', force: false};
$scope.remove = function() {
if (confirm("Are you sure you want to delete this image?")) {
Image.remove({id: $routeParams.id}, function(d) {
Messages.send({class: 'text-success', data: 'Image removed.'});
}, function(e) {
failedRequestHandler(e, Messages);
});
}
Image.remove({id: $routeParams.id}, function(d) {
Messages.send({class: 'text-success', data: 'Image removed.'});
}, function(e) {
failedRequestHandler(e, Messages);
});
};
$scope.getHistory = function() {
@ -307,10 +311,10 @@ function StartContainerController($scope, $routeParams, $location, Container, Me
var s = $scope;
Container.create({
Image: id,
Memory: $scope.config.memory,
MemorySwap: $scope.config.memorySwap,
Cmd: cmds,
Image: id,
Memory: $scope.config.memory,
MemorySwap: $scope.config.memorySwap,
Cmd: cmds,
VolumesFrom: $scope.config.volumesFrom
}, function(d) {
if (d.Id) {
@ -331,12 +335,19 @@ function BuilderController($scope, Dockerfile, Messages) {
$scope.template = '/partials/builder.html';
ace.config.set('basePath', '/lib/ace-builds/src-noconflict/');
var spinner = new Spinner();
$scope.build = function() {
spinner.spin(document.getElementById('build-modal'));
Dockerfile.build(editor.getValue(), function(d) {
Messages.send({class:'text-info', data: d});
console.log(d.currentTarget.response);
$scope.messages = d.currentTarget.response;
$scope.$apply();
spinner.stop();
}, function(e) {
Messages.send({class:'text-error', data: e});
$scope.messages = e;
$scope.$apply();
spinner.stop();
});
};
}

@ -80,12 +80,12 @@ angular.module('dockerui.services', ['ngResource'])
return {
event: 'messageSend',
send: function(msg) {
$rootScope.$broadcast('messageSend', msg);
}
$rootScope.$broadcast('messageSend', msg);
}
};
})
.factory('Dockerfile', function(Settings) {
var url = Settings.rawUrl + '/build';
var url = Settings.rawUrl + '/build';
return {
build: function(file, callback) {
var data = new FormData();

@ -5,6 +5,7 @@
</div>
<div class="modal-body">
<div id="editor"></div>
<p>{{ messages }}</p>
</div>
<div class="modal-footer">
<a href="" class="btn btn-primary" ng-click="build()">Build</a>

@ -23,6 +23,11 @@
<td>Container:</td>
<td><a href="/#/containers/{{ image.container }}/">{{ image.container }}</a></td>
</tr>
<tr>
<td>Size:</td>
<td>{{ image.Size|humansize }}</td>
</tr>
<tr>
<td>Hostname:</td>
<td>{{ image.container_config.Hostname }}</td>
@ -43,10 +48,14 @@
<td>Volumes from:</td>
<td>{{ image.container_config.VolumesFrom }}</td>
</tr>
<tr>
<td>Comment:</td>
<td>{{ image.comment }}</td>
</tr>
</tbody>
</table>
<div class="row-fluid">
<div class="span1">
History:

@ -46,20 +46,4 @@
</tr>
</tbody>
</table>
<form>
<fieldset>
<legend>Auth Information</legend>
<label>Username:</label>
<input type="text" ng-model="auth.username" required>
<label>Email:</label>
<input type="text" ng-model="auth.email" required>
<label>Password:</label>
<input type="password" ng-model="auth.password" required>
<label>Confirm Password:</label>
<input type="password" ng-model="auth.cpassword" required>
<br />
<input type="button" ng-click="updateAuthInfo()" value="Update"/>
</fieldset>
</form>
</div>

Loading…
Cancel
Save