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

feat: node updates (must manually check for updates) #613

Merged
merged 14 commits into from
Jul 10, 2024
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
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,8 @@
"test/**/__snapshots__": true,
"package-lock.json": true,
"*.{css,sass,scss}.d.ts": true
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
}
}
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ SENTRY_DSN=fake-token
MP_PROJECT_TOKEN=fake-token
MP_PROJECT_ENV=dev
NICENODE_ENV=development
CONTROLLER_API_URL=http://localhost:3000/api
```

`SENTRY_DSN` and `MP_PROJECT_TOKEN` should be fake unless testing. Contact Johns, @jgresham, if you want to test new error or event reporting code.
Expand Down
6 changes: 6 additions & 0 deletions assets/locales/en/genericComponents.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"AboutSecondsRemaining": "About {{seconds}} seconds remaining",
"CheckForUpdates": "Check for updates...",
"Confirm": "Confirm",
"FinishingUp": "Finishing up...",
"Hide": "Hide",
Expand Down Expand Up @@ -55,6 +56,7 @@
"PodmanIsNotRunning": "Podman is not running",
"ClickToStartPodman": "Click to start Podman",
"UpdateAvailable": "Update available",
"Update": "Update",
"NewVersionAvailable": "New version ready to install",
"PodmanInstalling": "Installing...",
"PodmanLoading": "Loading...",
Expand Down Expand Up @@ -96,10 +98,14 @@
"SetUp": "Set up",
"SkipForNow": "Skip for now",
"UpdateClient": "Update your client",
"UpdateNamedClient": "Update {{client}}",
"UpdateStopClient": "{{client}} will stop momentarily.",
"UpdateClientDescription": "{{client}} has been downloaded and is ready to install.",
"InstallUpdate": "Install Update",
"Skip": "Skip",
"ViewReleaseNotes": "View release notes",
"ViewNamedReleaseNotes": "View {{name}} release notes",
"ViewDetailedChanges": "View detailed changes...",
"InitialSyncInProgress": "Initial sync in progress...",
"NodeSettings": "Node Settings...",
"RemoveNode": "Remove Node...",
Expand Down
4 changes: 4 additions & 0 deletions assets/locales/en/notifications.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{
"ClientSuccessfulyUpdatedTitle": "Client successfully updated",
"ClientSuccessfulyUpdatedDescription": "{{variable}} has been updated",
"ClientUpdateErrorTitle": "Client update error",
"ClientUpdateErrorDescription": "An error occurred while updating {{variable}}",
"LowDiskSpaceTitle": "Low disk space",
"LowDiskSpaceDescription": "Disk space is lower than 40GB",
"InternetConnectionDownTitle": "Internet connection down",
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions src/common/NodeSpecs/besu/besu-v1.0.0.json
Original file line number Diff line number Diff line change
Expand Up @@ -410,12 +410,14 @@
"type": "text"
},
"infoDescription": "Set to lower number to use less bandwidth",
"documentation": "https://besu.hyperledger.org/public-networks/reference/cli/options#max-peers"
"documentation": "https://besu.hyperledger.org/public-networks/reference/cli/options#max-peers",
"releaseNotesUrl": "https://github.com/NethermindEth/nethermind/releases"
}
},
"documentation": {
"default": "https://besu.hyperledger.org/en/stable/",
"docker": "https://besu.hyperledger.org/en/stable/HowTo/Get-Started/Installation-Options/Run-Docker-Image/"
"docker": "https://besu.hyperledger.org/en/stable/HowTo/Get-Started/Installation-Options/Run-Docker-Image/",
"releaseNotesUrl": "https://github.com/hyperledger/besu/releases"
},
"iconUrl": "https://clientdiversity.org/assets/img/execution-clients/besu-text-logo.png",
"resources": [
Expand Down
4 changes: 4 additions & 0 deletions src/common/NodeSpecs/erigon/erigon-v1.0.0.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,10 @@
},
"category": "L1/ExecutionClient",
"rpcTranslation": "eth-l1",
"documentation": {
"default": "https://erigon.tech/",
"releaseNotesUrl": "https://github.com/ledgerwatch/erigon/releases"
},
"iconUrl": "https://clientdiversity.org/assets/img/execution-clients/erigon-text-logo.png",
"resources": [
{
Expand Down
5 changes: 5 additions & 0 deletions src/common/NodeSpecs/geth/geth-v1.0.0.json
Original file line number Diff line number Diff line change
Expand Up @@ -333,5 +333,10 @@
"defaultValue": "localhost,host.containers.internal"
}
},
"documentation": {
"default": "https://geth.ethereum.org/",
"docker": "https://geth.ethereum.org/docs/getting-started/installing-geth#docker-container",
"releaseNotesUrl": "https://github.com/ethereum/go-ethereum/releases"
},
"iconUrl": "https://clientdiversity.org/assets/img/execution-clients/geth-logo.png"
}
3 changes: 2 additions & 1 deletion src/common/NodeSpecs/lighthouse/lighthouse-v1.0.0.json
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@
},
"documentation": {
"default": "https://lighthouse-book.sigmaprime.io/intro.html",
"docker": "https://lighthouse-book.sigmaprime.io/docker.html"
"docker": "https://lighthouse-book.sigmaprime.io/docker.html",
"releaseNotesUrl": "https://github.com/sigp/lighthouse/releases"
},
"iconUrl": "https://clientdiversity.org/assets/img/consensus-clients/lighthouse-logo.png",
"resources": [
Expand Down
3 changes: 2 additions & 1 deletion src/common/NodeSpecs/lodestar/lodestar-v1.0.0.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@
},
"documentation": {
"default": "https://chainsafe.github.io/lodestar/",
"docker": "https://chainsafe.github.io/lodestar/installation/#install-with-docker"
"docker": "https://chainsafe.github.io/lodestar/installation/#install-with-docker",
"releaseNotesUrl": "https://github.com/ChainSafe/lodestar/releases"
},
"iconUrl": "https://clientdiversity.org/assets/img/consensus-clients/lodestar-logo-text.png",
"resources": [
Expand Down
3 changes: 2 additions & 1 deletion src/common/NodeSpecs/nethermind/nethermind-v1.0.0.json
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,8 @@
"type": "text"
},
"infoDescription": "Set to lower number to use less bandwidth",
"documentation": "https://docs.nethermind.io/nethermind/ethereum-client/configuration/network"
"documentation": "https://docs.nethermind.io/nethermind/ethereum-client/configuration/network",
"releaseNotesUrl": "https://github.com/NethermindEth/nethermind/releases"
}
},
"documentation": {
Expand Down
3 changes: 2 additions & 1 deletion src/common/NodeSpecs/nimbus/nimbus-v1.0.0.json
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@
},
"documentation": {
"default": "https://nimbus.guide/",
"docker": "https://nimbus.guide/docker.html"
"docker": "https://nimbus.guide/docker.html",
"releaseNotesUrl": "https://github.com/status-im/nimbus-eth2/releases"
},
"iconUrl": "https://clientdiversity.org/assets/img/consensus-clients/nimbus-logo-text.png",
"resources": [
Expand Down
3 changes: 2 additions & 1 deletion src/common/NodeSpecs/prysm/prysm-v1.0.0.json
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@
},
"documentation": {
"default": "https://docs.prylabs.network/docs/getting-started",
"docker": "https://docs.prylabs.network/docs/install/install-with-docker/"
"docker": "https://docs.prylabs.network/docs/install/install-with-docker/",
"releaseNotesUrl": "https://github.com/prysmaticlabs/prysm/releases"
},
"iconUrl": "https://clientdiversity.org/assets/img/consensus-clients/prysm-logo.png",
"resources": [
Expand Down
3 changes: 2 additions & 1 deletion src/common/NodeSpecs/reth/reth-v1.0.0.json
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,8 @@
}
},
"documentation": {
"default": "https://paradigmxyz.github.io/reth"
"default": "https://paradigmxyz.github.io/reth",
"releaseNotesUrl": "https://github.com/paradigmxyz/reth/releases"
},
"resources": [
{
Expand Down
3 changes: 2 additions & 1 deletion src/common/NodeSpecs/teku/teku-v1.0.0.json
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@
},
"documentation": {
"default": "https://docs.teku.consensys.net/en/stable/",
"docker": "https://docs.teku.consensys.net/en/stable/HowTo/Get-Started/Installation-Options/Run-Docker-Image/"
"docker": "https://docs.teku.consensys.net/en/stable/HowTo/Get-Started/Installation-Options/Run-Docker-Image/",
"releaseNotesUrl": "https://github.com/ConsenSys/teku/releases"
},
"iconUrl": "https://clientdiversity.org/assets/img/consensus-clients/teku-logo.png",
"resources": [
Expand Down
52 changes: 52 additions & 0 deletions src/common/node-spec-tool/injectDefaultControllerConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import type {
NodeSpecification,
DockerExecution as PodmanExecution,
} from '../nodeSpec.js';

/**
* Injects default controller configuration (cliInput, serviceVersion, etc.)
* into the nodeSpec. It does NOT overwrite existing values.
* Always updated is the default serviceVersion value to spec.excution.defaultImageTag
* For example, if `cliInput` is defined, it does NOT get overwritten.
* @param nodeSpec
*/
export const injectDefaultControllerConfig = (nodeSpec: NodeSpecification) => {
// "inject" serviceVersion and dataDir (todo) here. Universal for all nodes.
const execution = nodeSpec.execution as PodmanExecution;
let defaultImageTag = 'latest';
// if the defaultImageTag is set in the spec use that, otherwise 'latest'
if (execution.defaultImageTag !== undefined) {
defaultImageTag = execution.defaultImageTag;
}

if (!nodeSpec.configTranslation) {
nodeSpec.configTranslation = {};
}

if (!nodeSpec.configTranslation.cliInput) {
nodeSpec.configTranslation.cliInput = {
displayName: `${nodeSpec.displayName} CLI input`,
uiControl: {
type: 'text',
},
defaultValue: '',
addNodeFlow: 'advanced',
infoDescription: 'Additional CLI input',
};
}
if (!nodeSpec.configTranslation.serviceVersion) {
nodeSpec.configTranslation.serviceVersion = {
displayName: `${nodeSpec.displayName} version`,
uiControl: {
type: 'text',
},
defaultValue: defaultImageTag,
addNodeFlow: 'advanced',
infoDescription:
'Possible values: latest, v1.0.0, or stable. Check service documenation.',
};
}

// always update the default serviceVersion value to the latest excution.defaultImageTag
nodeSpec.configTranslation.serviceVersion.defaultValue = defaultImageTag;
};
118 changes: 118 additions & 0 deletions src/common/node-spec-tool/specDiff.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import type { SelectControl, SelectTranslation } from '../nodeConfig.js';
import type { DockerExecution, NodeSpecification } from '../nodeSpec.js';
import { assert, compareObjects } from './util.js';

export type UserSpecDiff = {
message: string;
};

// Only time a user default would be overridden is if the user default is not in the new spec as
// an option on a select config. In that case, the default should be used. So we should highlight any
// removal of select options.
// returns a list of changes
export const calcUserSpecDiff = (
oldSpec: NodeSpecification,
newSpec: NodeSpecification,
): UserSpecDiff[] => {
assert(oldSpec.specId === newSpec.specId, 'specId mismatch');
assert(
oldSpec.version < newSpec.version,
'newSpec version is not greater than oldSpec version',
);

const diffs: UserSpecDiff[] = [];
diffs.push({
message: `Controller version: ${oldSpec.version} -> ${newSpec.version}`,
});
if (oldSpec.displayName !== newSpec.displayName) {
diffs.push({
message: `Name: ${oldSpec.displayName} -> ${newSpec.displayName}`,
});
}

/////// [start] Execution
const oldSpecExecution = oldSpec.execution as DockerExecution;
const newSpecExecution = newSpec.execution as DockerExecution;
if (oldSpecExecution.imageName !== newSpecExecution.imageName) {
diffs.push({
message: `Download URL: ${oldSpecExecution.imageName} -> ${newSpecExecution.imageName}`,
});
}
if (oldSpecExecution.defaultImageTag !== newSpecExecution.defaultImageTag) {
diffs.push({
message: `${newSpec.displayName} Version: ${oldSpecExecution.defaultImageTag} -> ${newSpecExecution.defaultImageTag}`,
});
}
/////// [end] Execution

/////// [start] System Requirements
const oldSysReq = oldSpec.systemRequirements;
const newSysReq = newSpec.systemRequirements;
if (!compareObjects(oldSysReq, newSysReq)) {
let oldSysReqString = '';
let newSysReqString = '';
if (!compareObjects(oldSysReq?.cpu, newSysReq?.cpu)) {
oldSysReqString += ` CPU: ${JSON.stringify(oldSysReq?.cpu)}`;
newSysReqString += ` CPU: ${JSON.stringify(newSysReq?.cpu)}`;
}
if (!compareObjects(oldSysReq?.memory, newSysReq?.memory)) {
oldSysReqString += ` Memory: ${JSON.stringify(oldSysReq?.memory)}`;
newSysReqString += ` Memory: ${JSON.stringify(newSysReq?.memory)}`;
}
if (!compareObjects(oldSysReq?.storage, newSysReq?.storage)) {
oldSysReqString += ` Storage: ${JSON.stringify(oldSysReq?.storage)}`;
newSysReqString += ` Storage: ${JSON.stringify(newSysReq?.storage)}`;
}
if (!compareObjects(oldSysReq?.internet, newSysReq?.internet)) {
oldSysReqString += ` Internet: ${JSON.stringify(oldSysReq?.internet)}`;
newSysReqString += ` Internet: ${JSON.stringify(newSysReq?.internet)}`;
}

diffs.push({
message: `System requirements: ${oldSysReqString} -> ${newSysReqString}`,
});
}
/////// [end] System Requirements

/////// [start] Config Tralsations
const oldTranslations = oldSpec.configTranslation ?? {};
const newTranslations = newSpec.configTranslation ?? {};
const oldTranslationKeys = Object.keys(oldTranslations);
const newTranslationKeys = Object.keys(newTranslations);
for (const key of oldTranslationKeys) {
if (!newTranslationKeys.includes(key)) {
diffs.push({
message: `Removed setting: ${oldTranslations[key]?.displayName}`,
});
} else {
if (oldTranslations[key]?.uiControl?.type.includes('select')) {
const oldSelectOptions = (
oldTranslations[key].uiControl as SelectControl
)?.controlTranslations as SelectTranslation[];
const newSelectOptions = (
newTranslations[key].uiControl as SelectControl
)?.controlTranslations as SelectTranslation[];
if (!compareObjects(oldSelectOptions, newSelectOptions)) {
diffs.push({
message: `Changed setting options: ${JSON.stringify(
oldSelectOptions,
)} -> ${JSON.stringify(newSelectOptions)}`,
});
}
}

// else, they're the same
}
}
for (const key of newTranslationKeys) {
if (!oldTranslationKeys.includes(key)) {
diffs.push({
message: `New setting: ${newTranslations[key]?.displayName}`,
});
}
// else, they were compared when iterating over oldTranslationKeys
}
/////// [end] Config Tralsations

return diffs;
};
Loading