Skip to content

Commit

Permalink
Fixed host override when there is no custom preset is provided (#222)
Browse files Browse the repository at this point in the history
* Fixed host override when there no custom preset is provided
* Fixed voting, roles and privateKeySecurityMode overrides
* Loading preset and assembly from existing target/address.yml
* Audit fix
* Improved validation and error handling
  • Loading branch information
fboucquez authored Apr 1, 2021
1 parent 34ff6a0 commit a72c014
Show file tree
Hide file tree
Showing 19 changed files with 131 additions and 66 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ The changelog format is based on [Keep a Changelog](https://keepachangelog.com/e
| ---------------- | ------- | ------------------------------------------------------------------ |
| Symbol Bootstrap | v1.0.4 | [symbol-bootstrap](https://www.npmjs.com/package/symbol-bootstrap) |

- Fixed host override when no custom preset is provided in mainnet.
- Fixed case issue validating keys when creating certificates.

## [1.0.3] - Mar-31-2021
Expand Down
3 changes: 2 additions & 1 deletion cmds/start-testnet-supernode.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#!/bin/bash
set -e
symbol-bootstrap start -p testnet -a dual -t target/testnet-supernode -c test/supernode.yml $1 $2 $3
symbol-bootstrap config -p testnet -a dual -t target/testnet-supernode -c test/supernode.yml -r --password 1111 $1 $2 $3
symbol-bootstrap start --password 1111 --upgrade -t target/testnet-supernode
6 changes: 4 additions & 2 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ USAGE
$ symbol-bootstrap config
OPTIONS
-a, --assembly=assembly An optional assembly type, example "dual" for testnet
-a, --assembly=assembly The assembly, example "dual" for testnet. If not provided, the value is
resolved from the target/preset.yml file.
-c, --customPreset=customPreset External preset file. Values in this file will override the provided presets
(optional)
-h, --help It shows the help of this command.
-p, --preset=(bootstrap|testnet|mainnet) [default: bootstrap] the network preset
-p, --preset=(bootstrap|testnet|mainnet) The network preset, can be provided via custom preset or cli parameter. If
not provided, the value is resolved from the target/preset.yml file.
-r, --reset It resets the configuration generating a new one
Expand Down
5 changes: 3 additions & 2 deletions docs/start.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ USAGE
OPTIONS
-a, --assembly=assembly
An optional assembly type, example "dual" for testnet
The assembly, example "dual" for testnet. If not provided, the value is resolved from the target/preset.yml file.
-b, --build
If provided, docker-compose will run with -b (--build)
Expand All @@ -31,7 +31,8 @@ OPTIONS
It shows the help of this command.
-p, --preset=(bootstrap|testnet|mainnet)
[default: bootstrap] the network preset
The network preset, can be provided via custom preset or cli parameter. If not provided, the value is resolved from
the target/preset.yml file.
-r, --reset
It resets the configuration generating a new one
Expand Down
1 change: 0 additions & 1 deletion presets/bootstrap/network.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ nodes:
openPort: '{{add $index 7900}}'
- repeat: 1
harvesting: false
voting: false
api: true
friendlyName: 'api-node-{{$index}}'
name: 'api-node-{{$index}}'
Expand Down
2 changes: 0 additions & 2 deletions presets/mainnet/assembly-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ databases:
openPort: false
nodes:
- harvesting: false
voting: false
api: true
name: 'node'
host: ''
databaseHost: 'db'
brokerName: 'broker'
openPort: true
Expand Down
2 changes: 0 additions & 2 deletions presets/mainnet/assembly-dual.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ databases:
openPort: false
nodes:
- harvesting: true
voting: false
api: true
name: 'node'
host: ''
databaseHost: 'db'
brokerName: 'broker'
openPort: true
Expand Down
2 changes: 0 additions & 2 deletions presets/mainnet/assembly-peer.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
localNetworks: 127.0.0.1
nodes:
- harvesting: true
voting: false
api: false
name: 'node'
openPort: true
host: ''
2 changes: 1 addition & 1 deletion presets/shared.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
nodeUseRemoteAccount: true
privateKeySecurityMode: ENCRYPT
nodePort: 7900
enableCacheDatabaseStorage: true
enableVerifiableState: true
Expand Down Expand Up @@ -105,6 +104,7 @@ maxHashesPerPoint: 256
prevoteBlocksMultiple: 4
nonVotingUnfinalizedBlocksDuration: 8m
votingUnfinalizedBlocksDuration: 0m
voting: false

# config messages:
subscriberPort: 7902
Expand Down
1 change: 0 additions & 1 deletion presets/testnet/assembly-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ databases:
openPort: false
nodes:
- harvesting: false
voting: false
api: true
name: 'api-node'
databaseHost: 'db'
Expand Down
1 change: 0 additions & 1 deletion presets/testnet/assembly-dual.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ databases:
openPort: false
nodes:
- harvesting: true
voting: false
api: true
name: 'api-node'
databaseHost: 'db'
Expand Down
1 change: 0 additions & 1 deletion presets/testnet/assembly-peer.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
localNetworks: 127.0.0.1
nodes:
- harvesting: true
voting: false
api: false
name: 'peer-node'
openPort: true
7 changes: 4 additions & 3 deletions src/commands/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,14 @@ export default class Config extends Command {
noPassword: CommandUtils.noPasswordFlag,
preset: flags.enum({
char: 'p',
description: 'the network preset',
description:
'The network preset, can be provided via custom preset or cli parameter. If not provided, the value is resolved from the target/preset.yml file.',
options: Object.keys(Preset).map((v) => v as Preset),
default: ConfigService.defaultParams.preset,
}),
assembly: flags.string({
char: 'a',
description: 'An optional assembly type, example "dual" for testnet',
description:
'The assembly, example "dual" for testnet. If not provided, the value is resolved from the target/preset.yml file.',
}),

customPreset: flags.string({
Expand Down
2 changes: 1 addition & 1 deletion src/model/ConfigPreset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ export interface CommonConfigPreset extends NodeConfigPreset, GatewayConfigPrese
preset: Preset;
assembly: string;
assemblies?: string;
privateKeySecurityMode: string;
privateKeySecurityMode?: string;
votingKeysDirectory: string;
sinkAddress?: string;
epochAdjustment: string;
Expand Down
94 changes: 61 additions & 33 deletions src/service/ConfigLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -331,68 +331,96 @@ export class ConfigLoader {
private static getArray(size: number): number[] {
return [...Array(size).keys()];
}
private loadCustomPreset(customPreset: string | undefined, password: string | undefined): CustomPreset {
if (!customPreset) {
return {};
}
if (!existsSync(customPreset)) {
throw new KnownError(
`Custom preset '${customPreset}' doesn't exist. Have you provided the right --customPreset <customPrestFileLocation> ?`,
);
}
return BootstrapUtils.loadYaml(customPreset, password);
}

private loadAssembly(root: string, preset: Preset, assembly: string | undefined): CustomPreset {
if (!assembly) {
return {};
}
const fileLocation = `${root}/presets/${preset}/assembly-${assembly}.yml`;
if (!existsSync(fileLocation)) {
throw new KnownError(
`Assembly '${assembly}' is not valid for preset '${preset}'. Have you provided the right --preset <preset> --assembly <assembly> ?`,
);
}
return BootstrapUtils.loadYaml(fileLocation, false);
}

public createPresetData({
password,
root,
preset,
assembly,
customPreset,
customPresetObject,
}: {
public createPresetData(params: {
password: string | undefined;
root: string;
preset: Preset;
preset?: Preset;
assembly?: string;
customPreset?: string;
customPresetObject?: CustomPreset;
oldPresetData?: ConfigPreset;
}): ConfigPreset {
const sharedPreset: ConfigPreset = BootstrapUtils.loadYaml(join(root, 'presets', 'shared.yml'), false);
const networkPreset: CustomPreset = BootstrapUtils.loadYaml(`${root}/presets/${preset}/network.yml`, false);
const assemblyPreset: CustomPreset = assembly
? BootstrapUtils.loadYaml(`${root}/presets/${preset}/assembly-${assembly}.yml`, false)
: {};
const customPresetFileObject: CustomPreset = customPreset ? BootstrapUtils.loadYaml(customPreset, password) : {};
const customPreset = params.customPreset;
const customPresetObject = params.customPresetObject;
const oldPresetData = params.oldPresetData;
const customPresetFileObject = this.loadCustomPreset(customPreset, params.password);
const preset =
params.preset ||
params.customPresetObject?.preset ||
customPresetFileObject?.preset ||
oldPresetData?.preset ||
Preset.bootstrap;

const assembly =
params.assembly || params.customPresetObject?.assembly || customPresetFileObject?.assembly || params.oldPresetData?.assembly;

const root = params.root;
const sharedPreset = BootstrapUtils.loadYaml(join(root, 'presets', 'shared.yml'), false);
const networkPreset = BootstrapUtils.loadYaml(`${root}/presets/${preset}/network.yml`, false);
const assemblyPreset = this.loadAssembly(root, preset, assembly);
//Deep merge
const inflation: Record<string, number> =
customPresetObject?.inflation ||
customPresetFileObject?.inflation ||
assemblyPreset?.inflation ||
networkPreset?.inflation ||
sharedPreset?.inflation ||
{};
const presetData: ConfigPreset = _.merge(sharedPreset, networkPreset, assemblyPreset, customPresetFileObject, customPresetObject, {
version: 1,
bootstrapVersion: BootstrapUtils.VERSION,
preset: preset,
assembly: assembly || 'default',
[];
const presetData = _.merge(sharedPreset, networkPreset, assemblyPreset, customPresetFileObject, customPresetObject, {
preset,
});
if (presetData.assemblies && !assembly) {
throw new Error(`Preset ${preset} requires assembly (-a, --assembly option). Possible values are: ${presetData.assemblies}`);
}
presetData.inflation = inflation;
if (!ConfigLoader.presetInfoLogged) {
logger.info(`Generating config from preset ${preset}`);
logger.info(`Generating config from preset '${preset}'`);
if (assembly) {
logger.info(`Assembly preset ${assembly}`);
logger.info(`Using assembly '${assembly}'`);
}
if (customPreset) {
logger.info(`Custom preset file ${customPreset}`);
logger.info(`Using custom preset file '${customPreset}'`);
}
}
ConfigLoader.presetInfoLogged = true;
if (presetData.assemblies && !assembly) {
throw new Error(`Preset ${preset} requires assembly (-a, --assembly option). Possible values are: ${presetData.assemblies}`);
}
const presetDataWithDynamicDefaults: ConfigPreset = {
const presetDataWithDynamicDefaults = {
version: 1,
preset: preset,
assembly: assembly || '',
...presetData,
nodes: this.dynamicDefaultNodeConfiguration(presetData.nodes),
};
return this.expandRepeat(presetDataWithDynamicDefaults);
return _.merge(oldPresetData || {}, this.expandRepeat(presetDataWithDynamicDefaults));
}

public dynamicDefaultNodeConfiguration(nodes?: NodePreset[]): NodePreset[] {
return _.map(nodes || [], (node) => {
const expandedNodeConfiguration = { ...this.getDefaultConfiguration(node), ...node };
const roles = this.resolveRoles(expandedNodeConfiguration);
return { ...expandedNodeConfiguration, roles };
return { ...this.getDefaultConfiguration(node), ...node };
});
}

Expand Down Expand Up @@ -438,7 +466,7 @@ export class ConfigLoader {
};
}

private resolveRoles(nodePreset: NodePreset): string {
public static resolveRoles(nodePreset: NodePreset): string {
if (nodePreset.roles) {
return nodePreset.roles;
}
Expand Down
15 changes: 6 additions & 9 deletions src/service/ConfigService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export interface ConfigParams {
report: boolean;
reset: boolean;
upgrade: boolean;
preset: Preset;
preset?: Preset;
target: string;
password?: string;
user: string;
Expand All @@ -88,7 +88,6 @@ export class ConfigService {
public static defaultParams: ConfigParams = {
target: BootstrapUtils.defaultTargetFolder,
report: false,
preset: Preset.bootstrap,
reset: false,
upgrade: false,
pullImages: false,
Expand Down Expand Up @@ -177,10 +176,7 @@ export class ConfigService {
}

private resolveCurrentPresetData(oldPresetData: ConfigPreset | undefined, password: string | undefined) {
return _.merge(
_.omit(oldPresetData || {}, 'inflation'),
this.configLoader.createPresetData({ ...this.params, root: this.root, password: password }),
);
return this.configLoader.createPresetData({ ...this.params, root: this.root, password: password, oldPresetData });
}

private async copyNemesis(addresses: Addresses) {
Expand Down Expand Up @@ -237,13 +233,13 @@ export class ConfigService {
await BootstrapUtils.generateConfiguration({}, presetData.nemesisSeedFolder, nemesisSeedFolder);
return;
}
const finalNemesisSeed = join(this.root, 'presets', this.params.preset, 'seed');
const finalNemesisSeed = join(this.root, 'presets', presetData.preset, 'seed');
if (existsSync(finalNemesisSeed)) {
await BootstrapUtils.generateConfiguration({}, finalNemesisSeed, nemesisSeedFolder);
await this.validateSeedFolder(nemesisSeedFolder, `Is the ${this.params.preset} preset default seed a valid seed folder?`);
await this.validateSeedFolder(nemesisSeedFolder, `Is the ${presetData.preset} preset default seed a valid seed folder?`);
return;
}
logger.warn(`Seed for preset ${this.params.preset} could not be found in ${finalNemesisSeed}`);
logger.warn(`Seed for preset ${presetData.preset} could not be found in ${finalNemesisSeed}`);

throw new Error('Seed could not be found!!!!');
}
Expand Down Expand Up @@ -316,6 +312,7 @@ export class ConfigService {
? presetData.votingUnfinalizedBlocksDuration
: presetData.nonVotingUnfinalizedBlocksDuration,
beneficiaryAddress: beneficiaryAddress == undefined ? account.main.address : beneficiaryAddress,
roles: ConfigLoader.resolveRoles(nodePreset),
};
const templateContext: any = { ...presetData, ...generatedContext, ...nodePreset };
const excludeFiles: string[] = [];
Expand Down
5 changes: 4 additions & 1 deletion src/service/CryptoUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ export class CryptoUtils {
return value;
}

public static getPrivateKeySecurityMode(value: string): PrivateKeySecurityMode {
public static getPrivateKeySecurityMode(value: string | undefined): PrivateKeySecurityMode {
if (!value) {
return PrivateKeySecurityMode.ENCRYPT;
}
const securityModes = Object.values(PrivateKeySecurityMode) as PrivateKeySecurityMode[];
const securityMode = securityModes.find((p) => p.toLowerCase() == value.toLowerCase());
if (securityMode) {
Expand Down
Loading

0 comments on commit a72c014

Please sign in to comment.