The dashboard to monitor your Juju & JAAS environments.
Starting with Juju 2.8 this dashboard is installed by default with every bootstrap. To access it simply run juju dashboard
and visit the link provided and log in using the supplied credentials. It's also available and automatically updated for users of JAAS on jaas.ai.
- Using the Dashboard with Juju
- QA'ing the Dashboard
- Developing the Dashboard
- Releasing the Dashboard
Below are the commands you can use to interact with the dashboard from Juju 2.8+
usage: juju <command>
command | description |
---|---|
dashboard | Outputs the Juju Dashboard URL, username and password. The password will only be shown if you haven't changed it from its default. |
upgrade-dashboard | Upgrade to a new released Juju Dashboard version. A file path to a tarball can be provided to switch to a custom version. |
see juju help <command>
for detailed option output.
The Juju Dashboard is run in a number of different environments that distill down to two different backends, Juju and JAAS. A thorough QA will test the new features in both environments.
For both environments you'll want to pull down the code locally from the appropriate pull request.
git clone [email protected]:canonical-web-and-design/jaas-dashboard.git
git checkout -b branch-name-for-the-pr master
git pull git://github.com/<pr creators username>/jaas-dashboard.git <pull request branch name>
This is the preferred approach as it's served by Juju itself which is also generating the configuration files so it's the closest to a production environment.
./run exec yarn run generate-release-tarball
juju upgrade-dashboard juju-dashboard-<version>.tar.bz2
juju dashboard
And connect to the Dashboard from your browser using the supplied details.
If you'd like to run the Dashboard locally and connect to a remote controller see Developing while connected to a Juju controller
The default configuration setting for the Dashboard is to connect to public JAAS so you can simply:
./run
Then connect to the Dashboard from your browser at http://localhost:8036/.
- Can you log in?
- Does the model list show your available models?
- Are your models correctly grouped by status?
- Are your models correctly grouped by owner?
- Are your models correctly grouped by cloud?
- Can you filter the tables?
- Can you view the controllers list?
- Is the controllers list hidden if you do not have permission to view it?
- Are your model details accurate?
- Can you hide and show tables in the model details?
- Is the Topology rendered correctly?
- Chaos monkey, did anything break?
- General observations, was there anything that needs improvement?
Assuming you already have Docker installed, you can simply run;
./run
...and view the site locally at: http://localhost:8036/. Any changes you make to the code will be automatically recompiled and reloaded in the browser.
Assuming you already have a Juju controller created you will need to connect to the existing controller and accept the self-signed certificate. Without this step your local dashboard will not be permitted to complete the required secure websocket connection to the controller.
- Run
juju dashboard
and view the Dashboard using the supplied url.- Accept the self-signed cert
- Open
config.js
and modify the following values:baseControllerURL
should be output from thejuju dashboard
call above with the port17070
.identityProviderAvailable
tofalse
.isJuju
totrue
.
- Start the Dashboard with
./run
. - You can now access the dashboard at http://localhost:8036/ and it'll require the log in credentials from the above
juju dashboard
command.
./run test
When you want to access a dashboard that was automatically installed with a juju bootstrap
within an lxd in a multipass
vm from the host.
- Create a ssh tunnel
- In the host
multipass info <vm name> | grep IPv4
and take note of the IP address.- In your browser visit
http://<that ip>:17070
- Log in using the credentials provided from the
juju dashboard
command.
When you have a Juju controller bootstrapped in an lxd within a multipass
vm and a dashboard being hosted from the same multipass
vm but accessed from the host.
- Create a ssh tunnel
- In the host
multipass info dev | grep IPv4
and take note of the IP address.- Open
config.js
and modify the following values:baseControllerURL
should be output from themultipass info
call above with the port17070
.identityProviderAvailable
tofalse
.isJuju
totrue
.
If you're bootstrapping a Juju controller within a multipass
VM you will not have access to the dashboard from the host because there is no network path to it. To create a tunnel to access the dashboard follow these steps.
- After bootstrapping a controller on
lxd
in yourmultipass
VM... - In the multipass vm
juju switch controller && juju ssh 0
- In the lxd container
ssh-import-id <your launchpad name>
- In the multipass vm
juju dashboard
and take note of the ip:portssh -fN -L *:17070:0:17070 [email protected]
Where the "10." ip is replaced with the ip from the output of thejuju dashboard
command.
The Juju Dashboard uses Vanilla CSS and Vanilla React Components. Be sure to check there first for any components before writing your own.
- Components are stored in their own self-named folders using the TitleCase format.
- Tests and Sass files are stored along side each component with the naming convention of
ComponentName.css
andComponentName.test.js
respectively. - Sub components are nested within subfolders of their parent components if they are not shared among other components.
- Use functional components.
- Use hooks.
- Consider contributing generic components back to Vanilla CSS and Vanilla React Components where appropriate.
- Components can be as big as they need to be, don't split them up into micro components.
- Components either accept props or interact with the redux store via selectors, do not access data sources directly.
We follow the Testing your user contract system of writing tests.
The consumer expects that when they perform action X, they receive outcome Y. Typically they are not concerned about how X became Y just that it does so reliably.
This effectively means that we write integration and component tests, not unit tests.
- The test files are kept along side the library or component file following the naming convention
<component|filename>.test.js
. - We limit the use of snapshots except for where the snapshot updates can be easily verified by a reviewer.
- Add assertions for the explicit content you're expecting. This allows changes to things that may not be relevant to the test like classNames, attributes, etc.
- When searching for an element, use element selectors where possible and add a data attribute when not. We follow the format of
data-test="..."
ordata-test-<specifier>="..."
e.g.<a data-test-column="priority">High</a>
. - Test labels should be specific and representative of the test content. Create additional tests if you need assertions that do not apply to the label.
- Do not mock components unless absolutely necessary. The data dump mentioned below should contain sufficient data to render the full component tree in the test.
The file complete-redux-store-dump.js contains a sanitized redux dump from a Dashboard instance with many models in different states. When writing a test use the real data provided by this file when generating a redux store that will provide the data to your component or library. Because every test uses the same dataset this allows us to see when a library or component will fail if the data that's saved to the redux store, or a selector is modified.
If you modify the data that is saved into the redux store then you must update this file
If you want to test states that are not included in the data dump, or if you want to see how a component will act in different data states you can modify it locally within the test. If you must modify some value see if there is value in adding another entry into the dataset for others to use.
The typical import and test case setup looks like the following. Note that we create a shared mockStore
factory at the top of each test suite.
import React from "react";
import { MemoryRouter } from "react-router";
import { mount } from "enzyme";
import { Provider } from "react-redux";
import configureStore from "redux-mock-store";
import dataDump from "../../testing/complete-redux-store-dump";
const mockStore = configureStore([]);
describe("ComponentName", () => {
it('', () => {
// test case
});
//... more tests
});
Setting up a typical component test involves creating a mock store and passing that to the Provider so that any component you're testing can still use its built-in redux selectors.
const store = mockStore(dataDump);
const wrapper = mount(
<MemoryRouter>
<Provider store={store}>
<StatusGroup />
</Provider>
</MemoryRouter>
);
If you need to modify the data used in the application, clone the data dump in each test so that you do not run the risk of overriding data in subsequent tests. You should only update the values directly.
const clonedData = cloneDeep(dataDump);
clonedData.root.appVersion = "0.1.8";
const store = mockStore(clonedData);
const wrapper = mount(
<MemoryRouter>
<Provider store={store}>
<StatusGroup />
</Provider>
</MemoryRouter>
);
We have a special component for routing to be used with testing. It ensures that the routes that are used in the test are valid within the application by comparing them to the real routes.
const wrapper = mount(
<Provider store={store}>
<MemoryRouter initialEntries={["/models/group-test"]}>
<TestRoute path="/models/*">
<InfoPanel />
</TestRoute>
</MemoryRouter>
</Provider>
);
To complete QA and release the Dashboard will take aproximately 2h of total time, 1h of which is an automated process at the end.
- Release prep
- Generate a release tarball for Juju
- Release to jaas.ai
- Release to Juju Simplestreams
- Create an announcement on the Juju Discourse
To prepare to release:
- Clone a new copy of the repository to remove the chance of any uncommitted artifacts ending up in the release.
- Thoroughly QA the Dashboard following the Release tests
- Update the changelog by adding the important commits from the last tag.
git log `git describe --tags --abbrev=0`..HEAD --format='- %b' --merges | sed '/^- $/d'
- Bump the version of the
package.json
file to the next appropriate semver version. - Commit the changes
- Tag that commit with the appropriate version number.
The version of the Dashboard that's installed with every new Juju bootstrap is generated using:
./run exec yarn run generate-release-tarball
- Take this tarball and create a new release on GitHub under the appropriate version tag.
- Add the notes from the changelog to the release notes on GitHub.
The release to jaas.ai is in two steps. New releases of the jaas.ai website will pull in the latest release of the Dashboard for JAAS.
- Trigger the Staging CI job to release a new version of jaas.ai to staging.
- Validate that the website works as expected and that the release tests are pass successfully.
- Trigger the Production CI job to perform the release to jaas.ai production.
- Validate that the website works as expected and that the release tests are pass successfully.
When Juju bootstraps a new instance it fetches the appropriate content for the infrastructure it's deployed on from a system called Simplestreams.
To release a tarball of the Dashboard to Simplestreams:
- Clone the release script Shipit.
- Follow the instructions in that projects
README.md
to perform the release. This will take aproximately an hour but it's automated. You'll want to keep an eye on it as it's doing its thing in the event it needs input.
Create a new post in the News category on the Juju Discourse outlining what new features and fixes were included as well as what we're planning on including in upcoming releases.