#JavaScript & Node.js for DevOps

Node.js brings JavaScript to the server-side, making it a powerful choice for DevOps automation, especially for teams already using JavaScript in their frontend stack.

#šŸ“‹ Table of Contents


#Why Node.js for DevOps?

#Key Advantages

AdvantageDescription
UbiquitousJavaScript is everywhere, easy to find developers
Async I/ONon-blocking operations for efficient scripting
NPM EcosystemLargest package registry in the world
Cross-PlatformRuns on Linux, Windows, macOS
JSON NativePerfect for API interactions and config files

#Use Cases

Loading diagram...

#Setting Up Node.js

bash
1# Install nvm (Node Version Manager)
2curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
3
4# Reload shell configuration
5source ~/.bashrc
6
7# Install Node.js LTS
8nvm install --lts
9nvm use --lts
10
11# Verify installation
12node --version
13npm --version

#Direct Installation

bash
1# Ubuntu/Debian
2curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
3sudo apt-get install -y nodejs
4
5# macOS (Homebrew)
6brew install node
7
8# Windows (Chocolatey)
9choco install nodejs-lts

#Project Setup

bash
1# Create new project
2mkdir devops-automation
3cd devops-automation
4
5# Initialize package.json
6npm init -y
7
8# Install common DevOps packages
9npm install axios dotenv yaml commander chalk ora

#Node.js Basics

#Variables and Functions

javascript
1// Modern ES6+ syntax
2const serverName = 'web-server-01';
3let port = 8080;
4const isHealthy = true;
5
6// Arrays
7const servers = ['web-01', 'web-02', 'web-03'];
8
9// Objects
10const serverConfig = {
11    name: 'web-server-01',
12    ip: '10.0.1.100',
13    port: 8080,
14    enabled: true
15};
16
17// Template literals
18console.log(`Server ${serverName} is running on port ${port}`);
19
20// Arrow functions
21const checkHealth = async (host, port) => {
22    // Implementation
23    return true;
24};
25
26// Destructuring
27const { name, ip } = serverConfig;
28console.log(`Name: ${name}, IP: ${ip}`);

#Async/Await

javascript
1const axios = require('axios');
2
3// Async function with error handling
4async function fetchServerStatus(url) {
5    try {
6        const response = await axios.get(url, { timeout: 5000 });
7        return {
8            status: 'healthy',
9            statusCode: response.status,
10            data: response.data
11        };
12    } catch (error) {
13        return {
14            status: 'unhealthy',
15            error: error.message
16        };
17    }
18}
19
20// Using the function
21async function main() {
22    const status = await fetchServerStatus('https://api.github.com');
23    console.log('Status:', status);
24}
25
26main();

#Promises

javascript
1// Promise-based function
2function delay(ms) {
3    return new Promise(resolve => setTimeout(resolve, ms));
4}
5
6// Promise.all for parallel operations
7async function checkAllServers(servers) {
8    const checks = servers.map(server => checkHealth(server));
9    const results = await Promise.all(checks);
10    return results;
11}
12
13// Promise.allSettled (doesn't fail if one fails)
14async function checkAllServersSafe(servers) {
15    const checks = servers.map(server => checkHealth(server));
16    const results = await Promise.allSettled(checks);
17    
18    return results.map((result, index) => ({
19        server: servers[index],
20        status: result.status,
21        value: result.value || result.reason
22    }));
23}

#File System Operations

javascript
1const fs = require('fs').promises;
2const path = require('path');
3const yaml = require('yaml');
4
5// Read file
6async function readConfig(filePath) {
7    try {
8        const content = await fs.readFile(filePath, 'utf-8');
9        return yaml.parse(content);
10    } catch (error) {
11        console.error(`Error reading ${filePath}:`, error.message);
12        return null;
13    }
14}
15
16// Write file
17async function writeConfig(filePath, data) {
18    const content = yaml.stringify(data);
19    await fs.writeFile(filePath, content, 'utf-8');
20    console.log(`Config written to ${filePath}`);
21}
22
23// List directory
24async function listServers(directory) {
25    const files = await fs.readdir(directory);
26    const serverFiles = files.filter(f => f.endsWith('.yaml'));
27    
28    for (const file of serverFiles) {
29        const filePath = path.join(directory, file);
30        const config = await readConfig(filePath);
31        console.log(`Server: ${config.name}, IP: ${config.ip}`);
32    }
33}
34
35// Check if file exists
36async function fileExists(filePath) {
37    try {
38        await fs.access(filePath);
39        return true;
40    } catch {
41        return false;
42    }
43}

#Working with APIs

#HTTP Requests with Axios

javascript
1const axios = require('axios');
2
3// Create configured client
4const apiClient = axios.create({
5    baseURL: 'https://api.example.com',
6    timeout: 10000,
7    headers: {
8        'Authorization': `Bearer ${process.env.API_TOKEN}`,
9        'Content-Type': 'application/json'
10    }
11});
12
13// GET request
14async function getServers() {
15    const response = await apiClient.get('/servers');
16    return response.data;
17}
18
19// POST request
20async function createServer(serverData) {
21    const response = await apiClient.post('/servers', serverData);
22    return response.data;
23}
24
25// DELETE request
26async function deleteServer(serverId) {
27    await apiClient.delete(`/servers/${serverId}`);
28    console.log(`Server ${serverId} deleted`);
29}

#AWS SDK

