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

mardizzone/pos-1040: dev: add: commands to stop/start AWS EC2 instances using terraform with express-cli #133

Merged
merged 8 commits into from
Jan 9, 2023
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ First off, you need to `--init` terraform on your local machine, by executing th
- `../../bin/express-cli --destroy`

- Destroys the remote setup and delete the dedicated VMs
The `express-cli` also comes with additional utility commands, listed below. Some of them are only available for
non-dockerized devnets.

The `express-cli` also comes with additional utility commands, listed below. Some of them are only available for non-dockerized devnets.

- `../../bin/express-cli --update-all [index]`

Expand Down Expand Up @@ -182,6 +182,14 @@ First off, you need to `--init` terraform on your local machine, by executing th
If `--send-state-sync` hasn't been used before, only checkpoints will be detected. The execution stops when
a `state-sync` is found

- ` ../../bin/express-cli --instances-stop`

- Stop the AWS EC2 VM instances associated with the deployed devnet.

- ` ../../bin/express-cli --instances-start`

- Start the (previously stopped) AWS EC2 VM instances associated with the deployed devnet. Also, it starts all services, such as ganache, heimdall, and bor
marcello33 marked this conversation as resolved.
Show resolved Hide resolved

- `../../bin/express-cli --stress [fund]`

- Runs the stress tests on remote nodes. The string `fund` is needed when stress tests are ran for the first time,
Expand Down
20 changes: 17 additions & 3 deletions main.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# main.tf

