dce-dev-wizard
Version:
Wizard for managing development apps at Harvard DCE.
159 lines (138 loc) • 4.99 kB
text/typescript
import clear from 'clear';
// Import helpers
import showChooser from '../helpers/showChooser';
import getDeploymentConfig from '../operations/getDeploymentConfig';
import print from '../helpers/print';
import prompt from '../helpers/prompt';
import exec from '../helpers/exec';
import config from '../helpers/config';
// Import shared types
import Deployment from '../types/Deployment';
import ChooserOption from '../types/ChooserOption';
/**
* Show and/or modify related cluster status
* @author Gabe Abrams
* @param deployment the currently selected deployment
*/
const relatedClusters = async (deployment: Deployment) => {
while (true) {
// Show loading indicator
clear();
console.log('Checking status of related instances...\n');
// Get related clusters
const { relatedClusters } = config;
if (!relatedClusters || relatedClusters.length === 0) {
clear();
console.log('No related clusters. In your dceConfig.json file, add a "relatedClusters" array.');
return;
}
// Get the status on related clusters
const relatedClustersWithStatus: {
name: string,
cluster: string,
isOnline: boolean,
}[] = [];
for (let i = 0; i < relatedClusters.length; i += 1) {
const relatedCluster = relatedClusters[i];
// Check if the related cluster is valid
if (!relatedCluster.cluster || !relatedCluster.name) {
console.log('Related clusters must be of form { name, cluster } where name is a human-readable name, cluster is the AWS cluster name.');
process.exit(0);
}
// Execute status command via aws cli
const statusOutput = exec(
`aws autoscaling describe-auto-scaling-groups --query "AutoScalingGroups[?contains(AutoScalingGroupName, '${relatedCluster.cluster}')] | [].Instances[] | length(@)"`,
false,
);
// Check if the output is a number
if (Number.isNaN(Number.parseInt(statusOutput, 10))) {
console.log(`Error getting status of ${relatedCluster.name} (${relatedCluster.cluster})`);
console.log(`Got output: ${statusOutput} but expected a number.`);
process.exit(0);
}
const isOnline = Number.parseInt(statusOutput, 10) >= 2;
// Write to related cluster list
relatedClustersWithStatus.push({
...relatedCluster,
isOnline,
});
}
// Show status
clear();
const options: ChooserOption[] = relatedClustersWithStatus.map((cluster) => {
return {
description: `${cluster.name} (${cluster.isOnline ? 'ONLINE' : 'Offline'})`,
};
});
// Option to refresh
options.push({
description: '[Refresh Status]',
tag: 'R',
});
// Option to go back to main menu
options.push({
description: '[Back to Main Menu]',
tag: 'B',
});
// Show chooser
const option = showChooser({
question: 'Choose a cluster to turn on/off:',
options,
});
if (option.tag === 'B') {
// Back to main menu
return;
}
if (option.tag === 'R') {
// Refresh status
continue;
}
const cluster = relatedClustersWithStatus[option.index];
// Re-check status
const statusOutput = exec(
`aws autoscaling describe-auto-scaling-groups --query "AutoScalingGroups[?contains(AutoScalingGroupName, '${cluster.cluster}')] | [].Instances[] | length(@)"`,
false,
);
const nowIsOnline = Number.parseInt(statusOutput, 10) >= 2;
if (nowIsOnline !== cluster.isOnline) {
console.log('Status is out of date. Please continue to refresh.');
await print.enterToContinue();
continue;
}
// Ready to toggle!
const newStatus = (cluster.isOnline ? 'off' : 'on');
const script = `
ON_OR_OFF="${newStatus}"
CLUSTER_NAME="${cluster.cluster}"
if ! command -v -- "aws" >/dev/null 2>&1; then
echo "AWS CLI is not installed. Please install it first."
exit 1
fi
desiredCapacity=$([ "$ON_OR_OFF" == "on" ] && echo 1 || echo 0)
asgs=$(
aws autoscaling describe-auto-scaling-groups \
--query "AutoScalingGroups[?contains(AutoScalingGroupName, '$CLUSTER_NAME')].AutoScalingGroupName" \
--output text
)
for asg in $asgs; do
echo "Turning $ON_OR_OFF auto scaling group $asg"
aws autoscaling set-desired-capacity \
--auto-scaling-group-name $asg \
--desired-capacity $desiredCapacity \
--no-honor-cooldown
done
`;
clear();
print.title(`Turning ${newStatus}`);
console.log(`\nTurning ${newStatus} ${cluster.name}...\n`);
await exec(script, true);
await new Promise((r) => {
setTimeout(r, 3000);
});
clear();
print.title('Cluster Updated');
console.log(`\n${cluster.name} is ${cluster.isOnline ? 'turning off' : 'turning on'}. This will take up to 15min.\n`);
print.enterToContinue();
}
};
export default relatedClusters;