From 9360693f8daa2dc4408e3815bbadfc2d3ea41e20 Mon Sep 17 00:00:00 2001 From: Anthony Lapenna Date: Thu, 16 Jun 2016 17:37:57 +1200 Subject: [PATCH 01/11] clean:all on release grunt task --- gruntFile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gruntFile.js b/gruntFile.js index fd6c06e01..429f2d957 100644 --- a/gruntFile.js +++ b/gruntFile.js @@ -24,7 +24,7 @@ module.exports = function (grunt) { 'copy' ]); grunt.registerTask('release', [ - 'clean:app', + 'clean:all', 'if:binaryNotExist', 'html2js', 'uglify', From 54c82a3a5c0c1cacbfaa8e08317ecb497404f695 Mon Sep 17 00:00:00 2001 From: Anthony Lapenna Date: Thu, 16 Jun 2016 17:39:59 +1200 Subject: [PATCH 02/11] add section in README about Swarm support --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 5810918db..42a937257 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,14 @@ You can use the `-e` flag to change this socket: # Connect to a tcp socket: $ docker run -d -p 9000:9000 --privileged cloudinovasi/cloudinovasi-ui -e http://127.0.0.1:2375 +### Swarm support + +You can access a specific view for you Swarm cluster by defining the `-s` option: + + # Connect to a tcp socket and enable Swarm: + $ docker run -d -p 9000:9000 --privileged cloudinovasi/cloudinovasi-ui -e http://: -s + + ### Change address/port UI For Docker is served on UI For Docker listens on port 9000 by default. If you run UI For Docker inside a container then you can bind the container's internal port to any external address and port: From 9ca2aa9bbd9ae9d3adbbc2481d1cd1b71438f2ac Mon Sep 17 00:00:00 2001 From: Anthony Lapenna Date: Tue, 21 Jun 2016 12:27:32 +1200 Subject: [PATCH 03/11] refactor(dockerui): replace -s flag with -swarm --- README.md | 7 ++++--- dockerui.go | 2 +- gruntFile.js | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 42a937257..bda4ee10c 100644 --- a/README.md +++ b/README.md @@ -26,15 +26,16 @@ By default UI For Docker connects to the Docker daemon with`/var/run/docker.sock You can use the `-e` flag to change this socket: # Connect to a tcp socket: - $ docker run -d -p 9000:9000 --privileged cloudinovasi/cloudinovasi-ui -e http://127.0.0.1:2375 + $ docker run -d -p 9000:9000 cloudinovasi/cloudinovasi-ui -e http://127.0.0.1:2375 ### Swarm support -You can access a specific view for you Swarm cluster by defining the `-s` option: +You can access a specific view for you Swarm cluster by defining the `-swarm` flag: # Connect to a tcp socket and enable Swarm: - $ docker run -d -p 9000:9000 --privileged cloudinovasi/cloudinovasi-ui -e http://: -s + $ docker run -d -p 9000:9000 cloudinovasi/cloudinovasi-ui -e http://: -swarm +*NOTE*: At the moment, only *Swarm 1.2.0* is supported. ### Change address/port UI For Docker is served on UI For Docker listens on port 9000 by default. If you run UI For Docker inside a container then you can bind the container's internal port to any external address and port: diff --git a/dockerui.go b/dockerui.go index fd20836b7..6d51a16a0 100644 --- a/dockerui.go +++ b/dockerui.go @@ -21,7 +21,7 @@ var ( endpoint = flag.String("e", "/var/run/docker.sock", "Dockerd endpoint") addr = flag.String("p", ":9000", "Address and port to serve UI For Docker") assets = flag.String("a", ".", "Path to the assets") - swarm = flag.Bool("s", false, "Swarm mode") + swarm = flag.Bool("swarm", false, "Swarm mode") authKey []byte authKeyFile = "authKey.dat" ) diff --git a/gruntFile.js b/gruntFile.js index 429f2d957..51df529df 100644 --- a/gruntFile.js +++ b/gruntFile.js @@ -267,7 +267,7 @@ module.exports = function (grunt) { command: [ 'docker stop ui-for-docker', 'docker rm ui-for-docker', - 'docker run --privileged -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock --name ui-for-docker ui-for-docker -s' + 'docker run --privileged -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock --name ui-for-docker ui-for-docker -swarm' ].join(';') }, cleanImages: { From 9468839bf9e1bc52fa7d6aeab0c97a05623465d1 Mon Sep 17 00:00:00 2001 From: Anthony Lapenna Date: Tue, 21 Jun 2016 18:34:32 +1200 Subject: [PATCH 04/11] chore(grunt): run-swarm task expect a Swarm cluster at 10.0.7.10:4000 --- gruntFile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gruntFile.js b/gruntFile.js index 51df529df..7f54ff697 100644 --- a/gruntFile.js +++ b/gruntFile.js @@ -267,7 +267,7 @@ module.exports = function (grunt) { command: [ 'docker stop ui-for-docker', 'docker rm ui-for-docker', - 'docker run --privileged -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock --name ui-for-docker ui-for-docker -swarm' + 'docker run --privileged -d -p 9000:9000 --name ui-for-docker ui-for-docker -e http://10.0.7.10:4000 -swarm' ].join(';') }, cleanImages: { From 91f3b1f1389076720b8c2b83d637446310bf11ac Mon Sep 17 00:00:00 2001 From: Anthony Lapenna Date: Tue, 21 Jun 2016 18:35:21 +1200 Subject: [PATCH 05/11] refactor(service): Config factory returns a promise --- app/components/dashboard/master-ctrl.js | 2 +- app/shared/services.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/dashboard/master-ctrl.js b/app/components/dashboard/master-ctrl.js index 330952b41..9d5080005 100644 --- a/app/components/dashboard/master-ctrl.js +++ b/app/components/dashboard/master-ctrl.js @@ -9,7 +9,7 @@ angular.module('dashboard') return window.innerWidth; }; - $scope.config = Config.get(); + $scope.config = Config; $scope.$watch($scope.getWidth, function(newValue, oldValue) { if (newValue >= mobileView) { diff --git a/app/shared/services.js b/app/shared/services.js index 5a16cb192..1085cdd58 100644 --- a/app/shared/services.js +++ b/app/shared/services.js @@ -143,7 +143,7 @@ angular.module('dockerui.services', ['ngResource', 'ngSanitize']) }); }]) .factory('Config', ['$resource', 'CONFIG_ENDPOINT', function($resource, CONFIG_ENDPOINT) { - return $resource(CONFIG_ENDPOINT); + return $resource(CONFIG_ENDPOINT).get(); }]) .factory('Settings', ['DOCKER_ENDPOINT', 'DOCKER_PORT', 'UI_VERSION', function SettingsFactory(DOCKER_ENDPOINT, DOCKER_PORT, UI_VERSION) { 'use strict'; From abfa921b7acf97c5c0278d2ebf83314a3671a109 Mon Sep 17 00:00:00 2001 From: Anthony Lapenna Date: Thu, 23 Jun 2016 17:36:01 +1200 Subject: [PATCH 06/11] feat(ui): new logo size --- assets/css/app.css | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/assets/css/app.css b/assets/css/app.css index 0d99e9de8..b8d40de69 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -116,8 +116,11 @@ .logo { display: inline; - width: 110px; - max-height: 38px; + width: 100%; + max-width: 160px; + height: 100%; + max-height: 55px; + margin-bottom: 5px; } .containerNameInput { From cd12243b0f74dfa0c3104b3a503730e2ef10e9a8 Mon Sep 17 00:00:00 2001 From: Anthony Lapenna Date: Fri, 24 Jun 2016 10:11:25 +1200 Subject: [PATCH 07/11] feat(ui): latest Swarm API support (#18) * feat(ui): latest Swarm API support --- README.md | 4 +++- app/components/swarm/swarm.html | 8 ++++++++ app/components/swarm/swarmController.js | 5 +++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bda4ee10c..829461600 100644 --- a/README.md +++ b/README.md @@ -30,12 +30,14 @@ You can use the `-e` flag to change this socket: ### Swarm support +**Supported Swarm version: 1.2.3** + You can access a specific view for you Swarm cluster by defining the `-swarm` flag: # Connect to a tcp socket and enable Swarm: $ docker run -d -p 9000:9000 cloudinovasi/cloudinovasi-ui -e http://: -swarm -*NOTE*: At the moment, only *Swarm 1.2.0* is supported. +*NOTE*: Due to Swarm not exposing information in a machine readable way, the app is bound to a specific version of Swarm at the moment. ### Change address/port UI For Docker is served on UI For Docker listens on port 9000 by default. If you run UI For Docker inside a container then you can bind the container's internal port to any external address and port: diff --git a/app/components/swarm/swarm.html b/app/components/swarm/swarm.html index ee95f7115..19c621a2b 100644 --- a/app/components/swarm/swarm.html +++ b/app/components/swarm/swarm.html @@ -115,6 +115,13 @@ + + + Engine + + + + Status @@ -129,6 +136,7 @@ {{ node.name }} {{ node.ip }} {{ node.containers }} + {{ node.version }} {{ node.status }} diff --git a/app/components/swarm/swarmController.js b/app/components/swarm/swarmController.js index 3734383da..a3b096076 100644 --- a/app/components/swarm/swarmController.js +++ b/app/components/swarm/swarmController.js @@ -42,7 +42,7 @@ angular.module('swarm', []) var node_offset = 4; for (i = 0; i < node_count; i++) { extractNodeInfo(info, node_offset); - node_offset += 9; + node_offset += 10; } } @@ -50,7 +50,8 @@ angular.module('swarm', []) var node = {}; node.name = info[offset][0]; node.ip = info[offset][1]; - node.status = info[offset + 1][1]; + node.id = info[offset + 1][1]; + node.status = info[offset + 2][1]; node.containers = info[offset + 2][1]; node.cpu = info[offset + 3][1]; node.memory = info[offset + 4][1]; From 808694d6b5c45d6c49fba61d13a8710386f79805 Mon Sep 17 00:00:00 2001 From: Anthony Lapenna Date: Fri, 24 Jun 2016 10:11:49 +1200 Subject: [PATCH 08/11] feat(global): hide containers with labels using -l flag (#19) --- README.md | 16 +++++ .../containers/containersController.js | 35 +++++++++-- dockerui.go | 63 +++++++++++++++---- 3 files changed, 95 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 829461600..a3c7b1dc8 100644 --- a/README.md +++ b/README.md @@ -44,3 +44,19 @@ UI For Docker listens on port 9000 by default. If you run UI For Docker inside a # Expose UI For Docker on 10.20.30.1:80 $ docker run -d -p 10.20.30.1:80:9000 --privileged -v /var/run/docker.sock:/var/run/docker.sock cloudinovasi/cloudinovasi-ui + +### Hide containers with specifc labels + +You can hide specific containers from the containers view by using the `-hide-label` or `-l` options and specifying a label. + +For example, take a container started with the label `owner=acme`: + +``` +$ docker run -d --label owner=acme nginx +``` + +You can hide it in the view by starting the ui with: + +``` +$ docker run -d -p 9000:9000 --privileged -v /var/run/docker.sock:/var/run/docker.sock cloudinovasi/cloudinovasi-ui -l owner=acme +``` diff --git a/app/components/containers/containersController.js b/app/components/containers/containersController.js index 0672cda7f..62ea46930 100644 --- a/app/components/containers/containersController.js +++ b/app/components/containers/containersController.js @@ -1,6 +1,6 @@ angular.module('containers', []) -.controller('ContainersController', ['$scope', 'Container', 'Settings', 'Messages', 'ViewSpinner', -function ($scope, Container, Settings, Messages, ViewSpinner) { +.controller('ContainersController', ['$scope', 'Container', 'Settings', 'Messages', 'ViewSpinner', 'Config', +function ($scope, Container, Settings, Messages, ViewSpinner, Config) { $scope.state = {}; $scope.state.displayAll = Settings.displayAll; @@ -18,9 +18,11 @@ function ($scope, Container, Settings, Messages, ViewSpinner) { ViewSpinner.spin(); $scope.state.selectedItemCount = 0; Container.query(data, function (d) { - $scope.containers = d.filter(function (container) { - return container.Image !== 'swarm'; - }).map(function (container) { + var containers = d; + if (hiddenLabels) { + containers = hideContainers(d); + } + $scope.containers = containers.map(function (container) { return new ContainerViewModel(container); }); ViewSpinner.stop(); @@ -134,5 +136,26 @@ function ($scope, Container, Settings, Messages, ViewSpinner) { batch($scope.containers, Container.remove, "Removed"); }; - update({all: Settings.displayAll ? 1 : 0}); + var hideContainers = function (containers) { + return containers.filter(function (container) { + var filterContainer = false; + hiddenLabels.forEach(function(label, index) { + if (_.has(container.Labels, label.name) && + container.Labels[label.name] === label.value) { + filterContainer = true; + console.log('Hide: ' + container.Names[0]); + + } + }); + if (!filterContainer) { + return container; + } + }); + }; + + var hiddenLabels; + Config.$promise.then(function (c) { + hiddenLabels = c.hiddenLabels; + update({all: Settings.displayAll ? 1 : 0}); + }); }]); diff --git a/dockerui.go b/dockerui.go index 6d51a16a0..51e9f5102 100644 --- a/dockerui.go +++ b/dockerui.go @@ -1,7 +1,6 @@ package main // import "github.com/cloudinovasi/ui-for-docker" import ( - "flag" "io" "log" "net" @@ -15,13 +14,15 @@ import ( "io/ioutil" "fmt" "github.com/gorilla/securecookie" + "gopkg.in/alecthomas/kingpin.v2" ) var ( - endpoint = flag.String("e", "/var/run/docker.sock", "Dockerd endpoint") - addr = flag.String("p", ":9000", "Address and port to serve UI For Docker") - assets = flag.String("a", ".", "Path to the assets") - swarm = flag.Bool("swarm", false, "Swarm mode") + endpoint = kingpin.Flag("endpoint", "Dockerd endpoint").Default("/var/run/docker.sock").Short('e').String() + addr = kingpin.Flag("bind", "Address and port to serve UI For Docker").Default(":9000").Short('p').String() + assets = kingpin.Flag("assets", "Path to the assets").Default(".").Short('a').String() + swarm = kingpin.Flag("swarm", "Swarm cluster support").Default("false").Short('s').Bool() + labels = LabelParser(kingpin.Flag("hide-label", "Hide containers with a specific label in the UI").Short('l')) authKey []byte authKeyFile = "authKey.dat" ) @@ -32,6 +33,40 @@ type UnixHandler struct { type Config struct { Swarm bool `json:"swarm"` + HiddenLabels Labels `json:"hiddenLabels"` +} + +type Label struct { + Name string `json:"name"` + Value string `json:"value"` +} + +type Labels []Label + +func (l *Labels) Set(value string) error { + parts := strings.SplitN(value, "=", 2) + if len(parts) != 2 { + return fmt.Errorf("expected HEADER=VALUE got '%s'", value) + } + label := new(Label) + label.Name = parts[0] + label.Value = parts[1] + *l = append(*l, *label) + return nil +} + +func (l *Labels) String() string { + return "" +} + +func (l *Labels) IsCumulative() bool { + return true +} + +func LabelParser(s kingpin.Settings) (target *[]Label) { + target = new([]Label) + s.SetValue((*Labels)(target)) + return } func (h *UnixHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { @@ -82,7 +117,7 @@ func createUnixHandler(e string) http.Handler { return &UnixHandler{e} } -func createHandler(dir string, e string, s bool) http.Handler { +func createHandler(dir string, e string, c Config) http.Handler { var ( mux = http.NewServeMux() fileHandler = http.FileServer(http.Dir(dir)) @@ -120,14 +155,10 @@ func createHandler(dir string, e string, s bool) http.Handler { csrf.Secure(false), ) - configuration := Config{ - Swarm: s, - } - mux.Handle("/dockerapi/", http.StripPrefix("/dockerapi", h)) mux.Handle("/", fileHandler) mux.HandleFunc("/config", func(w http.ResponseWriter, r *http.Request) { - configurationHandler(w, r, configuration) + configurationHandler(w, r, c) }) return CSRF(csrfWrapper(mux)) } @@ -140,9 +171,15 @@ func csrfWrapper(h http.Handler) http.Handler { } func main() { - flag.Parse() + kingpin.Version("1.0.3") + kingpin.Parse() - handler := createHandler(*assets, *endpoint, *swarm) + configuration := Config{ + Swarm: *swarm, + HiddenLabels: *labels, + } + + handler := createHandler(*assets, *endpoint, configuration) if err := http.ListenAndServe(*addr, handler); err != nil { log.Fatal(err) } From 9655f57698626532a8e72691077cf55244c115c2 Mon Sep 17 00:00:00 2001 From: Anthony Lapenna Date: Fri, 24 Jun 2016 10:22:04 +1200 Subject: [PATCH 09/11] docs(global): review documentation --- README.md | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index a3c7b1dc8..db5f23915 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Cloudinovasi UI for Docker +# Cloudinovasi UI for Docker A fork of the amazing UI for Docker by Michael Crosby and Kevan Ahlquist (https://github.com/kevana/ui-for-docker) using the rdash-angular theme (https://github.com/rdash/rdash-angular). @@ -6,11 +6,14 @@ A fork of the amazing UI for Docker by Michael Crosby and Kevan Ahlquist (https: UI For Docker is a web interface for the Docker Remote API. The goal is to provide a pure client side implementation so it is effortless to connect and manage docker. -### Goals +## Goals * Minimal dependencies - I really want to keep this project a pure html/js app. * Consistency - The web UI should be consistent with the commands found on the docker CLI. +## Run + ### Quickstart + 1. Run: `docker run -d -p 9000:9000 --privileged -v /var/run/docker.sock:/var/run/docker.sock cloudinovasi/cloudinovasi-ui` 2. Open your browser to `http://:9000` @@ -25,8 +28,10 @@ By default UI For Docker connects to the Docker daemon with`/var/run/docker.sock You can use the `-e` flag to change this socket: - # Connect to a tcp socket: - $ docker run -d -p 9000:9000 cloudinovasi/cloudinovasi-ui -e http://127.0.0.1:2375 +``` +# Connect to a tcp socket: +$ docker run -d -p 9000:9000 cloudinovasi/cloudinovasi-ui -e http://127.0.0.1:2375 +``` ### Swarm support @@ -34,20 +39,24 @@ You can use the `-e` flag to change this socket: You can access a specific view for you Swarm cluster by defining the `-swarm` flag: - # Connect to a tcp socket and enable Swarm: - $ docker run -d -p 9000:9000 cloudinovasi/cloudinovasi-ui -e http://: -swarm +``` +# Connect to a tcp socket and enable Swarm: +$ docker run -d -p 9000:9000 cloudinovasi/cloudinovasi-ui -e http://: -swarm +``` *NOTE*: Due to Swarm not exposing information in a machine readable way, the app is bound to a specific version of Swarm at the moment. ### Change address/port UI For Docker is served on UI For Docker listens on port 9000 by default. If you run UI For Docker inside a container then you can bind the container's internal port to any external address and port: - # Expose UI For Docker on 10.20.30.1:80 - $ docker run -d -p 10.20.30.1:80:9000 --privileged -v /var/run/docker.sock:/var/run/docker.sock cloudinovasi/cloudinovasi-ui +``` +# Expose UI For Docker on 10.20.30.1:80 +$ docker run -d -p 10.20.30.1:80:9000 --privileged -v /var/run/docker.sock:/var/run/docker.sock cloudinovasi/cloudinovasi-ui +``` -### Hide containers with specifc labels +### Hide containers with specific labels -You can hide specific containers from the containers view by using the `-hide-label` or `-l` options and specifying a label. +You can hide specific containers in the containers view by using the `-hide-label` or `-l` options and specifying a label. For example, take a container started with the label `owner=acme`: @@ -60,3 +69,13 @@ You can hide it in the view by starting the ui with: ``` $ docker run -d -p 9000:9000 --privileged -v /var/run/docker.sock:/var/run/docker.sock cloudinovasi/cloudinovasi-ui -l owner=acme ``` + +### Available options + +The following options are available for the `ui-for-docker` binary: + +* `-endpoint`, `-e`: Docker deamon endpoint (default: *"/var/run/docker.sock"*) +* `-bind`, `-p`: Address and port to serve UI For Docker (default: *":9000"*) +* `-assets`, `-a`: Path to the assets (default: *"."*) +* `-swarm`, `-s`: Swarm cluster support (default: *false*) +* `-hide-label`, `-l`: Hide containers with a specific label in the UI From bf4622e4f515fc6701fd01a32c691967fb2327e2 Mon Sep 17 00:00:00 2001 From: Anthony Lapenna Date: Fri, 24 Jun 2016 10:23:12 +1200 Subject: [PATCH 10/11] refactor(ui): remove useless logging --- app/components/containers/containersController.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/components/containers/containersController.js b/app/components/containers/containersController.js index 62ea46930..c16e101f2 100644 --- a/app/components/containers/containersController.js +++ b/app/components/containers/containersController.js @@ -143,8 +143,6 @@ function ($scope, Container, Settings, Messages, ViewSpinner, Config) { if (_.has(container.Labels, label.name) && container.Labels[label.name] === label.value) { filterContainer = true; - console.log('Hide: ' + container.Names[0]); - } }); if (!filterContainer) { From ce2e6f80fcc89bfac3e24678f9dfba2043835808 Mon Sep 17 00:00:00 2001 From: Anthony Lapenna Date: Fri, 24 Jun 2016 10:24:27 +1200 Subject: [PATCH 11/11] chore(version): bump version number --- app/app.js | 2 +- bower.json | 2 +- dockerui.go | 2 +- package.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/app.js b/app/app.js index e707b41b9..0c3158372 100644 --- a/app/app.js +++ b/app/app.js @@ -120,4 +120,4 @@ angular.module('uifordocker', [ .constant('DOCKER_ENDPOINT', 'dockerapi') .constant('DOCKER_PORT', '') // Docker port, leave as an empty string if no port is requred. If you have a port, prefix it with a ':' i.e. :4243 .constant('CONFIG_ENDPOINT', '/config') - .constant('UI_VERSION', 'v1.0.3'); + .constant('UI_VERSION', 'v1.0.4'); diff --git a/bower.json b/bower.json index 91fd79d08..f4b19b158 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "uifordocker", - "version": "1.0.3", + "version": "1.0.4", "homepage": "https://github.com/kevana/ui-for-docker", "authors": [ "Michael Crosby ", diff --git a/dockerui.go b/dockerui.go index 51e9f5102..7497436d1 100644 --- a/dockerui.go +++ b/dockerui.go @@ -171,7 +171,7 @@ func csrfWrapper(h http.Handler) http.Handler { } func main() { - kingpin.Version("1.0.3") + kingpin.Version("1.0.4") kingpin.Parse() configuration := Config{ diff --git a/package.json b/package.json index 49649fdd4..536b45b17 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Michael Crosby & Kevan Ahlquist", "name": "uifordocker", "homepage": "https://github.com/kevana/ui-for-docker", - "version": "1.0.3", + "version": "1.0.4", "repository": { "type": "git", "url": "git@github.com:kevana/ui-for-docker.git"