Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WD-7718 - feat: Remove additional controllers feature #1676

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 0 additions & 25 deletions HACKING.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ contribute and what kinds of contributions are welcome.
- [Deploying a local app](#deploying-a-local-app)
- [Setting up cross model integrations](#setting-up-cross-model-integrations)
- [Getting models into a broken state](#getting-models-into-a-broken-state)
- [Adding additional controllers](#adding-additional-controllers)

## Setting up the dashboard for development

Expand Down Expand Up @@ -597,27 +596,3 @@ To get the model out of the broken state run:
```shell
juju exec --app nginx "status-set --application=True active"
```

### Adding additional controllers

To add additional controllers in the dashboard you'll need more than one controller. You might
like to [set up two controllers](#juju-controllers-in-multipass), each in their
own Multipass.

You might also like to add some models and deploy some applications on each controller.

Once you have your controllers set up, [configure your dashboard](#controller-configuration) to point to one
of the controllers.

At this point you should probably [accept the
certificates](#self-signed-certificates) for both controllers.

Load the dashboard and go to the controllers list (click Controllers in the
sidebar).

Now click the 'Register a controller' button. Fill in the form using the details
of the second controller (you can get the IP address of the controller using
`multipass list`) and then click 'Add Controller'.

The second controller should now be visible in the controller list and going to
the model list should display the models from both controllers.
65 changes: 17 additions & 48 deletions src/juju/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
} from "testing/factories/juju/ModelManagerV9";
import {
controllerFactory,
controllerInfoFactory,
modelListInfoFactory,
} from "testing/factories/juju/juju";
import { connectionInfoFactory } from "testing/factories/juju/jujulib";
Expand Down Expand Up @@ -722,12 +723,8 @@ describe("Juju API", () => {
jimM: {
listControllers: jest.fn().mockResolvedValueOnce({
controllers: [
{
"agent-version": "1.2.3",
name: "jaas1",
uuid: "abc123",
},
{ path: "admin/jaas2", uuid: "def456" },
controllerInfoFactory.build({ name: "jaas1" }),
controllerInfoFactory.build({ name: "jaas2" }),
],
}),
},
Expand All @@ -737,30 +734,21 @@ describe("Juju API", () => {
.spyOn(jujuLibVersions, "jujuUpdateAvailable")
.mockImplementationOnce(async () => true)
.mockImplementationOnce(async () => false);
await fetchControllerList(
"wss://example.com/api",
conn,
true,
dispatch,
() => rootStateFactory.build(),
await fetchControllerList("wss://example.com/api", conn, dispatch, () =>
rootStateFactory.build(),
);
expect(dispatch).toHaveBeenCalledWith(
jujuActions.updateControllerList({
wsControllerURL: "wss://example.com/api",
controllers: [
{
"agent-version": "1.2.3",
controllerInfoFactory.build({
name: "jaas1",
uuid: "abc123",
additionalController: true,
updateAvailable: true,
},
{
path: "admin/jaas2",
uuid: "def456",
additionalController: true,
}),
controllerInfoFactory.build({
name: "jaas2",
updateAvailable: false,
},
}),
],
}),
);
Expand All @@ -781,12 +769,8 @@ describe("Juju API", () => {
.spyOn(jujuLibVersions, "jujuUpdateAvailable")
.mockImplementationOnce(async () => true)
.mockImplementationOnce(async () => false);
await fetchControllerList(
"wss://example.com/api",
conn,
true,
dispatch,
() => rootStateFactory.build(),
await fetchControllerList("wss://example.com/api", conn, dispatch, () =>
rootStateFactory.build(),
);
expect(dispatch).toHaveBeenCalledWith(
jujuActions.updateControllerList({
Expand Down Expand Up @@ -825,7 +809,6 @@ describe("Juju API", () => {
await fetchControllerList(
"wss://example.com/api",
conn,
true,
dispatch,
() => state,
);
Expand All @@ -836,7 +819,6 @@ describe("Juju API", () => {
{
path: "admin/juju1",
uuid: "abc123",
additionalController: true,
updateAvailable: true,
version: "1.2.3",
},
Expand All @@ -851,38 +833,25 @@ describe("Juju API", () => {
facades: {
jimM: {
listControllers: jest.fn().mockResolvedValueOnce({
controllers: [
{
"agent-version": "1.2.3",
name: "jaas1",
uuid: "abc123",
},
],
controllers: [controllerInfoFactory.build({ name: "jaas1" })],
}),
},
},
} as unknown as Connection;
jest
.spyOn(jujuLibVersions, "jujuUpdateAvailable")
.mockImplementationOnce(async () => null);
await fetchControllerList(
"wss://example.com/api",
conn,
true,
dispatch,
() => rootStateFactory.build(),
await fetchControllerList("wss://example.com/api", conn, dispatch, () =>
rootStateFactory.build(),
);
expect(dispatch).toHaveBeenCalledWith(
jujuActions.updateControllerList({
wsControllerURL: "wss://example.com/api",
controllers: [
{
"agent-version": "1.2.3",
controllerInfoFactory.build({
name: "jaas1",
uuid: "abc123",
additionalController: true,
updateAvailable: false,
},
}),
],
}),
);
Expand Down
10 changes: 1 addition & 9 deletions src/juju/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -397,25 +397,18 @@ export async function fetchAllModelStatuses(
@param wsControllerURL The URL of the controller.
@param conn The Juju controller connection.
@param reduxStore The applications reduxStore.
@param additionalController If this is an additional controller.
*/
export async function fetchControllerList(
wsControllerURL: string,
conn: ConnectionWithFacades,
additionalController: boolean,
dispatch: Store["dispatch"],
getState: () => RootState,
) {
let controllers: JujuController[] | null = null;
if (conn.facades.jimM) {
try {
const response = await conn.facades.jimM?.listControllers();
controllers = response.controllers
? response.controllers.map((controller) => ({
...controller,
additionalController,
}))
: [];
controllers = response.controllers ?? [];
} catch (error) {
dispatch(
generalActions.storeConnectionError(
Expand All @@ -435,7 +428,6 @@ export async function fetchControllerList(
uuid: controllerConfig.config["controller-uuid"],
version: getControllerConnection(getState(), wsControllerURL)
?.serverVersion,
additionalController,
},
];
}
Expand Down
75 changes: 1 addition & 74 deletions src/pages/ControllersIndex/ControllersIndex.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import userEvent from "@testing-library/user-event";
import type { RootState } from "store/store";
import { generalStateFactory } from "testing/factories/general";
import {
additionalControllerFactory,
controllerFactory,
jujuStateFactory,
modelDataApplicationFactory,
Expand All @@ -18,7 +17,7 @@ import { connectionInfoFactory } from "testing/factories/juju/jujulib";
import { rootStateFactory } from "testing/factories/root";
import { renderComponent } from "testing/utils";

import ControllersIndex, { Label } from "./ControllersIndex";
import ControllersIndex from "./ControllersIndex";

describe("Controllers table", () => {
let state: RootState;
Expand All @@ -45,67 +44,6 @@ describe("Controllers table", () => {
expect(screen.getAllByRole("row")).toHaveLength(3);
});

it("displays additional controllers", () => {
state.general.controllerConnections = {
"wss://jimm.jujucharms.com/api": connectionInfoFactory.build({}),
};
state.juju = jujuStateFactory.build({
controllers: {
"wss://jimm.jujucharms.com/api": [
controllerFactory.build(),
additionalControllerFactory.build(),
],
},
});
renderComponent(<ControllersIndex />, { state });
const tables = screen.getAllByRole("grid");
expect(tables).toHaveLength(2);
const additionalRows = within(tables[1]).getAllByRole("row");
expect(additionalRows).toHaveLength(2);
expect(additionalRows[1]).toHaveTextContent(
[
"jimm.jujucharms.com",
"Connected",
"unknown/unknown",
"0",
"0",
"0",
"0",
].join(""),
);
});

it("displays additional controllers from JIMM", () => {
state.general.controllerConnections = {
"wss://jimm.jujucharms.com/api": connectionInfoFactory.build(),
};
state.juju = jujuStateFactory.build({
controllers: {
"wss://jimm.jujucharms.com/api": [
controllerFactory.build(),
controllerInfoFactory.build({ additionalController: true }),
],
},
});
renderComponent(<ControllersIndex />, { state });
const tables = screen.getAllByRole("grid");
expect(tables).toHaveLength(2);
const additionalRows = within(tables[1]).getAllByRole("row");
expect(additionalRows).toHaveLength(2);
expect(additionalRows[1]).toHaveTextContent(
[
"controller1",
"Connected",
"unknown/unknown",
"0",
"0",
"0",
"0",
"1.2.3",
].join(""),
);
});

it("counts models, machines, apps, and units", () => {
state.general.controllerConnections = {
"wss://jimm.jujucharms.com/api": connectionInfoFactory.build(),
Expand Down Expand Up @@ -193,17 +131,6 @@ describe("Controllers table", () => {
).toBeInTheDocument();
});

it("shows 'Register new controller' panel", async () => {
renderComponent(<ControllersIndex />, { url: "/controllers" });
await userEvent.click(
screen.getByRole("button", { name: Label.REGISTER_BUTTON }),
);
expect(window.location.search).toBe("?panel=register-controller");
expect(
document.querySelector(".p-panel.register-controller"),
).toBeInTheDocument();
});

it("Indicates if a controller has an update available", () => {
state.juju = jujuStateFactory.build({
controllers: {
Expand Down
Loading
Loading