diff --git a/app/app.js b/app/app.js index 62c5013aae..cc2fc4b6de 100644 --- a/app/app.js +++ b/app/app.js @@ -511,6 +511,14 @@ YUI.add('juju-gui', function(Y) { // Once the user logs in, we need to redraw. this.env.after('login', this.onLogin, this); + // Once we know about MAAS server, update the header accordingly. + var maasServer = this.env.get('maasServer'); + if (maasServer === undefined) { + this.env.once('maasServerChange', this._onMaasServer, this); + } else { + this._displayMaasLink(maasServer); + } + // Feed environment changes directly into the database. this.env.on('delta', this.db.onDelta, this.db); @@ -1215,6 +1223,34 @@ YUI.add('juju-gui', function(Y) { } }, + /** + If we are in a MAAS environment, react to the MAAS server address + retrieval adding a link to the header pointing to the MAAS server. + + @method _onMaasServer + @param {Object} evt An event object (with a "newVal" attribute). + */ + _onMaasServer: function(evt) { + this._displayMaasLink(evt.newVal); + }, + + /** + If the given maasServer is not null, create a link to the MAAS server + in the GUI header. + + @method _displayMaasLink + @param {String} maasServer The MAAS server URL (or null if not in MAAS). + */ + _displayMaasLink: function(maasServer) { + if (maasServer === null) { + // The current environment is not MAAS. + return; + } + var maasContainer = Y.one('#maas-server'); + maasContainer.one('a').set('href', maasServer); + maasContainer.show(); + }, + /** Hides the fullscreen mask and stops the spinner. diff --git a/app/index.html b/app/index.html index ad9472dd3c..2372bf87f1 100644 --- a/app/index.html +++ b/app/index.html @@ -161,6 +161,9 @@
  • +
  • Logout
  • diff --git a/app/store/env/fakebackend.js b/app/store/env/fakebackend.js index bf9c668055..a9232e2d10 100644 --- a/app/store/env/fakebackend.js +++ b/app/store/env/fakebackend.js @@ -47,13 +47,14 @@ YUI.add('juju-env-fakebackend', function(Y) { FakeBackend.NAME = 'fake-backend'; FakeBackend.ATTRS = { - authorizedUsers: {value: {'admin': 'password'}}, - token: {value: 'demoToken'}, authenticated: {value: false}, - store: {required: true}, + authorizedUsers: {value: {'admin': 'password'}}, defaultSeries: {value: 'precise'}, + name: {value: 'Environment'}, + maasServer: {value: null}, providerType: {value: 'demonstration'}, - name: {value: 'Environment'} + store: {required: true}, + token: {value: 'demoToken'} }; Y.extend(FakeBackend, Y.Base, { diff --git a/app/store/env/go.js b/app/store/env/go.js index 983782b495..c5b6cd2736 100644 --- a/app/store/env/go.js +++ b/app/store/env/go.js @@ -475,6 +475,10 @@ YUI.add('juju-env-go', function(Y) { // For now we only need to call environmentGet if the provider is MAAS. if (response.ProviderType === 'maas') { this.environmentGet(); + } else { + // Set the MAAS server to null, so that subscribers waiting for this + // attribute to be set can be released. + this.set('maasServer', null); } } }, diff --git a/app/store/env/sandbox.js b/app/store/env/sandbox.js index 80f6d240a7..c45059d8c8 100644 --- a/app/store/env/sandbox.js +++ b/app/store/env/sandbox.js @@ -846,7 +846,7 @@ YUI.add('juju-env-sandbox', function(Y) { }, /** - Handle EnvironmentView messages. + Handle EnvironmentInfo messages. @method handleClientEnvironmentInfo @param {Object} data The contents of the API arguments. @@ -865,6 +865,24 @@ YUI.add('juju-env-sandbox', function(Y) { }); }, + /** + Handle EnvironmentGet messages. + + @method handleClientEnvironmentGet + @param {Object} data The contents of the API arguments. + @param {Object} client The active ClientConnection. + @param {Object} state An instance of FakeBackend. + */ + handleClientEnvironmentGet: function(data, client, state) { + client.receive({ + RequestId: data.RequestId, + Response: { + // For now only the MAAS server is required by the GUI. + Config: {'maas-server': state.get('maasServer')} + } + }); + }, + /** A white-list for model attributes. This translates them from the raw ATTRS to the format expected by the environment's delta handling. diff --git a/test/test_app.js b/test/test_app.js index e778b1eb75..3395e6bf5c 100644 --- a/test/test_app.js +++ b/test/test_app.js @@ -347,6 +347,77 @@ function injectData(app, data) { done(); }); }); + + describe('MAAS support', function() { + var env, maasNode; + + beforeEach(function() { + // Set up the MAAS link node. + maasNode = Y.Node.create( + ''); + container.appendChild(maasNode); + // Create the environment. + env = new juju.environments.GoEnvironment({ + conn: new utils.SocketStub(), + ecs: new juju.EnvironmentChangeSet() + }); + }); + + // Ensure the given MAAS node is shown and includes a link to the given + // address. + var assertMaasLinkExists = function(node, address) { + assert.strictEqual(node.getStyle('display'), 'block'); + assert.strictEqual(node.one('a').get('href'), address); + }; + + it('shows a link to the MAAS server if provider is MAAS', function() { + constructAppInstance({env: env}); + // The MAAS node is initially hidden. + assert.strictEqual(maasNode.getStyle('display'), 'none'); + env.set('maasServer', 'http://1.2.3.4/MAAS'); + // Once the MAAS server becomes available, the node is activated and + // includes a link to the server. + assertMaasLinkExists(maasNode, 'http://1.2.3.4/MAAS'); + // Further changes to the maasServer attribute don't change the link. + env.set('maasServer', 'http://example.com/MAAS'); + assertMaasLinkExists(maasNode, 'http://1.2.3.4/MAAS'); + }); + + it('shows a link to the MAAS server if already in the env', function() { + env.set('maasServer', 'http://1.2.3.4/MAAS'); + constructAppInstance({env: env}); + // The link to the MAAS server should be already activated. + assertMaasLinkExists(maasNode, 'http://1.2.3.4/MAAS'); + // Further changes to the maasServer attribute don't change the link. + env.set('maasServer', 'http://example.com/MAAS'); + assertMaasLinkExists(maasNode, 'http://1.2.3.4/MAAS'); + }); + + it('does not show the MAAS link if provider is not MAAS', function() { + constructAppInstance({env: env}); + // The MAAS node is initially hidden. + assert.strictEqual(maasNode.getStyle('display'), 'none'); + env.set('maasServer', null); + // The MAAS node is still hidden. + assert.strictEqual(maasNode.getStyle('display'), 'none'); + // Further changes to the maasServer attribute don't activate the link. + env.set('maasServer', 'http://1.2.3.4/MAAS'); + assert.strictEqual(maasNode.getStyle('display'), 'none'); + }); + + it('does not show the MAAS link if already null in the env', function() { + env.set('maasServer', null); + constructAppInstance({env: env}); + assert.strictEqual(maasNode.getStyle('display'), 'none'); + // Further changes to the maasServer attribute don't activate the link. + env.set('maasServer', 'http://1.2.3.4/MAAS'); + assert.strictEqual(maasNode.getStyle('display'), 'none'); + }); + + }); + }); })(); diff --git a/test/test_app_hotkeys.js b/test/test_app_hotkeys.js index 4c294a5e0f..6f1f4a3a42 100644 --- a/test/test_app_hotkeys.js +++ b/test/test_app_hotkeys.js @@ -28,6 +28,7 @@ describe('application hotkeys', function() { after: function() {}, get: function() {}, on: function() {}, + once: function() {}, set: function() {} }; windowNode = Y.one(window); diff --git a/test/test_env_go.js b/test/test_env_go.js index 5f000e7d54..4011758667 100644 --- a/test/test_env_go.js +++ b/test/test_env_go.js @@ -507,6 +507,8 @@ with this program. If not, see . }); it('does not call EnvironmentGet after Info when not on MAAS', function() { + // The MAAS server attribute is initially undefined. + assert.isUndefined(env.get('maasServer')); // Simulate an EnvironmentInfo request/response. env.environmentInfo(); conn.msg({ @@ -518,6 +520,8 @@ with this program. If not, see . } }); assert.lengthOf(conn.messages, 1); + // The MAAS server attribute has been set to null. + assert.isNull(env.get('maasServer')); }); it('sends the correct AddServiceUnits message', function() { diff --git a/test/test_sandbox_go.js b/test/test_sandbox_go.js index 55d63a3541..48f3b241c6 100644 --- a/test/test_sandbox_go.js +++ b/test/test_sandbox_go.js @@ -245,6 +245,26 @@ with this program. If not, see . client.send(Y.JSON.stringify(data)); }); + it('returns EnvironmentGet responses', function(done) { + var data = { + RequestId: 42, + Type: 'Client', + Request: 'EnvironmentGet' + }; + client.onmessage = function(received) { + var expected = { + RequestId: 42, + Response: { + Config: {'maas-server': state.get('maasServer')} + } + }; + assert.deepEqual(Y.JSON.parse(received.data), expected); + done(); + }; + client.open(); + client.send(Y.JSON.stringify(data)); + }); + it('can start the AllWatcher', function(done) { var data = { Type: 'Client',