Skip to content

Commit 776534a

Browse files
authored
Merge pull request #432 from dappnode/remove-external-vols
Remove external vols
2 parents 70e26ac + b1395a9 commit 776534a

File tree

24 files changed

+377
-864
lines changed

24 files changed

+377
-864
lines changed

packages/admin-ui/server-mock/data/sample.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,6 @@ export const sampleDnp: InstalledPackageDetailData = {
7676
gettingStarted: "",
7777
gettingStartedShow: true,
7878
areThereVolumesToRemove: false,
79-
volumeUsersToRemove: [],
8079
dependantsOf: [],
81-
namedExternalVols: [],
8280
containers: []
8381
};

packages/admin-ui/src/common/types.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -429,13 +429,7 @@ export interface InstalledPackageDetailData extends InstalledPackageData {
429429
* Checks if there are volumes to be removed on this DNP
430430
*/
431431
areThereVolumesToRemove: boolean;
432-
/**
433-
* If there are volumes which this DNP is the owner and some other
434-
* DNPs are users, they will be removed by the DAPPMANAGER.
435-
*/
436-
volumeUsersToRemove: string[];
437432
dependantsOf: string[];
438-
namedExternalVols: VolumeOwnershipData[];
439433
// Non-indexed data
440434
manifest?: Manifest;
441435
}
@@ -455,7 +449,6 @@ interface ManifestImage {
455449
size: number;
456450
path: string;
457451
volumes?: string[];
458-
external_vol?: string[];
459452
ports?: string[];
460453
environment?: string[];
461454
restart?: string;
@@ -482,8 +475,8 @@ export interface ManifestWithImage extends Manifest {
482475
export interface ComposeVolumes {
483476
// volumeName: "dncore_ipfsdnpdappnodeeth_data"
484477
[volumeName: string]: {
485-
// Allowed to user
486-
external?: boolean | { name: string }; // name: "dncore_ipfsdnpdappnodeeth_data"
478+
// FORBIDDEN
479+
// external?: boolean | { name: string }; // name: "dncore_ipfsdnpdappnodeeth_data"
487480
// NOT allowed to user, only used by DAppNode internally (if any)
488481
name?: string; // Volumes can only be declared locally or be external
489482
driver?: string; // Dangerous
@@ -917,7 +910,6 @@ export interface PackageReleaseImageData {
917910
ports?: string[];
918911
environment?: string[];
919912
// Non-mergable properties
920-
external_vol?: string[];
921913
restart?: string;
922914
privileged?: boolean;
923915
cap_add?: string[];
@@ -944,7 +936,6 @@ export interface MountpointData {
944936
export interface VolumeOwnershipData {
945937
name: string; // "gethdnpdappnodeeth_geth", Actual name to call delete on
946938
owner?: string; // "geth.dnp.dappnode.eth", Actual name of the owner
947-
users: string[]; // ["geth.dnp.dappnode.eth", "dependency.dnp.dappnode.eth"]
948939
}
949940

950941
export interface VolumeData extends VolumeOwnershipData {

packages/admin-ui/src/pages/packages/components/Info/RemovePackage.tsx

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,7 @@ interface WarningItem {
1919
}
2020

2121
export function RemovePackage({ dnp }: { dnp: InstalledPackageDetailData }) {
22-
const {
23-
dnpName,
24-
areThereVolumesToRemove,
25-
volumeUsersToRemove,
26-
dependantsOf,
27-
isCore
28-
} = dnp;
22+
const { dnpName, areThereVolumesToRemove, dependantsOf, isCore } = dnp;
2923

3024
const history = useHistory();
3125

@@ -60,15 +54,6 @@ export function RemovePackage({ dnp }: { dnp: InstalledPackageDetailData }) {
6054
});
6155
}
6256

63-
// dnpsToRemove = "raiden.dnp.dappnode.eth, another.dnp.dappnode.eth"
64-
if (volumeUsersToRemove.length > 0) {
65-
const volumeUsersToRemoveList = markdownList(volumeUsersToRemove);
66-
dnpsToRemoveWarningsList.push({
67-
title: "Warning! Other packages to be removed",
68-
body: `Some other DAppNode Packages will be removed as well because they are dependent on ${dnpName} volumes. \n\n ${volumeUsersToRemoveList}`
69-
});
70-
}
71-
7257
if (dnpsToRemoveWarningsList.length > 0)
7358
await new Promise(resolve =>
7459
confirm({

packages/admin-ui/src/pages/packages/components/Info/VolumesList.tsx

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
prettyBytes,
1313
shortNameCapitalized as sn
1414
} from "utils/format";
15-
import { markdownList } from "utils/markdown";
1615
import { InstalledPackageDetailData } from "common";
1716
import "./volumesList.scss";
1817

@@ -24,24 +23,11 @@ interface WarningItem {
2423
export const VolumesList = ({ dnp }: { dnp: InstalledPackageDetailData }) => {
2524
const [showAll, setShowAll] = useState(false);
2625

27-
const { dnpName, volumeUsersToRemove } = dnp;
26+
const { dnpName } = dnp;
2827

2928
async function packageRestartVolumes(volumeName?: string) {
3029
const warningsList: WarningItem[] = [];
3130

32-
/**
33-
* If there are volumes which this DNP is the owner and some other
34-
* DNPs are users, they will be removed by the DAPPMANAGER.
35-
* Alert the user about this fact
36-
*/
37-
if (volumeUsersToRemove.length > 0) {
38-
const volumeUsersToRemoveList = markdownList(volumeUsersToRemove);
39-
warningsList.push({
40-
title: "Warning! DAppNode Packages to be removed",
41-
body: `Some other DAppNode Packages will be reseted in order to remove ${dnpName} volumes. \n\n ${volumeUsersToRemoveList}`
42-
});
43-
}
44-
4531
// If there are NOT conflicting volumes,
4632
// Display a dialog to confirm volumes reset
4733
await new Promise(resolve =>

packages/admin-ui/src/pages/system/actions.ts

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,10 @@ import { getEthClientPrettyName } from "components/EthMultiClient";
55
// External actions
66
import { fetchPasswordIsSecure } from "services/dappnodeStatus/actions";
77
// Selectors
8-
import { getDnpInstalledByDnpName } from "services/dnpInstalled/selectors";
9-
import {
10-
getEthClientTarget,
11-
getVolumes
12-
} from "services/dappnodeStatus/selectors";
8+
import { getEthClientTarget } from "services/dappnodeStatus/selectors";
139
import { EthClientTarget } from "types";
1410
import { withToastNoThrow } from "components/toast/Toast";
1511
import { AppThunk } from "store";
16-
import { markdownList } from "utils/markdown";
1712

1813
// Redux Thunk actions
1914

@@ -108,33 +103,13 @@ export const volumeRemove = (name: string): AppThunk => async dispatch => {
108103
export const packageVolumeRemove = (
109104
dnpName: string,
110105
volName: string
111-
): AppThunk => async (dispatch, getState) => {
106+
): AppThunk => async () => {
112107
// Make sure there are no colliding volumes with this DNP
113-
const dnp = getDnpInstalledByDnpName(getState(), dnpName);
114-
const volumesData = getVolumes(getState());
115108
const prettyDnpName = shortNameCapitalized(dnpName);
116109
const prettyVolName = prettyVolumeName(volName, dnpName).name;
117110
const prettyVolRef = `${prettyDnpName} ${prettyVolName} volume`;
118111

119112
const warningsList: { title: string; body: string }[] = [];
120-
/**
121-
* If there are volumes which this DNP is the owner and some other
122-
* DNPs are users, they will be removed by the DAPPMANAGER.
123-
* Alert the user about this fact
124-
*/
125-
if (dnp) {
126-
const vol = volumesData.find(v => v.name === volName);
127-
if (vol && vol.users) {
128-
const externalUsers = vol.users.filter(d => d !== dnpName);
129-
if (externalUsers.length > 0) {
130-
const externalUsersList = markdownList(externalUsers);
131-
warningsList.push({
132-
title: "Warning! DAppNode Packages to be removed",
133-
body: `Some other DAppNode Packages will be reseted in order to remove ${prettyVolRef}. \n\n ${externalUsersList}`
134-
});
135-
}
136-
}
137-
}
138113

139114
// If there are NOT conflicting volumes,
140115
// Display a dialog to confirm volumes reset

packages/admin-ui/src/services/dnpInstalled/selectors.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,3 @@ import { InstalledPackageData } from "types";
55

66
export const getDnpInstalled = (state: RootState): InstalledPackageData[] =>
77
state.dnpInstalled.dnpInstalled;
8-
9-
/**
10-
* Regular selectors, called outside of a normal react-redux situation
11-
*/
12-
13-
export const getDnpInstalledByDnpName = (state: RootState, dnpName: string) =>
14-
getDnpInstalled(state).find(dnp => dnp.dnpName === dnpName);

packages/dappmanager/src/calls/packageGet.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { InstalledPackageDetailData } from "../types";
66
import { logs } from "../logs";
77
import { ComposeFileEditor } from "../modules/compose/editor";
88
import { getVolumesOwnershipData } from "../modules/docker/volumesData";
9-
import { getDnpsToRemoveAll } from "../modules/docker/restartPackageVolumes";
109

1110
/**
1211
* Toggles the visibility of a getting started block
@@ -24,9 +23,6 @@ export async function packageGet({
2423
if (!dnp) throw Error(`No DNP was found for name ${dnpName}`);
2524
const volumesData = await getVolumesOwnershipData();
2625

27-
// Metadata for package/:id/controls feedback
28-
const { dnpsToRemove } = getDnpsToRemoveAll(dnp, volumesData);
29-
3026
const dnpData: InstalledPackageDetailData = {
3127
...dnp,
3228

@@ -38,13 +34,9 @@ export async function packageGet({
3834
return !owner || owner === dnp.dnpName;
3935
})
4036
),
41-
volumeUsersToRemove: dnpsToRemove.filter(name => name !== dnp.dnpName),
4237
dependantsOf: dnpList
4338
.filter(d => d.dependencies[dnpName])
44-
.map(d => d.dnpName),
45-
namedExternalVols: volumesData.filter(
46-
v => v.owner && v.owner !== dnp.dnpName && v.users.includes(dnp.dnpName)
47-
)
39+
.map(d => d.dnpName)
4840
};
4941

5042
// Add non-blocking data
Lines changed: 28 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import fs from "fs";
22
import * as eventBus from "../eventBus";
33
import params from "../params";
4-
// Modules
5-
import { dockerComposeDown, dockerRm } from "../modules/docker/dockerCommands";
6-
// Utils
4+
import {
5+
dockerComposeDown,
6+
dockerRm,
7+
dockerStop
8+
} from "../modules/docker/dockerCommands";
79
import * as getPath from "../utils/getPath";
810
import shell from "../utils/shell";
911
import { listPackage } from "../modules/docker/listContainers";
10-
import { restartPackageVolumes } from "../modules/docker/restartPackageVolumes";
1112
import { logs } from "../logs";
1213

1314
/**
@@ -33,54 +34,39 @@ export async function packageRemove({
3334
throw Error("Core packages cannot be cannot be removed");
3435
}
3536

36-
// Only no-cores will
37+
// Only no-cores reach this block
3738
const composePath = getPath.dockerCompose(dnp.dnpName, false);
3839
const packageRepoDir = getPath.packageRepoDir(dnp.dnpName, false);
3940

40-
// Necessary for eventBus dependants to know the exact list of deleted DNPs
41-
let removedDnps: string[] = [dnp.dnpName];
41+
// [NOTE] Not necessary to close the ports since they will just
42+
// not be renewed in the next interval
4243

43-
/**
44-
* [NOTE] Not necessary to close the ports since they will just
45-
* not be renewed in the next interval
46-
*/
47-
48-
// Call restartPackageVolumes to safely delete dependant volumes
49-
if (deleteVolumes) {
50-
// Note: restartPackageVolumes may remove additional DNPs
51-
removedDnps = (
52-
await restartPackageVolumes({
53-
dnpName: dnp.dnpName,
54-
doNotRestart: true
55-
})
56-
).removedDnps;
57-
} else {
58-
/**
59-
* If there is no docker-compose, do a docker rm directly
60-
* Otherwise, try to do a docker-compose down and if it fails,
61-
* log to console and do docker-rm
62-
*/
63-
if (fs.existsSync(composePath))
64-
try {
65-
await dockerComposeDown(composePath, {
66-
volumes: deleteVolumes,
67-
timeout
68-
});
69-
} catch (e) {
70-
logs.error(`Error on dockerComposeDown of ${dnp.dnpName}`, e);
71-
for (const container of dnp.containers)
72-
await dockerRm(container.containerName, { volumes: deleteVolumes });
73-
}
74-
else {
75-
for (const container of dnp.containers)
76-
await dockerRm(container.containerName, { volumes: deleteVolumes });
44+
// If there is no docker-compose, do a docker rm directly
45+
// Otherwise, try to do a docker-compose down and if it fails,
46+
// log to console and do docker-rm
47+
let hasRemoved = false;
48+
if (fs.existsSync(composePath)) {
49+
try {
50+
await dockerComposeDown(composePath, {
51+
volumes: deleteVolumes,
52+
timeout
53+
});
54+
hasRemoved = true; // To mimic an early return
55+
} catch (e) {
56+
logs.error(`Error on dockerComposeDown of ${dnp.dnpName}`, e);
7757
}
7858
}
7959

60+
if (!hasRemoved) {
61+
const containerNames = dnp.containers.map(c => c.containerName);
62+
await dockerStop(containerNames, { time: timeout });
63+
await dockerRm(containerNames, { volumes: deleteVolumes });
64+
}
65+
8066
// Remove DNP folder and files
8167
if (fs.existsSync(packageRepoDir)) await shell(`rm -r ${packageRepoDir}`);
8268

8369
// Emit packages update
8470
eventBus.requestPackages.emit();
85-
eventBus.packagesModified.emit({ dnpNames: removedDnps, removed: true });
71+
eventBus.packagesModified.emit({ dnpNames: [dnp.dnpName], removed: true });
8672
}

0 commit comments

Comments
 (0)