You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2018/07/26 10:50:25 UTC

[08/28] brooklyn-ui git commit: This adds the contributed brooklyn-ui-angular code in the folder new/.

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/location-manager/app/views/wizard/byon/byon.controller.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/location-manager/app/views/wizard/byon/byon.controller.js b/new/ui-modules/location-manager/app/views/wizard/byon/byon.controller.js
new file mode 100644
index 0000000..c12c789
--- /dev/null
+++ b/new/ui-modules/location-manager/app/views/wizard/byon/byon.controller.js
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import angular from 'angular';
+import uiRouter from 'angular-ui-router';
+import brooklynApi from 'brooklyn-ui-utils/brooklyn.api/brooklyn.api';
+import {transformResponse} from '../../../components/transformers/locations.transformer';
+import template from './byon.template.html';
+
+const MODULE_NAME = 'state.wizard.byon';
+
+angular.module(MODULE_NAME, [uiRouter, brooklynApi])
+    .config(['$stateProvider', wizardByonStateConfig]);
+
+export default MODULE_NAME;
+
+export const wizardByonState = {
+    name: 'wizard.byon',
+    url: '/byon?symbolicName&version',
+    params: {
+        version: {value: null},
+        symbolicName: {value: null}
+    },
+    controller: ['$element', '$state', 'brSnackbar', 'location', 'catalogApi', wizardByonController],
+    controllerAs: 'vm',
+    template: template,
+    resolve: {
+        location: ['catalogApi', 'locationApi', '$q', '$stateParams', (catalogApi, locationApi, $q, $stateParams) => {
+            if ($stateParams.symbolicName !== null) {
+                return catalogApi.getLocation($stateParams.symbolicName, $stateParams.version, {cache: null, transformResponse: transformResponse});
+            }
+            return;
+        }]
+    }
+};
+
+export function wizardByonStateConfig($stateProvider) {
+    $stateProvider.state(wizardByonState);
+}
+
+export function wizardByonController($element, $state, brSnackbar, location, catalogApi) {
+    $element.find('input')[0].focus();
+    let vm = this;
+    mapLocation();
+
+    vm.save = function () {
+        let config = angular.copy(vm.config);
+        if (vm.user) {
+            config.user = vm.user;
+        }
+        if (vm.password) {
+            config.password = vm.password;
+        }
+        if (vm.privateKeyData) {
+            config.privateKeyData = vm.privateKeyData;
+        }
+        if (vm.privateKeyPassphrase) {
+            config.privateKeyPassphrase = vm.privateKeyPassphrase;
+        }
+        if (vm.hosts) {
+            config.hosts = vm.hosts.split("\n");
+        }
+        let payload = {
+            'brooklyn.catalog': {
+                bundle: `catalog-bom-${vm.id}`,
+                version: vm.version,
+                items: [
+                    {
+                        itemType: 'location',
+                        item: {
+                            id: vm.id,
+                            name: vm.name,
+                            type: 'byon',
+                            'brooklyn.config': config
+                        }
+                    }
+                ]
+            }
+        };
+        catalogApi.create(payload).then(data => {
+            $state.go('detail', {symbolicName: vm.id, version: vm.version});
+        }).catch(error => {
+            brSnackbar.create('Could not save location: ' + error.data.message ? error.data.message : error.data);
+        });
+    };
+
+    function mapLocation() {
+        if (location) {
+            vm.id = location.symbolicName;
+            vm.name = location.name;
+            vm.user = location.config.user;
+            vm.password = location.config.password;
+            vm.hosts = location.config.hosts.join("\n");
+            vm.version = location.version;
+            vm.privateKeyData = location.config.privateKeyData;
+            vm.privateKeyPassphrase = location.config.privateKeyPassphrase;
+            delete location.config.password;
+            delete location.config.user;
+            delete location.config.hosts;
+            delete location.config.privateKeyData;
+            delete location.config.privateKeyPassphrase;
+            vm.config = location.config;
+        } else {
+            vm.config = {};
+            vm.version = '0.0.0.SNAPSHOT';
+        }
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/location-manager/app/views/wizard/byon/byon.template.html
----------------------------------------------------------------------
diff --git a/new/ui-modules/location-manager/app/views/wizard/byon/byon.template.html b/new/ui-modules/location-manager/app/views/wizard/byon/byon.template.html
new file mode 100644
index 0000000..2335232
--- /dev/null
+++ b/new/ui-modules/location-manager/app/views/wizard/byon/byon.template.html
@@ -0,0 +1,85 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<div class="row">
+    <div class="col-md-12">
+        <p class="page-subheading">Enter the details of your new BYON location</p>
+        <div class="brooklyn-home-card">
+            <div class="title">
+                <form novalidate name="form">
+                    <div class="form-group" ng-class="{'has-error': form.id.$invalid && form.id.$touched}">
+                        <label class="control-label" for="id">Location ID*</label>
+                        <input ng-model="vm.id" type="text" class="form-control" id="id" name="id" required placeholder="A label to identify this location in YAML. Typically this is lower case using hyphens and no spaces">
+                        <p class="help-block" ng-show="form.$submitted || form.id.$touched">
+                            <span ng-show="form.id.$error.required">You must specify a location ID</span>
+                        </p>
+                    </div>
+                    <div class="form-group" ng-class="{'has-error': form.version.$invalid && form.version.$touched}">
+                        <label class="control-label" for="id">Location version*</label>
+                        <input ng-model="vm.version" type="text" class="form-control" id="version" name="version" required placeholder="A version number to identify this location">
+                        <p class="help-block" ng-show="form.$submitted || form.version.$touched">
+                            <span ng-show="form.id.$error.required">You must specify a location version</span>
+                        </p>
+                    </div>
+
+                    <div class="form-group" ng-class="{'has-error': form.name.$invalid && form.name.$touched}">
+                        <label class="control-label" for="name">Location name</label>
+                        <input ng-model="vm.name" type="text" class="form-control" id="name" name="name" placeholder="A display name to present this location to a user (optional)">
+                    </div>
+
+                    <div class="form-group" ng-class="{'has-error': form.user.$invalid && form.user.$touched}">
+                        <label class="control-label" for="user">User</label>
+                        <input ng-model="vm.user" type="text" class="form-control" id="user" name="user" placeholder="The user to use to connect to the machines">
+                    </div>
+
+                    <div class="form-group" ng-class="{'has-error': form.password.$invalid && form.password.$touched}">
+                        <label class="control-label" for="password">Password</label>
+                        <input ng-model="vm.password" type="password" class="form-control" id="password" name="password" placeholder="The password to use to connect to the machines (if using password access)">
+                    </div>
+
+                    <div class="form-group" ng-class="{'has-error': form.privateKeyData.$invalid && form.privateKeyData.$touched}">
+                        <label class="control-label" for="privateKeyData">Private key data</label>
+                        <textarea ng-model="vm.privateKeyData" class="form-control" id="privateKeyData" name="privateKeyData" rows="5" placeholder="The contents of the private key file to use to connect to the machines (if using key access, where the corresponding public key is in the .authorized_keys file on the servers)"></textarea>
+                    </div>
+
+                    <div class="form-group" ng-class="{'has-error': form.privateKeyPassphrase.$invalid && form.privateKeyPassphrase.$touched}">
+                        <label class="control-label" for="privateKeyPassphrase">Private key passphrase</label>
+                        <input ng-model="vm.privateKeyPassphrase" type="text" class="form-control" id="privateKeyPassphrase" name="privateKeyPassphrase" placeholder="The passphrase to unlock the private key specified above (if applicable)">
+                    </div>
+
+                    <div class="form-group" ng-class="{'has-error': form.hosts.$invalid && form.hosts.$touched}">
+                        <label class="control-label" for="hosts">Hosts*</label>
+                        <textarea ng-model="vm.hosts" class="form-control" id="hosts" name="hosts" rows="5" required placeholder="The IP addresses of the machines to include in this location definition, one per line" required></textarea>
+                        <p class="help-block" ng-show="form.$submitted || form.hosts.$touched">
+                            <span ng-show="form.hosts.$error.required">You must specify at least one host</span>
+                        </p>
+                    </div>
+                </form>
+
+                <section>
+                    <h3>Additional configuration</h3>
+                    <dynamic-config model="vm.config" type="configuration"></dynamic-config>
+                </section>
+
+                <div class="col-md-12 text-right">
+                    <button class="btn btn-primary btn-lg" ng-disabled="form.$invalid" ng-click="vm.save()">Save</button>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/location-manager/app/views/wizard/cloud/cloud.controller.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/location-manager/app/views/wizard/cloud/cloud.controller.js b/new/ui-modules/location-manager/app/views/wizard/cloud/cloud.controller.js
new file mode 100644
index 0000000..4e015c4
--- /dev/null
+++ b/new/ui-modules/location-manager/app/views/wizard/cloud/cloud.controller.js
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import angular from 'angular';
+import uiRouter from 'angular-ui-router';
+import brooklynApi from 'brooklyn-ui-utils/brooklyn.api/brooklyn.api';
+import {transformResponse} from '../../../components/transformers/locations.transformer';
+import locationUtils from '../../../components/location-utils/location-utils';
+import template from './cloud.template.html';
+
+const MODULE_NAME = 'state.wizard.cloud';
+
+angular.module(MODULE_NAME, [uiRouter, brooklynApi, locationUtils])
+    .config(['$stateProvider', wizardCloudStateConfig]);
+
+export default MODULE_NAME;
+
+export const wizardCloudState = {
+    name: 'wizard.cloud',
+    url: '/cloud?symbolicName&version',
+    params: {
+        version: {value: null},
+        symbolicName: {value: null}
+    },
+    controller: ['$element', '$state', 'brSnackbar', 'locationSpec', 'location', 'catalogApi', wizardCloudController],
+    controllerAs: 'vm',
+    template: template,
+    resolve: {
+        location: ['catalogApi', 'locationApi', '$q', '$stateParams', (catalogApi, locationApi, $q, $stateParams) => {
+            if ($stateParams.symbolicName !== null) {
+                return catalogApi.getLocation($stateParams.symbolicName, $stateParams.version, {cache: null, transformResponse: transformResponse});
+            }
+            return;
+        }]
+    }
+};
+
+export function wizardCloudStateConfig($stateProvider) {
+    $stateProvider.state(wizardCloudState);
+}
+
+export function wizardCloudController($element, $state, brSnackbar, locationSpec, location, catalogApi) {
+    $element.find('input')[0].focus();
+
+    let vm = this;
+    mapLocation();
+    vm.providers = locationSpec;
+
+    vm.isRegionDisabled = function () {
+        let disabled = ['jclouds:openstack-nova'];
+        return disabled.indexOf(vm.provider) > -1;
+    };
+
+    vm.isEndpointDisabled = function () {
+        let disabled = ['jclouds:aws-ec2', 'jclouds:softlayer'];
+        return disabled.indexOf(vm.provider) > -1;
+    };
+
+    vm.save = function () {
+        let config = angular.copy(vm.config);
+        if (vm.region) {
+            config.region = vm.region;
+        }
+        if (vm.endpoint) {
+            config.endpoint = vm.endpoint;
+        }
+        config.identity = vm.identity;
+        config.credential = vm.credential;
+
+        let payload = {
+            'brooklyn.catalog': {
+                bundle: `catalog-bom-${vm.id}`,
+                version: vm.version,
+                items: [
+                    {
+                        itemType: 'location',
+                        item: {
+                            id: vm.id,
+                            name: vm.name,
+                            type: vm.provider !== 'other' ? vm.provider : vm.spec,
+                            'brooklyn.config': config
+                        }
+                    }
+                ]
+            }
+        };
+        catalogApi.create(payload).then(data => {
+            $state.go('detail', {symbolicName: vm.id, version: vm.version});
+        }).catch(error => {
+            brSnackbar.create('Could not save location: ' + error.data.message ? error.data.message : error.data);
+        });
+    };
+
+    function mapLocation() {
+        if (location) {
+            vm.id = location.symbolicName;
+            vm.name = location.name;
+            vm.provider = location.spec;
+            vm.region = location.config.region;
+            vm.endpoint = location.config.endpoint;
+            vm.identity = location.config.identity;
+            vm.credential = location.config.credential;
+            vm.version = location.version;
+            delete location.config.credential;
+            delete location.config.identity;
+            delete location.config.region;
+            delete location.config.endpoint;
+            vm.config = location.config;
+        } else {
+            vm.config = {};
+            vm.version = '0.0.0.SNAPSHOT';
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/location-manager/app/views/wizard/cloud/cloud.template.html
----------------------------------------------------------------------
diff --git a/new/ui-modules/location-manager/app/views/wizard/cloud/cloud.template.html b/new/ui-modules/location-manager/app/views/wizard/cloud/cloud.template.html
new file mode 100644
index 0000000..418e2fb
--- /dev/null
+++ b/new/ui-modules/location-manager/app/views/wizard/cloud/cloud.template.html
@@ -0,0 +1,101 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<div class="row">
+    <div class="col-md-12">
+        <p class="page-subheading">Enter the details of your new cloud location</p>
+        <div class="brooklyn-home-card">
+            <div class="title">
+                <form novalidate name="form">
+                    <div class="form-group" ng-class="{'has-error': form.id.$invalid && form.id.$touched}">
+                        <label class="control-label" for="id">Location ID*</label>
+                        <input ng-model="vm.id" type="text" class="form-control" id="id" name="id" required placeholder="A label to identify this location in YAML. Typically this is lower case using hyphens and no spaces">
+                        <p class="help-block" ng-show="form.$submitted || form.id.$touched">
+                            <span ng-show="form.id.$error.required">You must specify a location ID</span>
+                        </p>
+                    </div>
+                    <div class="form-group" ng-class="{'has-error': form.version.$invalid && form.version.$touched}">
+                        <label class="control-label" for="id">Location version*</label>
+                        <input ng-model="vm.version" type="text" class="form-control" id="version" name="version" required placeholder="A version number to identify this location">
+                        <p class="help-block" ng-show="form.$submitted || form.version.$touched">
+                            <span ng-show="form.id.$error.required">You must specify a location version</span>
+                        </p>
+                    </div>
+                    <div class="form-group" ng-class="{'has-error': form.name.$invalid && form.name.$touched}">
+                        <label class="control-label" for="name">Location name</label>
+                        <input ng-model="vm.name" type="text" class="form-control" id="name" name="name" placeholder="A display name to present this location to a user (optional)">
+                    </div>
+
+                    <div class="form-group" ng-class="{'has-error': (form.provider.$invalid && form.provider.$touched) || (form.spec.$invalid && form.spec.$touched)}">
+                        <label class="control-label" for="provider">Cloud provider*</label>
+                        <div class="row">
+                            <div ng-class="{'col-md-6': vm.provider === 'other', 'col-md-12': vm.provider !== 'other'}">
+                                <select ng-model="vm.provider" class="form-control" id="provider" name="provider" required>
+                                    <option ng-repeat="(key, value) in vm.providers" value="{{key}}">{{value.name}}</option>
+                                    <option value="other">Other</option>
+                                </select>
+                            </div>
+                            <div class="col-md-6" ng-if="vm.provider === 'other'">
+                                <input ng-model="vm.spec" type="text" class="form-control" id="spec" name="spec" required placeholder="A location spec string">
+                            </div>
+                        </div>
+                        <p class="help-block" ng-show="form.$submitted || form.provider.$touched || form.spec.$touched">
+                            <span ng-show="form.provider.$error.required">You need to select one cloud provider</span>
+                            <span ng-show="form.spec.$error.required">You need to specify a location spec</span>
+                        </p>
+                    </div>
+
+                    <div class="form-group" ng-class="{'has-error': form.region.$invalid && form.region.$touched}">
+                        <label class="control-label" for="region">Cloud region</label>
+                        <input ng-model="vm.region" type="text" class="form-control" id="region" name="region" ng-disabled="vm.isRegionDisabled()" placeholder="Public cloud providers often have multiple regions available. Enter the region to use if applicable (optional)">
+                    </div>
+
+                    <div class="form-group" ng-class="{'has-error': form.endpoint.$invalid && form.endpoint.$touched}">
+                        <label class="control-label" for="endpoint">Cloud endpoint</label>
+                        <input ng-model="vm.endpoint" type="text" class="form-control" id="endpoint" name="endpoint" ng-disabled="vm.isEndpointDisabled()" placeholder="If using a private cloud, the URL to connect to it is required">
+                    </div>
+
+                    <div class="form-group" ng-class="{'has-error': form.identity.$invalid && form.identity.$touched}">
+                        <label class="control-label" for="identity">Cloud identity*</label>
+                        <input ng-model="vm.identity" type="text" class="form-control" id="identity" name="identity" required placeholder="The account name or access key to log in to this cloud">
+                        <p class="help-block" ng-show="form.$submitted || form.identity.$touched">
+                            <span ng-show="form.identity.$error.required">You must specify a cloud identity to connect to the cloud provider</span>
+                        </p>
+                    </div>
+
+                    <div class="form-group" ng-class="{'has-error': form.credential.$invalid && form.credential.$touched}">
+                        <label class="control-label" for="credential">Cloud credential*</label>
+                        <input ng-model="vm.credential" type="password" class="form-control" id="credential" name="credential" required placeholder="The password or secret key for the Cloud Identity to log in to this cloud">
+                        <p class="help-block" ng-show="form.$submitted || form.credential.$touched">
+                            <span ng-show="form.credential.$error.required">You must specify a cloud credential to connect to the cloud provider</span>
+                        </p>
+                    </div>
+                </form>
+
+                <section>
+                    <h3>Additional configuration</h3>
+                    <dynamic-config model="vm.config" type="configuration"></dynamic-config>
+                </section>
+
+                <div class="col-md-12 text-right">
+                    <button class="btn btn-primary btn-lg" ng-disabled="form.$invalid" ng-click="vm.save()">Save</button>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/location-manager/app/views/wizard/wizard.controller.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/location-manager/app/views/wizard/wizard.controller.js b/new/ui-modules/location-manager/app/views/wizard/wizard.controller.js
new file mode 100644
index 0000000..25cf70f
--- /dev/null
+++ b/new/ui-modules/location-manager/app/views/wizard/wizard.controller.js
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import angular from 'angular';
+import uiRouter from 'angular-ui-router';
+import {HIDE_INTERSTITIAL_SPINNER_EVENT} from 'brooklyn-ui-utils/interstitial-spinner/interstitial-spinner';
+import template from './wizard.template.html';
+
+const MODULE_NAME = 'state.wizard';
+
+angular.module(MODULE_NAME, [uiRouter])
+    .config(['$stateProvider', wizardStateConfig]);
+
+export default MODULE_NAME;
+
+export const wizardState = {
+    name: 'wizard',
+    url: '/wizard',
+    controller: ['$scope', '$state', wizardStateController],
+    controllerAs: 'vm',
+    template: template
+};
+
+export function wizardStateConfig($stateProvider) {
+    $stateProvider.state(wizardState);
+}
+
+export function wizardStateController($scope, $state) {
+    const {type} = $state;
+    $scope.$emit(HIDE_INTERSTITIAL_SPINNER_EVENT);
+    let vm = this;
+
+    vm.type = type;
+
+    vm.startWizard = function (type) {
+        vm.type = type;
+        $state.go('wizard.' + type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/location-manager/app/views/wizard/wizard.less
----------------------------------------------------------------------
diff --git a/new/ui-modules/location-manager/app/views/wizard/wizard.less b/new/ui-modules/location-manager/app/views/wizard/wizard.less
new file mode 100644
index 0000000..0970686
--- /dev/null
+++ b/new/ui-modules/location-manager/app/views/wizard/wizard.less
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+section {
+  border-top: 1px solid @primary-30;
+
+  & > h3 {
+    color: @primary-30;
+    font-size: 16px;
+    text-transform: uppercase;
+  }
+}
+
+.wizard {
+  cursor: pointer;
+
+  transition: background 0.3s, border 0.3s;
+  padding-top: 20px;
+  i {
+    color: #CCCCCC;
+    transition: color 0.3s;
+  }
+
+  .caption {
+    color: #31549C;
+    transition: color 0.3s;
+    margin-top: 0;
+  }
+
+  &:hover {
+    text-decoration: none;
+
+    background-color: @primary-10;
+    border: 1px solid @primary-20;
+    i {
+      color: #112C64;
+    }
+
+    .caption {
+      color: #112C64;
+    }
+  }
+
+  &.selected {
+    background-color: @primary-10;
+    border: 1px solid @primary-300;
+    i {
+      color: mix(@brand-primary, #112C64, 20%);
+    }
+
+    .caption {
+      color: mix(@brand-primary, #112C64, 20%);
+    }
+  }
+}
+
+ui-view.wizard-content {
+  display: block;
+  &.ng-enter {
+    animation: fadein 0.3s linear 0s 1 normal;
+  }
+  &.ng-leave {
+    display: none;
+  }
+}
+
+@keyframes fadein {
+  0% {
+    opacity: 0.0;
+  }
+  100% {
+    opacity: 1.0;
+  }
+}
+
+

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/location-manager/app/views/wizard/wizard.template.html
----------------------------------------------------------------------
diff --git a/new/ui-modules/location-manager/app/views/wizard/wizard.template.html b/new/ui-modules/location-manager/app/views/wizard/wizard.template.html
new file mode 100644
index 0000000..3e1827c
--- /dev/null
+++ b/new/ui-modules/location-manager/app/views/wizard/wizard.template.html
@@ -0,0 +1,58 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<div class="container">
+    <div class="row">
+        <div class="col-md-12">
+            <div class="row">
+                <div class="col-md-12">
+                    <h2 class="page-heading">Add location</h2>
+                    <p class="page-subheading">Choose which type of location you want to create</p>
+                </div>
+                <div class="col-md-4">
+                    <div class="brooklyn-home-card wizard thumbnail text-center" ng-click="vm.startWizard('cloud')" ui-sref-active="{'selected': 'wizard.cloud'}">
+                        <i class="fa fa-cloud fa-4x"></i>
+                        <div class="caption">
+                            <h3>Cloud</h3>
+                        </div>
+                    </div>
+                </div>
+
+                <div class="col-md-4">
+                    <div class="brooklyn-home-card wizard thumbnail text-center" ng-click="vm.startWizard('byon')" ui-sref-active="{'selected': 'wizard.byon'}">
+                        <i class="fa fa-file-o fa-4x"></i>
+                        <div class="caption">
+                            <h3>BYON</h3>
+                        </div>
+                    </div>
+                </div>
+
+                <div class="col-md-4">
+                    <div class="brooklyn-home-card wizard thumbnail text-center" ng-click="vm.startWizard('advanced')" ui-sref-active="{'selected': 'wizard.advanced'}">
+                        <i class="fa fa-bolt fa-4x"></i>
+                        <div class="caption">
+                            <h3>Advanced</h3>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <ui-view class="wizard-content"></ui-view>
+</div>

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/location-manager/config/build/webpack.config.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/location-manager/config/build/webpack.config.js b/new/ui-modules/location-manager/config/build/webpack.config.js
new file mode 100644
index 0000000..a050fa9
--- /dev/null
+++ b/new/ui-modules/location-manager/config/build/webpack.config.js
@@ -0,0 +1,19 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+eval(require('fs').readFileSync('../shared/config/build/webpack.config.js')+'');

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/location-manager/config/server.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/location-manager/config/server.js b/new/ui-modules/location-manager/config/server.js
new file mode 100644
index 0000000..dfba7dc
--- /dev/null
+++ b/new/ui-modules/location-manager/config/server.js
@@ -0,0 +1,19 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+eval(require('fs').readFileSync('../shared/config/server.js')+'');

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/location-manager/config/test/karma.config.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/location-manager/config/test/karma.config.js b/new/ui-modules/location-manager/config/test/karma.config.js
new file mode 100644
index 0000000..6fc6558
--- /dev/null
+++ b/new/ui-modules/location-manager/config/test/karma.config.js
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+const PRODUCTION_BUILD = process.env.NODE_ENV === 'production';
+const webpackConfig = require('./../build/webpack.config.js');
+
+module.exports = function (config) {
+    const conf = {
+        basePath: '',
+        frameworks: ['jasmine'],
+        files: [
+            {pattern: './karma.test.shim.js', watched: false}
+        ],
+        preprocessors: {
+            './karma.test.shim.js': ['webpack', 'sourcemap']
+        },
+        webpack: Object.assign({}, webpackConfig, {entry: undefined, plugins: undefined}),
+        webpackMiddleware: {
+            stats: 'errors-only'
+        },
+        webpackServer: {
+            noInfo: true
+        },
+        exclude: [],
+        colors: !PRODUCTION_BUILD,
+        logLevel: config.LOG_INFO,
+        autoWatch: !PRODUCTION_BUILD,
+        singleRun: PRODUCTION_BUILD,
+        reporters: ['progress'],
+        browsers: ['PhantomJS'],
+        plugins: [
+            require('karma-webpack'),
+            require('karma-sourcemap-loader'),
+            'karma-jasmine',
+            'karma-phantomjs-launcher'
+        ],
+        failOnEmptyTestSuite: false
+    };
+    config.set(conf);
+};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/location-manager/config/test/karma.test.shim.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/location-manager/config/test/karma.test.shim.js b/new/ui-modules/location-manager/config/test/karma.test.shim.js
new file mode 100644
index 0000000..3d926c0
--- /dev/null
+++ b/new/ui-modules/location-manager/config/test/karma.test.shim.js
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+Error.stackTraceLimit = Infinity;
+
+require('angular');
+require('angular-mocks');
+require('babel-polyfill');
+
+var testsContext = require.context('./../../app', true, /\.spec\.js$/);
+testsContext.keys().forEach(testsContext);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/location-manager/config/test/protractor.config.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/location-manager/config/test/protractor.config.js b/new/ui-modules/location-manager/config/test/protractor.config.js
new file mode 100644
index 0000000..5274c81
--- /dev/null
+++ b/new/ui-modules/location-manager/config/test/protractor.config.js
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+exports.config = {
+    framework: 'jasmine2',
+    seleniumAddress: 'http://localhost:4444/wd/hub',
+    specs: ['../../app/**/*.e2e-spec.js'],
+    baseUrl: 'http://admin:password@localhost:8080',
+    capabilities: {
+        'browserName': 'chrome',
+        'chromeOptions': {
+            'args': ['--window-size=1440,1000']
+        }
+    },
+    onPrepare: function () {
+        require('babel-register');
+    },
+    jasmineNodeOpts: {
+        // If true, print colors to the terminal.
+        showColors: true,
+        // Default time to wait in ms before a test fails.
+        defaultTimeoutInterval: 30000
+    }
+};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/location-manager/package.json
----------------------------------------------------------------------
diff --git a/new/ui-modules/location-manager/package.json b/new/ui-modules/location-manager/package.json
new file mode 100644
index 0000000..33d140f
--- /dev/null
+++ b/new/ui-modules/location-manager/package.json
@@ -0,0 +1,103 @@
+{
+  "__license__": [
+    "Licensed to the Apache Software Foundation (ASF) under one",
+    "or more contributor license agreements.  See the NOTICE file",
+    "distributed with this work for additional information",
+    "regarding copyright ownership.  The ASF licenses this file",
+    "to you under the Apache License, Version 2.0 (the",
+    "\"License\"); you may not use this file except in compliance",
+    "with the License.  You may obtain a copy of the License at",
+    "    http://www.apache.org/licenses/LICENSE-2.0",
+    "Unless required by applicable law or agreed to in writing,",
+    "software distributed under the License is distributed on an",
+    "\"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY",
+    "KIND, either express or implied.  See the License for the",
+    "specific language governing permissions and limitations",
+    "under the License."
+  ],
+  "name": "brooklyn-ui-location-manager",
+  "versionBuildNote": "BROOKLYN_VERSION_BELOW this exists so scripts update this automatically",
+  "version": "1.0.0-SNAPSHOT",
+  "description": "Brooklyn UI :: Modules - Location manager",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/apache/brooklyn-ui.git"
+  },
+  "author": "Apache Software Foundation",
+  "license": "Apache-2.0",
+  "scripts": {
+    "build": "rimraf dist && webpack --config ./config/build/webpack.config.js --bail",
+    "start": "node ./config/server.js",
+    "test": "karma start ./config/test/karma.config.js",
+    "lint": "./node_modules/.bin/eslint app/**/*.js",
+    "e2e": "protractor ./config/test/protractor.config.js"
+  },
+  "engines": {
+    "node": ">=8.0.0",
+    "npm": ">=5.0.0"
+  },
+  "brooklyn": {
+    "appname": "Location manager"
+  },
+  "dependencies": {
+    "brooklyn-ui-utils": "file:../utils",
+    "angular": "^1.6.1",
+    "angular-animate": "^1.6.1",
+    "angular-cookies": "^1.6.1",
+    "angular-ui-bootstrap": "^2.5.0",
+    "angular-ui-router": "^0.3.1",
+    "bootstrap": "^3.3.6",
+    "es6-promise": "^4.0.5",
+    "font-awesome": "^4.6.1",
+    "isomorphic-fetch": "^2.2.1",
+    "js-yaml": "^3.6.1",
+    "lodash": "^4.12.0",
+    "normalizr": "^2.1.0"
+  },
+  "devDependencies": {
+    "angular-mocks": "^1.6.1",
+    "autoprefixer": "^6.3.6",
+    "babel-core": "^6.9.1",
+    "babel-loader": "^6.2.3",
+    "babel-polyfill": "^6.20.0",
+    "babel-preset-env": "^1.6.0",
+    "babel-preset-stage-0": "^6.16.0",
+    "css-loader": "^0.25.0",
+    "dotenv": "^2.0.0",
+    "ejs": "^2.5.2",
+    "ejs-html-loader": "^2.0.2",
+    "ejs-loader": "^0.3.0",
+    "eslint": "^3.4.0",
+    "exports-loader": "^0.6.2",
+    "expose-loader": "^0.7.1",
+    "express": "^4.13.4",
+    "extract-text-webpack-plugin": "^1.0.1",
+    "file-loader": "^0.9.0",
+    "html-loader": "^0.4.3",
+    "html-webpack-plugin": "^2.22.0",
+    "image-webpack-loader": "^3.0.0",
+    "imports-loader": "^0.6.5",
+    "jasmine-core": "^2.4.1",
+    "karma": "^1.1.2",
+    "karma-jasmine": "^1.0.2",
+    "karma-phantomjs-launcher": "^1.0.1",
+    "karma-sourcemap-loader": "^0.3.7",
+    "karma-webpack": "^1.8.0",
+    "less": "^2.6.1",
+    "less-loader": "^2.2.3",
+    "less-vars-to-js": "^1.1.2",
+    "phantomjs-prebuilt": "^2.1.11",
+    "postcss-loader": "^1.0.0",
+    "properties-reader": "0.0.15",
+    "proxy-middleware": "^0.15.0",
+    "raw-loader": "^0.5.1",
+    "resolve-url-loader": "^1.4.3",
+    "rimraf": "^2.5.3",
+    "style-loader": "^0.13.0",
+    "url": "^0.11.0",
+    "url-loader": "^0.5.7",
+    "webpack": "^1.12.12",
+    "webpack-dev-middleware": "^1.6.1",
+    "webpack-hot-middleware": "^2.10.0"
+  }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/location-manager/pom.xml
----------------------------------------------------------------------
diff --git a/new/ui-modules/location-manager/pom.xml b/new/ui-modules/location-manager/pom.xml
new file mode 100644
index 0000000..dd54a20
--- /dev/null
+++ b/new/ui-modules/location-manager/pom.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+         
+    <parent>
+        <artifactId>brooklyn-ui-modules-parent</artifactId>
+        <groupId>org.apache.brooklyn.ui.modules</groupId>
+        <version>${revision}</version>
+    </parent>
+    
+    <artifactId>brooklyn-ui-location-manager</artifactId>
+    <packaging>war</packaging>
+    <name>Brooklyn UI :: Modules - Location manager</name>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>dist</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>com.github.eirslett</groupId>
+                <artifactId>frontend-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <artifactId>maven-resources-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy-resources</id>
+                        <!-- here the phase you need -->
+                        <phase>compile</phase>
+                        <goals>
+                            <goal>copy-resources</goal>
+                        </goals>
+                        <configuration>
+                            <outputDirectory>
+                                ${project.build.directory}/${project.artifactId}-${project.version}
+                            </outputDirectory>
+                            <resources>
+                                <resource>
+                                    <directory>${project.basedir}/dist</directory>
+                                </resource>
+                            </resources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-war-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <!-- configure plugin to generate MANIFEST.MF
+                     adapted from http://blog.knowhowlab.org/2010/06/osgi-tutorial-from-project-structure-to.html -->
+                <executions>
+                    <execution>
+                        <id>bundle-manifest</id>
+                        <phase>process-classes</phase>
+                        <goals>
+                            <goal>manifest</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <supportedProjectTypes>
+                        <supportedProjectType>war</supportedProjectType>
+                        <supportedProjectType>jar</supportedProjectType>
+                        <supportedProjectType>bundle</supportedProjectType>
+                    </supportedProjectTypes>
+                    <instructions>
+                        <Bundle-ManifestVersion>${project.version}</Bundle-ManifestVersion>
+                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+                        <Import-Package>
+                            org.apache.brooklyn.ui.modularity.module.api,
+                            org.eclipse.jetty.servlets,
+                            *
+                        </Import-Package>
+                        <Export-Package>
+                            !*
+                        </Export-Package>
+                        <Web-ContextPath>/${project.artifactId}</Web-ContextPath>
+                        <_wab>app</_wab>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/location-manager/src/main/resources/ui-module/config.yaml
----------------------------------------------------------------------
diff --git a/new/ui-modules/location-manager/src/main/resources/ui-module/config.yaml b/new/ui-modules/location-manager/src/main/resources/ui-module/config.yaml
new file mode 100644
index 0000000..4add02c
--- /dev/null
+++ b/new/ui-modules/location-manager/src/main/resources/ui-module/config.yaml
@@ -0,0 +1,22 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+name: Location manager
+slug: ${project.artifactId}
+icon: fa-map-pin
+types:
+- home-ui-module
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/location-manager/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/new/ui-modules/location-manager/src/main/webapp/WEB-INF/web.xml b/new/ui-modules/location-manager/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..6b6683a
--- /dev/null
+++ b/new/ui-modules/location-manager/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,64 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<web-app version="2.4"
+         xmlns="http://java.sun.com/xml/ns/j2ee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
+                             http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+
+    <description>Brooklyn Location manager</description>
+    <display-name>Brooklyn Location manager</display-name>
+    <welcome-file-list>
+        <welcome-file>index.html</welcome-file>
+    </welcome-file-list>
+
+    <listener>
+        <listener-class>org.apache.brooklyn.ui.modularity.module.api.UiModuleListener</listener-class>
+    </listener>
+
+    <!--FILTERS :: START-->
+    <filter>
+        <filter-name>ui-module-filter</filter-name>
+        <filter-class>org.apache.brooklyn.ui.modularity.module.api.UiModuleFilter</filter-class>
+        <init-param>
+            <param-name>Cache-Control</param-name>
+            <param-value>public, max-age=604800</param-value><!--Cache static content for 1 week-->
+        </init-param>
+    </filter>
+    <filter>
+        <filter-name>GzipFilter</filter-name>
+        <filter-class>org.eclipse.jetty.servlets.GzipFilter</filter-class>
+        <init-param>
+            <param-name>mimeTypes</param-name>
+            <param-value>text/html,text/plain,text/xml,application/xhtml+xml,text/css,application/javascript,image/svg+xml</param-value>
+        </init-param>
+    </filter>
+
+    <filter-mapping>
+        <filter-name>ui-module-filter</filter-name>
+        <url-pattern>/*</url-pattern>
+    </filter-mapping>
+    <filter-mapping>
+        <filter-name>GzipFilter</filter-name>
+        <url-pattern>/*</url-pattern>
+    </filter-mapping>
+    <!--FILTERS :: END-->
+
+
+</web-app>

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/logout/.babelrc
----------------------------------------------------------------------
diff --git a/new/ui-modules/logout/.babelrc b/new/ui-modules/logout/.babelrc
new file mode 100644
index 0000000..222c2ba
--- /dev/null
+++ b/new/ui-modules/logout/.babelrc
@@ -0,0 +1,6 @@
+{
+  "presets": [
+    "env",
+    "stage-0"
+  ]
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/logout/.npmrc
----------------------------------------------------------------------
diff --git a/new/ui-modules/logout/.npmrc b/new/ui-modules/logout/.npmrc
new file mode 100644
index 0000000..c595d19
--- /dev/null
+++ b/new/ui-modules/logout/.npmrc
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+package-lock=false
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/logout/app/index.html
----------------------------------------------------------------------
diff --git a/new/ui-modules/logout/app/index.html b/new/ui-modules/logout/app/index.html
new file mode 100644
index 0000000..21854ca
--- /dev/null
+++ b/new/ui-modules/logout/app/index.html
@@ -0,0 +1,39 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<!doctype html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8"/>
+        <meta http-equiv="x-ua-compatible" content="ie=edge"/>
+        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"/>
+        <link rel="icon" type="image/png" href="${require('!!file-loader!<%= brand.product.favicon %>')}"/>
+        <title><%= getBrandedText('product.name' )%> - <%= app.appname %></title>
+    </head>
+    <body ng-app="app" ng-strict-di>
+    ${require('ejs-html!brooklyn-shared/partials/header-hero.html')}
+
+    <main class="page-main-area" id="main-content" ui-view ng-cloak></main>
+
+    ${require('ejs-html!brooklyn-shared/partials/footer.html')}
+
+    <br-interstitial-spinner event-count="1">
+        ${require('ejs-html!brooklyn-shared/partials/interstitial.html')}
+    </br-interstitial-spinner>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/logout/app/index.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/logout/app/index.js b/new/ui-modules/logout/app/index.js
new file mode 100644
index 0000000..09f6e4f
--- /dev/null
+++ b/new/ui-modules/logout/app/index.js
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import angular from 'angular';
+import ngAnimate from 'angular-animate';
+import ngCookies from 'angular-cookies';
+import uiRouter from 'angular-ui-router';
+
+import brCore from 'brooklyn-ui-utils/br-core/br-core';
+
+import brInterstitialSpinner from 'brooklyn-ui-utils/interstitial-spinner/interstitial-spinner';
+import brooklynModuleLinks from 'brooklyn-ui-utils/module-links/module-links';
+import brooklynUserManagement from 'brooklyn-ui-utils/user-management/user-management';
+
+import mainState from './views/main/main.controller';
+
+angular.module('app', [ngAnimate, ngCookies, uiRouter, brCore, brInterstitialSpinner, brooklynModuleLinks, brooklynUserManagement, mainState])
+    .config(['$urlRouterProvider', '$logProvider', applicationConfig])
+    .run(['$http', httpConfig]);
+
+function applicationConfig($urlRouterProvider, $logProvider) {
+    $logProvider.debugEnabled(false);
+    $urlRouterProvider.otherwise('/');
+}
+
+function httpConfig($http){
+    $http.defaults.headers.common['X-Csrf-Token-Required-For-Requests'] = 'write';
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/logout/app/index.less
----------------------------------------------------------------------
diff --git a/new/ui-modules/logout/app/index.less b/new/ui-modules/logout/app/index.less
new file mode 100644
index 0000000..5750772
--- /dev/null
+++ b/new/ui-modules/logout/app/index.less
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+@import '~brooklyn-shared/style/first.less';
+
+// Add project less files here
+
+
+// Load last so that these style rules and var values trump others
+@import "~brooklyn-shared/style/last.less";
+

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/logout/app/index.spec.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/logout/app/index.spec.js b/new/ui-modules/logout/app/index.spec.js
new file mode 100644
index 0000000..828bbf7
--- /dev/null
+++ b/new/ui-modules/logout/app/index.spec.js
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+describe('Logout module', () => {
+    it('has a dummy unit test', () => {
+        expect(true).toBeTruthy();
+    });
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/logout/app/views/main/main.controller.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/logout/app/views/main/main.controller.js b/new/ui-modules/logout/app/views/main/main.controller.js
new file mode 100644
index 0000000..8e554fb
--- /dev/null
+++ b/new/ui-modules/logout/app/views/main/main.controller.js
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import angular from 'angular';
+import uiRouter from 'angular-ui-router';
+import {HIDE_INTERSTITIAL_SPINNER_EVENT} from 'brooklyn-ui-utils/interstitial-spinner/interstitial-spinner';
+
+const MODULE_NAME = 'main.state';
+
+angular.module(MODULE_NAME, [uiRouter])
+    .config(['$stateProvider', mainStateConfig]);
+
+export default MODULE_NAME;
+
+export const mainState = {
+    name: 'main',
+    url: '/',
+    template: require('ejs-html!./main.template.html'),
+    controller: ['$scope', mainStateController],
+    controllerAs: 'vm'
+};
+
+export function mainStateConfig($stateProvider) {
+    $stateProvider.state(mainState);
+}
+
+export function mainStateController($scope) {
+    $scope.$emit(HIDE_INTERSTITIAL_SPINNER_EVENT);
+
+    let userRequest = new XMLHttpRequest();
+    userRequest.onreadystatechange = function () {
+        if (this.readyState === 4 && this.status === 200) {
+            logout(this.responseText)
+        }
+    };
+    userRequest.open('GET', '/v1/server/user', true);
+    userRequest.send('');
+
+    /**
+     * Logout the supplied user
+     * @param user
+     */
+    function logout(user) {
+        let ua = window.navigator.userAgent;
+        if (ua.indexOf('MSIE ') >= 0 || ua.indexOf(' Edge/') >= 0 || ua.indexOf(' Trident/') >= 0) {
+            document.execCommand('ClearAuthenticationCache', 'false');
+        }
+        let logoutRequest = new XMLHttpRequest();
+        logoutRequest.onreadystatechange = function () {
+            if (this.readyState === 4) {
+                if (this.status === 401) {
+                    console.info('User ' + user + ' logged out')
+                } else {
+                    setTimeout(function () {
+                        logout(user);
+                    }, 1000);
+                }
+            }
+        };
+        logoutRequest.open('POST', '/v1/logout', true, user, Math.random().toString(36).slice(2));
+        logoutRequest.send('');
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/logout/app/views/main/main.template.html
----------------------------------------------------------------------
diff --git a/new/ui-modules/logout/app/views/main/main.template.html b/new/ui-modules/logout/app/views/main/main.template.html
new file mode 100644
index 0000000..752ac93
--- /dev/null
+++ b/new/ui-modules/logout/app/views/main/main.template.html
@@ -0,0 +1,26 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<div class="container-fluid">
+    <div class="row">
+        <div class="col-md-12 text-center">
+            <h2>Thank you for using <%= getBrandedText('product.name') %>, see you soon</h2>
+            <p><a class="btn btn-lg btn-primary" href="/">Log back in</a></p>
+        </div>
+    </div>
+</div>

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/logout/config/build/webpack.config.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/logout/config/build/webpack.config.js b/new/ui-modules/logout/config/build/webpack.config.js
new file mode 100644
index 0000000..a050fa9
--- /dev/null
+++ b/new/ui-modules/logout/config/build/webpack.config.js
@@ -0,0 +1,19 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+eval(require('fs').readFileSync('../shared/config/build/webpack.config.js')+'');

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/logout/config/server.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/logout/config/server.js b/new/ui-modules/logout/config/server.js
new file mode 100644
index 0000000..dfba7dc
--- /dev/null
+++ b/new/ui-modules/logout/config/server.js
@@ -0,0 +1,19 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+eval(require('fs').readFileSync('../shared/config/server.js')+'');

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/logout/config/test/karma.config.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/logout/config/test/karma.config.js b/new/ui-modules/logout/config/test/karma.config.js
new file mode 100644
index 0000000..6fc6558
--- /dev/null
+++ b/new/ui-modules/logout/config/test/karma.config.js
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+const PRODUCTION_BUILD = process.env.NODE_ENV === 'production';
+const webpackConfig = require('./../build/webpack.config.js');
+
+module.exports = function (config) {
+    const conf = {
+        basePath: '',
+        frameworks: ['jasmine'],
+        files: [
+            {pattern: './karma.test.shim.js', watched: false}
+        ],
+        preprocessors: {
+            './karma.test.shim.js': ['webpack', 'sourcemap']
+        },
+        webpack: Object.assign({}, webpackConfig, {entry: undefined, plugins: undefined}),
+        webpackMiddleware: {
+            stats: 'errors-only'
+        },
+        webpackServer: {
+            noInfo: true
+        },
+        exclude: [],
+        colors: !PRODUCTION_BUILD,
+        logLevel: config.LOG_INFO,
+        autoWatch: !PRODUCTION_BUILD,
+        singleRun: PRODUCTION_BUILD,
+        reporters: ['progress'],
+        browsers: ['PhantomJS'],
+        plugins: [
+            require('karma-webpack'),
+            require('karma-sourcemap-loader'),
+            'karma-jasmine',
+            'karma-phantomjs-launcher'
+        ],
+        failOnEmptyTestSuite: false
+    };
+    config.set(conf);
+};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/logout/config/test/karma.test.shim.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/logout/config/test/karma.test.shim.js b/new/ui-modules/logout/config/test/karma.test.shim.js
new file mode 100644
index 0000000..3d926c0
--- /dev/null
+++ b/new/ui-modules/logout/config/test/karma.test.shim.js
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+Error.stackTraceLimit = Infinity;
+
+require('angular');
+require('angular-mocks');
+require('babel-polyfill');
+
+var testsContext = require.context('./../../app', true, /\.spec\.js$/);
+testsContext.keys().forEach(testsContext);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/logout/config/test/protractor.config.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/logout/config/test/protractor.config.js b/new/ui-modules/logout/config/test/protractor.config.js
new file mode 100644
index 0000000..5274c81
--- /dev/null
+++ b/new/ui-modules/logout/config/test/protractor.config.js
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+exports.config = {
+    framework: 'jasmine2',
+    seleniumAddress: 'http://localhost:4444/wd/hub',
+    specs: ['../../app/**/*.e2e-spec.js'],
+    baseUrl: 'http://admin:password@localhost:8080',
+    capabilities: {
+        'browserName': 'chrome',
+        'chromeOptions': {
+            'args': ['--window-size=1440,1000']
+        }
+    },
+    onPrepare: function () {
+        require('babel-register');
+    },
+    jasmineNodeOpts: {
+        // If true, print colors to the terminal.
+        showColors: true,
+        // Default time to wait in ms before a test fails.
+        defaultTimeoutInterval: 30000
+    }
+};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/logout/package.json
----------------------------------------------------------------------
diff --git a/new/ui-modules/logout/package.json b/new/ui-modules/logout/package.json
new file mode 100644
index 0000000..70cb03d
--- /dev/null
+++ b/new/ui-modules/logout/package.json
@@ -0,0 +1,94 @@
+{
+  "__license__": [
+    "Licensed to the Apache Software Foundation (ASF) under one",
+    "or more contributor license agreements.  See the NOTICE file",
+    "distributed with this work for additional information",
+    "regarding copyright ownership.  The ASF licenses this file",
+    "to you under the Apache License, Version 2.0 (the",
+    "\"License\"); you may not use this file except in compliance",
+    "with the License.  You may obtain a copy of the License at",
+    "    http://www.apache.org/licenses/LICENSE-2.0",
+    "Unless required by applicable law or agreed to in writing,",
+    "software distributed under the License is distributed on an",
+    "\"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY",
+    "KIND, either express or implied.  See the License for the",
+    "specific language governing permissions and limitations",
+    "under the License."
+  ],
+  "name": "brooklyn-ui-logout",
+  "versionBuildNote": "BROOKLYN_VERSION_BELOW this exists so scripts update this automatically",
+  "version": "1.0.0-SNAPSHOT",
+  "description": "Brooklyn UI :: Modules - Logout",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/apache/brooklyn-ui.git"
+  },
+  "author": "Apache Software Foundation",
+  "license": "Apache-2.0",
+  "scripts": {
+    "build": "rimraf dist && webpack --config ./config/build/webpack.config.js --bail",
+    "start": "node ./config/server.js",
+    "test": "karma start ./config/test/karma.config.js"
+  },
+  "engines": {
+    "node": ">=8.0.0",
+    "npm": ">=5.0.0"
+  },
+  "brooklyn": {
+    "appname": "Logout"
+  },
+  "dependencies": {
+    "brooklyn-ui-utils": "file:../utils",
+    "angular": "^1.6.1",
+    "angular-animate": "^1.6.1",
+    "angular-cookies": "^1.6.1",
+    "angular-ui-bootstrap": "^2.5.0",
+    "angular-ui-router": "^0.3.1",
+    "bootstrap": "^3.3.7",
+    "font-awesome": "^4.6.3"
+  },
+  "devDependencies": {
+    "autoprefixer": "^6.5.1",
+    "babel-core": "^6.17.0",
+    "babel-loader": "^6.2.5",
+    "babel-polyfill": "^6.20.0",
+    "babel-preset-env": "^1.6.0",
+    "babel-preset-stage-0": "^6.16.0",
+    "css-loader": "^0.25.0",
+    "dotenv": "^2.0.0",
+    "ejs": "^2.5.2",
+    "ejs-html-loader": "^2.0.2",
+    "ejs-loader": "^0.3.0",
+    "es6-promise": "^4.0.5",
+    "exports-loader": "^0.6.3",
+    "expose-loader": "^0.7.1",
+    "express": "^4.14.0",
+    "extract-text-webpack-plugin": "^1.0.1",
+    "file-loader": "^0.9.0",
+    "html-loader": "^0.4.4",
+    "html-webpack-plugin": "^2.22.0",
+    "image-webpack-loader": "^3.0.0",
+    "imports-loader": "^0.6.5",
+    "jasmine-core": "^2.5.2",
+    "karma": "^1.3.0",
+    "karma-jasmine": "^1.0.2",
+    "karma-phantomjs-launcher": "^1.0.2",
+    "karma-sourcemap-loader": "^0.3.7",
+    "karma-webpack": "^1.8.0",
+    "less": "^2.7.1",
+    "less-loader": "^2.2.3",
+    "less-vars-to-js": "^1.1.2",
+    "postcss-loader": "^1.0.0",
+    "properties-reader": "0.0.15",
+    "proxy-middleware": "^0.15.0",
+    "raw-loader": "^0.5.1",
+    "resolve-url-loader": "^1.6.0",
+    "rimraf": "^2.5.4",
+    "style-loader": "^0.13.1",
+    "url": "^0.11.0",
+    "url-loader": "^0.5.7",
+    "webpack": "^1.13.2",
+    "webpack-dev-middleware": "^1.8.4",
+    "webpack-hot-middleware": "^2.13.0"
+  }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/logout/pom.xml
----------------------------------------------------------------------
diff --git a/new/ui-modules/logout/pom.xml b/new/ui-modules/logout/pom.xml
new file mode 100644
index 0000000..98d50af
--- /dev/null
+++ b/new/ui-modules/logout/pom.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+         
+    <parent>
+        <artifactId>brooklyn-ui-modules-parent</artifactId>
+        <groupId>org.apache.brooklyn.ui.modules</groupId>
+        <version>${revision}</version>
+    </parent>
+    
+    <artifactId>brooklyn-ui-logout</artifactId>
+    <packaging>war</packaging>
+    <name>Brooklyn UI :: Modules - Logout</name>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>dist</directory>
+                            <followSymlinks>false</followSymlinks>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>com.github.eirslett</groupId>
+                <artifactId>frontend-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <artifactId>maven-resources-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy-resources</id>
+                        <!-- here the phase you need -->
+                        <phase>compile</phase>
+                        <goals>
+                            <goal>copy-resources</goal>
+                        </goals>
+                        <configuration>
+                            <outputDirectory>
+                                ${project.build.directory}/${project.artifactId}-${project.version}
+                            </outputDirectory>
+                            <resources>
+                                <resource>
+                                    <directory>${project.basedir}/dist</directory>
+                                </resource>
+                            </resources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-war-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <!-- configure plugin to generate MANIFEST.MF
+                     adapted from http://blog.knowhowlab.org/2010/06/osgi-tutorial-from-project-structure-to.html -->
+                <executions>
+                    <execution>
+                        <id>bundle-manifest</id>
+                        <phase>process-classes</phase>
+                        <goals>
+                            <goal>manifest</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <supportedProjectTypes>
+                        <supportedProjectType>war</supportedProjectType>
+                        <supportedProjectType>jar</supportedProjectType>
+                        <supportedProjectType>bundle</supportedProjectType>
+                    </supportedProjectTypes>
+                    <instructions>
+                        <Bundle-ManifestVersion>${project.version}</Bundle-ManifestVersion>
+                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+                        <Import-Package>
+                            org.apache.brooklyn.ui.modularity.module.api,
+                            org.eclipse.jetty.servlets,
+                            *
+                        </Import-Package>
+                        <Export-Package>
+                            !*
+                        </Export-Package>
+                        <Web-ContextPath>/${project.artifactId}</Web-ContextPath>
+                        <_wab>app</_wab>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/logout/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/new/ui-modules/logout/src/main/webapp/WEB-INF/web.xml b/new/ui-modules/logout/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..19970f8
--- /dev/null
+++ b/new/ui-modules/logout/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,30 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<web-app version="2.4"
+         xmlns="http://java.sun.com/xml/ns/j2ee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
+                             http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+
+    <description>Brooklyn Logout</description>
+    <display-name>Brooklyn Logout</display-name>
+    <welcome-file-list>
+        <welcome-file>index.html</welcome-file>
+    </welcome-file-list>
+</web-app>