#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?
- Setting Up Node.js
- Node.js Basics
- File System Operations
- Working with APIs
- Building Automation Scripts
- Popular DevOps Packages
#Why Node.js for DevOps?
#Key Advantages
| Advantage | Description |
|---|---|
| Ubiquitous | JavaScript is everywhere, easy to find developers |
| Async I/O | Non-blocking operations for efficient scripting |
| NPM Ecosystem | Largest package registry in the world |
| Cross-Platform | Runs on Linux, Windows, macOS |
| JSON Native | Perfect for API interactions and config files |
#Use Cases
Loading diagram...
#Setting Up Node.js
#Installation with nvm (Recommended)
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();#Popular DevOps Packages
| Package | Purpose | Install |
|---|---|---|
| axios | HTTP client | npm install axios |
| @aws-sdk/client-** | AWS SDK v3 | npm install @aws-sdk/client-ec2 |
| @azure/* | Azure SDK | npm install @azure/arm-compute |
| commander | CLI framework | npm install commander |
| chalk | Terminal colors | npm install chalk |
| ora | Terminal spinners | npm install ora |
| dotenv | Environment variables | npm install dotenv |
| yaml | YAML parsing | npm install yaml |
| shelljs | Shell commands | npm install shelljs |
| execa | Better child_process | npm 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
| Concept | Key Points |
|---|---|
| Setup | Use nvm, npm for packages |
| Async | async/await, Promise.all |
| Files | fs.promises, yaml/json |
| HTTP | axios for API calls |
| CLI | commander 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!