Skip to content

Commit

Permalink
feat: introduce separate roles for deployment placements
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelfig committed Mar 24, 2021
1 parent cc6cff2 commit a395571
Show file tree
Hide file tree
Showing 13 changed files with 199 additions and 65 deletions.
4 changes: 4 additions & 0 deletions packages/agoric-cli/lib/chain-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ export function finishTendermintConfig({
exportMetrics,
portNum = `${DEFAULT_RPC_PORT}`,
persistentPeers = '',
seeds = '',
unconditionalPeerIds = '',
}) {
const rpcPort = Number(portNum);

Expand All @@ -70,6 +72,8 @@ export function finishTendermintConfig({
// Update addresses in the config.
config.p2p.laddr = `tcp://0.0.0.0:${rpcPort - 1}`;
config.p2p.persistent_peers = persistentPeers;
config.p2p.unconditional_peer_ids = unconditionalPeerIds;
config.p2p.seeds = seeds;
config.rpc.laddr = `tcp://0.0.0.0:${rpcPort}`;
config.rpc.max_body_bytes = 15 * 10 ** 6;

Expand Down
6 changes: 6 additions & 0 deletions packages/agoric-cli/lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ const main = async (progname, rawArgs, powers) => {
'set the config.toml p2p.persistent_peers value',
'',
)
.option('--seeds <addrs>', 'set the config.toml p2p.seeds value', '')
.option(
'--unconditional-peer-ids <ids>',
'set the config.toml p2p.unconditional_peer_ids value',
'',
)
.option(
'--export-metrics',
'open ports to export Prometheus metrics',
Expand Down
4 changes: 3 additions & 1 deletion packages/agoric-cli/lib/set-defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,14 @@ export default async function setDefaultsMain(progname, rawArgs, powers, opts) {

if (configFile) {
log(`read ${configFile}`);
const { persistentPeers } = opts;
const { persistentPeers, seeds, unconditionalPeerIds } = opts;
const configToml = await fs.readFile(configFile, 'utf-8');

const newConfigToml = finishTendermintConfig({
configToml,
persistentPeers,
seeds,
unconditionalPeerIds,
exportMetrics,
});
await create(configFile, newConfigToml);
Expand Down
2 changes: 1 addition & 1 deletion packages/deployment/ansible/cosmos-genesis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@
- STAKER: ag-staker
- STAKER_TOKENS: 10000000000000000000000000uagstake
- STAKER_AMOUNT: 50000000uagstake
- STAKER_NODE: node0
- STAKER_NODE: validator0
roles:
- cosmos-genesis
4 changes: 2 additions & 2 deletions packages/deployment/ansible/cosmos-validators.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---

- hosts: "{{ service }}"
- hosts: validator
user: root
#any_errors_fatal: true
gather_facts: yes
Expand All @@ -10,7 +10,7 @@
- data: "{{ SETUP_HOME }}/{{ service }}/data"
- CHAIN_NAME: "{{ lookup('file', SETUP_HOME + '/' + service + '/chain-name.txt') }}"
- STAKER: ag-staker
- STAKER_NODE: node0
- STAKER_NODE: validator0
- STAKER_AMOUNT: 50000000uagstake
roles:
- cosmos-validators
61 changes: 51 additions & 10 deletions packages/deployment/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { assert, details as X } from '@agoric/assert';
import { PLAYBOOK_WRAPPER, SSH_TYPE } from './setup';
import { shellEscape } from './run';

export const AVAILABLE_ROLES = ['validator', 'peer', 'seed'];

const calculateTotal = placement =>
(placement ? Object.values(placement) : []).reduce(
(prior, cur) => prior + cur,
Expand Down Expand Up @@ -42,7 +44,6 @@ const tfStringify = obj => {
return ret;
};

/** @param {Powers} arg0 */
const genericAskApiKey = ({ env, inquirer }) => async (provider, myDetails) => {
const questions = [
{
Expand Down Expand Up @@ -149,6 +150,7 @@ module "${PLACEMENT}" {
CLUSTER_NAME = "${PREFIX}\${var.NETWORK_NAME}-${PLACEMENT}"
OFFSET = "\${var.OFFSETS["${PLACEMENT}"]}"
SSH_KEY_FILE = "\${var.SSH_KEY_FILE}"
ROLE = "\${var.ROLES["${PLACEMENT}"]}"
SERVERS = "\${length(var.DATACENTERS["${PLACEMENT}"])}"
VOLUMES = "\${var.VOLUMES["${PLACEMENT}"]}"
}
Expand Down Expand Up @@ -184,6 +186,7 @@ module "${PLACEMENT}" {
CLUSTER_NAME = "${PREFIX}\${var.NETWORK_NAME}-${PLACEMENT}"
OFFSET = "\${var.OFFSETS["${PLACEMENT}"]}"
REGIONS = "\${var.DATACENTERS["${PLACEMENT}"]}"
ROLE = "\${var.ROLES["${PLACEMENT}"]}"
SSH_KEY_FILE = "\${var.SSH_KEY_FILE}"
DO_API_TOKEN = "\${var.API_KEYS["${PLACEMENT}"]}"
SERVERS = "\${length(var.DATACENTERS["${PLACEMENT}"])}"
Expand All @@ -193,7 +196,7 @@ module "${PLACEMENT}" {
},
});

const askPlacement = ({ inquirer }) => PLACEMENTS => {
const askPlacement = ({ inquirer }) => async (PLACEMENTS, ROLES) => {
let total = 0;
PLACEMENTS.forEach(
([_PLACEMENT, placement]) => (total += calculateTotal(placement)),
Expand All @@ -211,13 +214,28 @@ const askPlacement = ({ inquirer }) => PLACEMENTS => {
DONE,
NEW,
...PLACEMENTS.map(([place, placement]) => ({
name: `${place}${nodeCount(calculateTotal(placement))}`,
name: `${ROLES[place]} - ${place}${nodeCount(
calculateTotal(placement),
)}`,
value: place,
})),
],
},
];
return inquirer.prompt(questions);

const first = await inquirer.prompt(questions);

const roleQuestions = [
{
name: 'ROLE',
type: 'list',
message: `Role for the ${first.PLACEMENT} placement?`,
choices: AVAILABLE_ROLES,
},
];
const second = first.PLACEMENT ? await inquirer.prompt(roleQuestions) : {};

return { ...first, ...second };
};

const askProvider = ({ inquirer }) => PROVIDERS => {
Expand Down Expand Up @@ -280,23 +298,27 @@ const doInit = ({ env, rd, wr, running, setup, inquirer, fetch }) => async (
SSH_PRIVATE_KEY_FILE: `id_${SSH_TYPE}`,
DETAILS: {},
OFFSETS: {},
ROLES: {},
DATACENTERS: {},
PROVIDER_NEXT_INDEX: {},
};
config.NETWORK_NAME = overrideNetworkName;

let instance = 0;

// eslint-disable-next-line no-constant-condition
while (true) {
// eslint-disable-next-line no-await-in-loop
let { PLACEMENT } = await askPlacement({ inquirer })(config.PLACEMENTS);
const { ROLE, ...rest } = await askPlacement({ inquirer })(
config.PLACEMENTS,
config.ROLES,
);
let { PLACEMENT } = rest;
if (!PLACEMENT) {
break;
}
let provider;
let myDetails = {};
if (PLACEMENT !== 'NEW') {
config.ROLES[PLACEMENT] = ROLE;
const PROVIDER = config.PLACEMENT_PROVIDER[PLACEMENT];
provider = PROVIDERS[PROVIDER];
} else {
Expand All @@ -320,6 +342,7 @@ const doInit = ({ env, rd, wr, running, setup, inquirer, fetch }) => async (
}
idx[PROVIDER] += 1;
PLACEMENT = `${PROVIDER}${idx[PROVIDER]}`;
config.ROLES[PLACEMENT] = ROLE;
config.PLACEMENT_PROVIDER[PLACEMENT] = PROVIDER;
};

Expand Down Expand Up @@ -354,6 +377,7 @@ const doInit = ({ env, rd, wr, running, setup, inquirer, fetch }) => async (
provider.datacenters &&
// eslint-disable-next-line no-await-in-loop
(await provider.datacenters(provider, PLACEMENT, myDetails));
config.ROLES;
const [_p, placement] = config.PLACEMENTS.find(
([p]) => p === PLACEMENT,
) || [PLACEMENT, {}];
Expand Down Expand Up @@ -412,7 +436,12 @@ const doInit = ({ env, rd, wr, running, setup, inquirer, fetch }) => async (
}

// Collate the placement information.
const ROLE_INSTANCE = {};
Object.values(config.ROLES).forEach(role => {
ROLE_INSTANCE[role] = 0;
});
for (const [PLACEMENT, placement] of config.PLACEMENTS) {
let instance = ROLE_INSTANCE[config.ROLES[PLACEMENT]];
const offset = instance;
config.DATACENTERS[PLACEMENT] = [];
for (const dc of Object.keys(placement).sort()) {
Expand All @@ -433,10 +462,14 @@ const doInit = ({ env, rd, wr, running, setup, inquirer, fetch }) => async (
}

// Commit the final details.
ROLE_INSTANCE[config.ROLES[PLACEMENT]] = instance;
config.OFFSETS[PLACEMENT] = offset;
}

assert(instance !== 0, X`Aborting due to no nodes configured!`);
assert(
Object.values(ROLE_INSTANCE).some(i => i > 0),
X`Aborting due to no nodes configured!`,
);

await wr.createFile(
`vars.tf`,
Expand All @@ -459,6 +492,10 @@ variable "OFFSETS" {
default = ${tfStringify(config.OFFSETS)}
}
variable "ROLES" {
default = ${tfStringify(config.ROLES)}
}
${Object.keys(config.DETAILS)
.sort()
.map(
Expand All @@ -473,7 +510,7 @@ variable ${JSON.stringify(vname)} {
);

// Go and create the specific files.
const clusterPrefix = 'ag-chain-cosmos-';
const clusterPrefix = 'ag-';
for (const PLACEMENT of Object.keys(config.PLACEMENT_PROVIDER).sort()) {
const PROVIDER = config.PLACEMENT_PROVIDER[PLACEMENT];
const provider = PROVIDERS[PROVIDER];
Expand All @@ -493,6 +530,10 @@ ${Object.keys(config.DATACENTERS)
}
}
output "roles" {
value = "\${var.ROLES}"
}
output "offsets" {
value = "\${var.OFFSETS}"
}
Expand Down Expand Up @@ -535,4 +576,4 @@ pipelining = True
await wr.createFile(networkTxt, config.NETWORK_NAME);
};

export default doInit;
export { doInit };
Loading

0 comments on commit a395571

Please sign in to comment.