💡 Introduction
Welcome to the world of DevOps! 🚀 Today, I’m back with another exciting blog to help you dive deeper into practical programming for DevOps tasks. In my previous blog, we explored 3 Python projects that laid the foundation for DevOps automation.
Now, let’s switch gears and explore the power of Go-lang! This blog will guide you through building 3 Go-lang projects that are both practical and beginner-friendly:
- A Monitor Disk Usage tool for tracking storage stats.
- Hosting a resume website using an HTTP server.
- A RESTful API program to manage DevOps tools.
So, grab your favorite code editor, and let’s get started! 🎉
💡 Pre-Requisites
Before we dive into building these projects, let’s make sure your environment is set up and ready to go. Here’s what you need:
1. Go (Golang)
You’ll need to have Go installed on your system. Follow these steps based on your operating system:
Windows
- Download the latest Go installer from the official website.
- Run the installer and follow the on-screen instructions.
- Verify the installation by opening Command Prompt or PowerShell and typing:
go version
Ubuntu
- Open a terminal and run:
sudo apt update
sudo apt install -y golang
- Verify the installation:
go version
macOS
- Use Homebrew to install Go. Run:
brew install go
- Verify the installation:
go version
2. Basic Understanding of Go
While you don’t need to be an expert, having a fundamental understanding of Go concepts like variables, functions, and structs will help you follow along smoothly. If you’re new to Go, I recommend exploring the Go Tour for a quick introduction.
With these prerequisites met, you’re all set to start building these awesome Go-lang projects! 🚀
💡 Monitor Disk Usage App
Let’s kick off our journey with the first project — a disk usage monitoring tool. This program will help you analyze disk usage for any specified directory on your system.
You can find the source code in my GitHub repository. Let’s start by creating a file named disk_usage.go and adding the following code:
package main
import (
"fmt"
"os"
"syscall"
)
func getDiskUsage(path string) {
var stat syscall.Statfs_t
err := syscall.Statfs(path, &stat)
if err != nil {
fmt.Println("Error Fetching Disk Usage:", err)
return
}
total := stat.Blocks * uint64(stat.Bsize)
free := stat.Bfree * uint64(stat.Bsize)
used := total - free
percentUsed := float64(used) / float64(total) * 100
fmt.Printf("Disk usage of %s:\n", path)
fmt.Printf("Total: %d GB\n", total/1e9)
fmt.Printf("Used: %d GB (%.2f%%)\n", used/1e9, percentUsed)
fmt.Printf("Free: %d GB\n", free/1e9)
}
func main() {
path := "/"
if len(os.Args) > 1 {
path = os.Args[1]
}
_, err := os.Stat(path)
if os.IsNotExist(err) {
fmt.Printf("Error: '%s' Path doesn't exist.\n", path)
return
} else if err != nil {
fmt.Printf("Error occurred while accessing path %s: %v \n", path, err)
return
}
getDiskUsage(path)
}
How the Program Works:
- The program uses the syscall.Statfs function to fetch disk statistics, including the total, used, and free space.
- It calculates the percentage of disk space used and formats the output in a user-friendly way.
- Error handling is implemented to check if the provided path exists or if there’s an issue accessing it.
Running the Program
To run the program, use the following commands:
- Check the disk usage of a specific directory:
go run disk_usage.go /path/to/directory
- If no path is specified, the program defaults to the root directory (/):
go run disk_usage.go
Since I have a single partition, I will get the same result if I provide different paths.
This project demonstrates how Go can interact with your system’s underlying APIs, making it a great starting point for system monitoring tasks. 🎉
💡 HTTP Server Program: Hosting a Portfolio Website
The second project involves creating an HTTP server in Go that hosts a portfolio website. This project demonstrates how you can build and serve static websites while incorporating a health check endpoint for monitoring.
You can find the source code in my GitHub repository.
Steps to Build the HTTP Server
- Create a file named http_server.go and add the following code:
package main
import (
"fmt"
"net/http"
)
func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
}
func main() {
fs := http.FileServer(http.Dir("./static"))
http.Handle("/", fs)
http.HandleFunc("/health", healthCheckHandler)
port := "8090"
fmt.Printf("Starting server on port %s....", port)
err := http.ListenAndServe(":"+port, nil)
if err != nil {
fmt.Println("Error starting server:", err)
}
}
How It Works
- Static File Server: The http.FileServer function serves files from the ./static directory.
- Health Check Endpoint: A /health route is defined to provide a simple health check metric.
- Server Setup: The server listens on port 8090 by default, and any errors during startup are logged.
Creating the Portfolio Website
-
Structure: Inside the static folder, create:
index.html
style.css
- A folder named images with a profile picture named profile.jpeg.
Add the following content to your files:
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pravesh Sudha - Portfolio</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<div class="container">
<img src="images/profile.jpeg" alt="Pravesh Sudha" class="profile-picture">
<h1>Pravesh Sudha</h1>
<p class="subtitle">DevOps Engineer | Freelancer at Fiverr | Tech Blogger</p>
</div>
</header>
<main>
<div class="about">
<h2>About Me</h2>
<p>
I am a passionate DevOps engineer with extensive experience in containerization, orchestration, and cloud computing.
I love contributing to open-source projects and writing beginner-friendly guides on Hashnode and Medium.
</p>
</div>
<div class="links">
<h2>Connect with Me</h2>
<ul>
<li><a href="https://fiverr.com/praveshsudha" target="_blank">Fiverr Profile</a></li>
<li><a href="https://praveshstwt.hashnode.dev" target="_blank">Hashnode Blog</a></li>
<li><a href="https://medium.com/@programmerpravesh" target="_blank">Medium Blog</a></li>
<li><a href="https://gravatar.com/praveshsudha" target="_blank">Gravatar</a></li>
</ul>
</div>
</main>
<footer>
<p>© 2024 Pravesh Sudha</p>
</footer>
</body>
</html>
style.css:
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
line-height: 1.6;
color: #333;
background-color: #f9f9f9;
}
header {
background: #4caf50;
color: #fff;
padding: 20px 0;
text-align: center;
}
header .profile-picture {
width: 150px;
height: 150px;
border-radius: 50%;
margin-bottom: 15px;
}
header h1 {
font-size: 2.5em;
margin: 0;
}
header .subtitle {
font-size: 1.2em;
margin: 0;
}
main {
padding: 20px;
max-width: 800px;
margin: 20px auto;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
main .about,
main .links {
margin-bottom: 20px;
}
main .links ul {
list-style: none;
padding: 0;
}
main .links li {
margin: 10px 0;
}
main .links a {
color: #4caf50;
text-decoration: none;
font-weight: bold;
}
main .links a:hover {
text-decoration: underline;
}
footer {
text-align: center;
padding: 10px 0;
background: #333;
color: #fff;
}
Running the Program
- Start the HTTP server with the following command:
go run http_server.go
- Your portfolio website will now be available at:
localhost:8090
Accessing the Health Check
To check the health of the server, visit:
localhost:8090/health
This project showcases how to use Go-lang to create a functional web server for hosting static content, with additional monitoring through a health check endpoint. 🎉
💡 RESTful API Project: Managing DevOps Tools
In the final project of this blog, we’ll create a RESTful API that allows you to manage a list of DevOps tools. This program demonstrates the use of Go’s net/http package to handle RESTful routes and manage data.
The complete source code is available on my GitHub repository.
Building the RESTful API
Step 1: Main Program
Create a file named main.go and add the following code:
package main
import (
"log"
"net/http"
"project/tools"
)
func main() {
http.HandleFunc("/tools", tools.ListTools)
http.HandleFunc("/tools/add", tools.AddTool)
http.HandleFunc("/tools/details", tools.ToolDetails)
port := "8090"
log.Printf("Starting the server at port %v", port)
err := http.ListenAndServe(":"+port, nil)
if err != nil {
log.Fatal("Error starting the server:", err)
}
}
Step 2: Data Handling
In the tools directory, create a file named data.go and add:
package tools
import "sync"
// Tool represents a DevOps tool.
type Tool struct {
Name string `json:"name"`
Description string `json:"description"`
Category string `json:"category"`
}
var toolStore = []Tool{
{"Docker", "A Platform to build, run and share containerized applications.", "Containerization"},
{"Kubernetes", "An orchestration tool for managing containerized workloads.", "Orchestration"},
{"Jenkins", "An open-source automation server for CI/CD.", "CI/CD"},
}
var mu sync.Mutex
Step 3: Handlers
In the tools directory, create another file named handler.go and add:
package tools
import (
"encoding/json"
"net/http"
)
// ListTools handles GET requests to list all tools.
func ListTools(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "Invalid Request Method", http.StatusMethodNotAllowed)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(toolStore)
}
// AddTool handles POST requests to add a new tool.
func AddTool(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Invalid Method Type", http.StatusMethodNotAllowed)
return
}
var newTool Tool
if err := json.NewDecoder(r.Body).Decode(&newTool); err != nil {
http.Error(w, "Invalid Request Body", http.StatusBadRequest)
return
}
mu.Lock()
toolStore = append(toolStore, newTool)
mu.Unlock()
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(newTool)
}
// ToolDetails handles GET requests to fetch details of a specific tool.
func ToolDetails(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "Invalid Method Type", http.StatusMethodNotAllowed)
return
}
toolName := r.URL.Query().Get("name")
if toolName == "" {
http.Error(w, "Missing Tool Name", http.StatusBadRequest)
return
}
mu.Lock()
defer mu.Unlock()
for _, tool := range toolStore {
if tool.Name == toolName {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(tool)
return
}
}
http.Error(w, "Tool Not Found", http.StatusNotFound)
}
Initializing the Module
Before running the program, initialize the Go module:
go mod init project
This ensures the project can use the project/tools package.
Running the Program
Start the server by running:
go run main.go
Testing the API
- List All Tools To fetch the list of tools, use:
curl localhost:8090/tools
Output:
[
{"name":"Docker","description":"A Platform to build, run and share Containerized applications.","category":"Containerization"},
{"name":"Kubernetes","description":"An orchestration tool for managing containerized workloads.","category":"Orchestration"},
{"name":"Jenkins","description":"An open-source automation server for CICD","category":"CI/CD"}
]
- Add a New Tool To add a new tool, use:
curl -X POST -H "Content-Type: application/json" \
-d '{"name":"Prometheus","description":"A monitoring system and time-series database.","category":"Monitoring"}' \
http://localhost:8090/tools/add
Output:
{"name":"Prometheus","description":"A monitoring system and time-series database.","category":"Monitoring"}
- Fetch Tool Details To fetch details of a specific tool, use:
curl "http://localhost:8090/tools/details?name=Prometheus"
Output:
{"name":"Prometheus","description":"A monitoring system and time-series database.","category":"Monitoring"}
💡 Conclusion
In this blog, we’ve explored three practical Go projects that help you get hands-on experience with different aspects of software development. From monitoring disk usage to building a simple HTTP server to hosting a portfolio website, and finally, creating a RESTful API to manage DevOps tools, these projects provide a solid foundation for anyone looking to sharpen their Go programming skills.
- The disk usage monitoring application introduced you to system calls and basic file handling in Go, giving you insight into how you can interact with a machine’s file system.
- The HTTP server project allowed you to learn how to serve static files and handle basic health-check endpoints, helping you get started with web development in Go.
- The RESTful API project demonstrated how to structure an API, manage data with concurrency control, and make your application interactive through POST and GET requests.
Each of these projects is a building block that can be expanded upon to suit real-world applications. Whether you are interested in monitoring systems, developing web applications, or building APIs, Go provides the simplicity and power needed for efficient development.
🚀 For more informative blog, Follow me on Hashnode, X(Twitter) and LinkedIn.
Till then, Happy Coding!!
Happy Learning! 🎉
Top comments (0)