terraform {
required_providers {
aws = {
Expand Down Expand Up @@ -35,6 +33,18 @@ resource "aws_instance" "app_server" {
}
}

resource "aws_eip" "eip" {
vpc = true
count = (var.DOCKERIZED == "yes") ? 1 : (var.VALIDATOR_COUNT + var.SENTRY_COUNT + var.ARCHIVE_COUNT)
instance = aws_instance.app_server[count.index].id
depends_on = [aws_internet_gateway.gw]
}

resource "aws_eip_association" "eip_assoc" {
count = (var.DOCKERIZED == "yes") ? 1 : (var.VALIDATOR_COUNT + var.SENTRY_COUNT + var.ARCHIVE_COUNT)
instance_id = aws_instance.app_server[count.index].id
allocation_id = aws_eip.eip[count.index].id
}

resource "aws_security_group" "internet_facing_alb" {
name = "internetfacing-loadbalancer-sg"
Expand Down Expand Up @@ -114,5 +124,9 @@ variable "Public_Subnet_1" {
}

output "instance_ips" {
value = aws_instance.app_server.*.public_ip
value = aws_eip.eip.*.public_ip
}

output "instance_ids" {
value = aws_instance.app_server.*.id
}
24 changes: 24 additions & 0 deletions src/express-cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import { checkDir } from './express/common/files-utils'
import { program } from 'commander'
import pkg from '../package.json'
import { testEip1559 } from '../tests/test-eip-1559'
import { stopInstances } from './express/commands/instances-stop'
import { startInstances } from './express/commands/instances-start'

const timer = (ms) => new Promise((resolve) => setTimeout(resolve, ms))

Expand Down Expand Up @@ -59,6 +61,8 @@ program
'Test EIP 1559 txs. In case of a non-dockerized devnet, if an integer [index] is specified, it will use that VM to send the tx. Otherwise, it will target the first VM.'
)
.option('-dd, --setup-datadog', 'Setup DataDog')
.option('-istop, --instances-stop', 'Stop aws ec2 instances')
.option('-istart, --instances-start', 'Start aws ec2 instances')
.version(pkg.version)

export async function cli() {
Expand Down Expand Up @@ -263,5 +267,25 @@ export async function cli() {
}
await timer(3000)
await setupDatadog()
} else if (options.instancesStop) {
console.log('📍Command --instances-stop')
if (!checkDir(false)) {
console.log(
'❌ The command is not called from the appropriate devnet directory!'
)
process.exit(1)
}
await timer(3000)
await stopInstances()
} else if (options.instancesStart) {
console.log('📍Command --instances-start')
if (!checkDir(false)) {
console.log(
'❌ The command is not called from the appropriate devnet directory!'
)
process.exit(1)
}
await timer(3000)
await startInstances()
}
}
47 changes: 47 additions & 0 deletions src/express/commands/instances-start.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// noinspection JSUnresolvedFunction

import { loadDevnetConfig } from '../common/config-utils'
import { restartAll } from './restart'
import { maxRetries, runSshCommand } from '../common/remote-worker'

const shell = require('shelljs')

const timer = (ms) => new Promise((resolve) => setTimeout(resolve, ms))

async function startGanache(doc) {
const ip = `${doc.ethHostUser}@${doc.devnetBorHosts[0]}`
console.log('📍Running ganache in machine ' + ip + ' ...')
const command = 'sudo systemctl start ganache.service'
await runSshCommand(ip, command, maxRetries)
}

export async function startInstances() {
console.log('📍Starting instances...')
require('dotenv').config({ path: `${process.cwd()}/.env` })
const devnetType =
process.env.TF_VAR_DOCKERIZED === 'yes' ? 'docker' : 'remote'
const doc = await loadDevnetConfig(devnetType)
const instances = doc.instancesIds.toString().replace(/,/g, ' ')

shell.exec(`aws ec2 start-instances --instance-ids ${instances}`)
if (shell.error() !== null) {
console.log(
`📍Starting instances ${doc.instancesIds.toString()} didn't work. Please check AWS manually`
)
} else {
console.log(`📍Instances ${doc.instancesIds.toString()} are starting...`)
}

if (devnetType === 'remote') {
console.log('📍Waiting 30s before restarting all services...')
await timer(30000)
await startGanache(doc)
await restartAll(true)
} else {
console.log('📍Waiting 20s to ensure instances are started...')
await timer(20000)
console.log(
'📍You can now ssh into the machine and restart the dockerized services...'
)
}
}
27 changes: 27 additions & 0 deletions src/express/commands/instances-stop.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// noinspection JSUnresolvedFunction

import { loadDevnetConfig } from '../common/config-utils'

const shell = require('shelljs')

const timer = (ms) => new Promise((resolve) => setTimeout(resolve, ms))

export async function stopInstances() {
console.log('📍Stopping instances...')
require('dotenv').config({ path: `${process.cwd()}/.env` })
const devnetType =
process.env.TF_VAR_DOCKERIZED === 'yes' ? 'docker' : 'remote'
const doc = await loadDevnetConfig(devnetType)
const instances = doc.instancesIds.toString().replace(/,/g, ' ')

shell.exec(`aws ec2 stop-instances --instance-ids ${instances}`)
if (shell.error() !== null) {
console.log(
`📍Stopping instances ${doc.instancesIds.toString()} didn't work. Please check AWS manually`
)
} else {
console.log('📍Waiting 20s to ensure instances are stopped...')
await timer(20000)
console.log(`📍Instances ${doc.instancesIds.toString()} are stopping...`)
}
}
2 changes: 2 additions & 0 deletions src/express/commands/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,9 @@ export async function start() {
await terraformApply(devnetId)
const tfOutput = await terraformOutput()
const ips = JSON.parse(tfOutput).instance_ips.value.toString()
const ids = JSON.parse(tfOutput).instance_ids.value.toString()
process.env.DEVNET_BOR_HOSTS = ips
process.env.INSTANCES_IDS = ids

await validateConfigs()

Expand Down
4 changes: 4 additions & 0 deletions src/express/common/config-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ function validateEnvVars() {
}),
MATIC_CLI_BRANCH: validStr({ default: 'master' }),
DEVNET_BOR_USERS: validStr({ default: 'ubuntu,ubuntu' }),
INSTANCES_IDS: validStr({
default: 'i-02a1f3a2884c9edbc,i-03b2d4b3014a4becd'
}),
BOR_DOCKER_BUILD_CONTEXT: url({
default: 'https://github.com/maticnetwork/bor.git#develop'
}),
Expand Down Expand Up @@ -299,6 +302,7 @@ function setCommonConfigs(doc) {
process.env.HEIMDALL_DOCKER_BUILD_CONTEXT,
doc
)
setConfigList('instancesIds', process.env.INSTANCES_IDS, doc)
}

function setConfigValue(key, value, doc) {
Expand Down