javascript
1const { EC2Client, DescribeInstancesCommand, RunInstancesCommand } = require('@aws-sdk/client-ec2');
2const { S3Client, ListBucketsCommand } = require('@aws-sdk/client-s3');
3
4// Configure AWS clients
5const ec2 = new EC2Client({ region: 'us-east-1' });
6const s3 = new S3Client({ region: 'us-east-1' });
7
8// List EC2 instances
9async function listInstances() {
10    const command = new DescribeInstancesCommand({});
11    const response = await ec2.send(command);
12    
13    for (const reservation of response.Reservations) {
14        for (const instance of reservation.Instances) {
15            console.log(`Instance: ${instance.InstanceId}`);
16            console.log(`  State: ${instance.State.Name}`);
17            console.log(`  Type: ${instance.InstanceType}`);
18        }
19    }
20}
21
22// List S3 buckets
23async function listBuckets() {
24    const command = new ListBucketsCommand({});
25    const response = await s3.send(command);
26    
27    for (const bucket of response.Buckets) {
28        console.log(`Bucket: ${bucket.Name}`);
29    }
30}

#Building Automation Scripts

#Server Health Check Script

javascript
1#!/usr/bin/env node
2
3const axios = require('axios');
4const chalk = require('chalk');
5const ora = require('ora');
6
7const servers = [
8    { name: 'Web Server', url: 'https://google.com', expectedStatus: 200 },
9    { name: 'API Server', url: 'https://api.github.com', expectedStatus: 200 },
10    { name: 'Database', url: 'http://localhost:5432', expectedStatus: 200 },
11];
12
13async function checkServer(server) {
14    try {
15        const start = Date.now();
16        const response = await axios.get(server.url, { timeout: 5000 });
17        const latency = Date.now() - start;
18        
19        return {
20            ...server,
21            status: 'healthy',
22            latency,
23            statusCode: response.status
24        };
25    } catch (error) {
26        return {
27            ...server,
28            status: 'unhealthy',
29            error: error.message
30        };
31    }
32}
33
34async function main() {
35    console.log(chalk.bold('\nšŸ” Server Health Check\n'));
36    
37    const spinner = ora('Checking servers...').start();
38    
39    const results = await Promise.all(servers.map(checkServer));
40    
41    spinner.stop();
42    
43    for (const result of results) {
44        if (result.status === 'healthy') {
45            console.log(chalk.green(`āœ… ${result.name}: healthy (${result.latency}ms)`));
46        } else {
47            console.log(chalk.red(`āŒ ${result.name}: ${result.error}`));
48        }
49    }
50    
51    const healthy = results.filter(r => r.status === 'healthy').length;
52    console.log(chalk.bold(`\nšŸ“Š Summary: ${healthy}/${results.length} servers healthy\n`));
53}
54
55main().catch(console.error);

#Building a CLI Tool with Commander

javascript
1#!/usr/bin/env node
2
3const { program } = require('commander');
4const chalk = require('chalk');
5
6program
7    .name('devops-cli')
8    .description('DevOps automation CLI')
9    .version('1.0.0');
10
11program
12    .command('server')
13    .description('Server management commands')
14    .command('list')
15    .description('List all servers')
16    .option('-e, --environment <env>', 'Filter by environment', 'all')
17    .action((options) => {
18        console.log(chalk.blue(`Listing servers for environment: ${options.environment}`));
19        // Implementation
20    });
21
22program
23    .command('deploy')
24    .description('Deploy application')
25    .argument('<environment>', 'Target environment')
26    .option('-t, --tag <tag>', 'Docker image tag', 'latest')
27    .option('-f, --force', 'Force deployment', false)
28    .action((environment, options) => {
29        console.log(chalk.yellow(`Deploying to ${environment}`));
30        console.log(`  Tag: ${options.tag}`);
31        console.log(`  Force: ${options.force}`);
32        // Implementation
33    });
34
35program.parse();

PackagePurposeInstall
axiosHTTP clientnpm install axios
@aws-sdk/client-**AWS SDK v3npm install @aws-sdk/client-ec2
@azure/*Azure SDKnpm install @azure/arm-compute
commanderCLI frameworknpm install commander
chalkTerminal colorsnpm install chalk
oraTerminal spinnersnpm install ora
dotenvEnvironment variablesnpm install dotenv
yamlYAML parsingnpm install yaml
shelljsShell commandsnpm install shelljs
execaBetter child_processnpm install execa

#Best Practices

#1. Use Environment Variables

javascript
1require('dotenv').config();
2
3const config = {
4    apiUrl: process.env.API_URL || 'http://localhost:3000',
5    apiKey: process.env.API_KEY,
6    environment: process.env.NODE_ENV || 'development'
7};

#2. Handle Errors Properly

javascript
1process.on('unhandledRejection', (reason, promise) => {
2    console.error('Unhandled Rejection:', reason);
3    process.exit(1);
4});
5
6process.on('uncaughtException', (error) => {
7    console.error('Uncaught Exception:', error);
8    process.exit(1);
9});

#3. Use Proper Logging

javascript
1const winston = require('winston');
2
3const logger = winston.createLogger({
4    level: 'info',
5    format: winston.format.combine(
6        winston.format.timestamp(),
7        winston.format.json()
8    ),
9    transports: [
10        new winston.transports.Console(),
11        new winston.transports.File({ filename: 'app.log' })
12    ]
13});
14
15logger.info('Deployment started');
16logger.error('Deployment failed', { error: 'Connection timeout' });

#Summary

ConceptKey Points
SetupUse nvm, npm for packages
Asyncasync/await, Promise.all
Filesfs.promises, yaml/json
HTTPaxios for API calls
CLIcommander for CLI tools

[!TIP] Pro Tip: Node.js excels at I/O-bound tasks. Use it for API automation, file processing, and building developer tools!