Hands-on Lab

#Lab 02: Build a CLI Tool with Go

Create a professional CLI tool using Go and Cobra.

#šŸŽÆ Objectives

  • Set up a Go project with modules
  • Build a CLI with Cobra
  • Implement health check commands

#šŸ“‹ Prerequisites

  • Go 1.20+ installed
  • Basic Go knowledge

#šŸ”¬ Lab Steps

#Step 1: Project Setup

bash
1mkdir server-cli
2cd server-cli
3go mod init github.com/yourusername/server-cli
4go get github.com/spf13/cobra@latest

#Step 2: Create Main File

Create main.go:

go
1package main
2
3import (
4    "github.com/yourusername/server-cli/cmd"
5)
6
7func main() {
8    cmd.Execute()
9}

#Step 3: Create Root Command

Create cmd/root.go:

go
1package cmd
2
3import (
4    "fmt"
5    "os"
6
7    "github.com/spf13/cobra"
8)
9
10var cfgFile string
11
12var rootCmd = &cobra.Command{
13    Use:   "server-cli",
14    Short: "A CLI tool for server management",
15    Long:  `A DevOps CLI tool for managing and monitoring servers.`,
16}
17
18func Execute() {
19    if err := rootCmd.Execute(); err != nil {
20        fmt.Println(err)
21        os.Exit(1)
22    }
23}
24
25func init() {
26    rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", 
27        "config file (default is ./config.yaml)")
28}

#Step 4: Create Health Command

Create cmd/health.go:

go
1package cmd
2
3import (
4    "fmt"
5    "net"
6    "sync"
7    "time"
8
9    "github.com/spf13/cobra"
10)
11
12type Server struct {
13    Name string
14    Host string
15    Port int
16}
17
18type Result struct {
19    Server  Server
20    Healthy bool
21    Latency time.Duration
22    Error   string
23}
24
25var healthCmd = &cobra.Command{
26    Use:   "health",
27    Short: "Check server health",
28    Run:   runHealthCheck,
29}
30
31func init() {
32    rootCmd.AddCommand(healthCmd)
33}
34
35func checkHealth(server Server) Result {
36    start := time.Now()
37    address := fmt.Sprintf("%s:%d", server.Host, server.Port)
38    
39    conn, err := net.DialTimeout("tcp", address, 5*time.Second)
40    if err != nil {
41        return Result{Server: server, Healthy: false, Error: err.Error()}
42    }
43    defer conn.Close()
44    
45    return Result{
46        Server:  server,
47        Healthy: true,
48        Latency: time.Since(start),
49    }
50}
51
52func runHealthCheck(cmd *cobra.Command, args []string) {
53    servers := []Server{
54        {Name: "Google", Host: "google.com", Port: 443},
55        {Name: "GitHub", Host: "github.com", Port: 443},
56    }
57    
58    var wg sync.WaitGroup
59    results := make(chan Result, len(servers))
60    
61    fmt.Println("šŸ” Checking servers...")
62    
63    for _, server := range servers {
64        wg.Add(1)
65        go func(s Server) {
66            defer wg.Done()
67            results <- checkHealth(s)
68        }(server)
69    }
70    
71    wg.Wait()
72    close(results)
73    
74    healthyCount := 0
75    for result := range results {
76        if result.Healthy {
77            fmt.Printf("āœ… %s: healthy (%v)\n", result.Server.Name, result.Latency)
78            healthyCount++
79        } else {
80            fmt.Printf("āŒ %s: %s\n", result.Server.Name, result.Error)
81        }
82    }
83    
84    fmt.Printf("\nšŸ“Š %d/%d servers healthy\n", healthyCount, len(servers))
85}

#Step 5: Build and Run

bash
1# Build
2go build -o server-cli .
3
4# Run
5./server-cli health

#āœ… Success Criteria

  • CLI builds successfully
  • Health command works
  • Parallel checks execute properly

#šŸŽ“ What You Learned

  • Go project structure
  • Cobra CLI framework
  • Goroutines and channels
  • TCP health checks