Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions app_go/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.git
*.md
docs/
bin/
dist/
tmp/
.idea/
.vscode/
.DS_Store
18 changes: 18 additions & 0 deletions app_go/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Go binaries / build output
devops-info-service
*.exe
*.out
*.test
bin/
dist/

# IDE/editor
.vscode/
.idea/

# OS files
.DS_Store
Thumbs.db

# Logs
*.log
14 changes: 14 additions & 0 deletions app_go/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# 🔨 Stage 1: Builder
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o myapp

# 🚀 Stage 2: Runtime
FROM gcr.io/distroless/static-debian12:nonroot
WORKDIR /app
COPY --from=builder /app/myapp .
EXPOSE 8080
CMD ["./myapp"]
43 changes: 43 additions & 0 deletions app_go/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# devops-info-service (Go)

## Overview
`devops-info-service` is a lightweight HTTP service written in Go. It returns:
- service metadata (name, version, description, framework),
- system information (hostname, OS/platform, architecture, CPU count, Go version),
- runtime information (uptime, current UTC time),
- request information (client IP, user-agent, method, path),
- a list of available endpoints.

This is useful for DevOps labs and basic observability: quick environment inspection and health checks.

---

## Prerequisites
- **Go:** 1.22+ (recommended)
- No external dependencies (standard library only)

---

## Installation
```bash
cd app_go
go mod tidy
```

## Running the Application
```bash
go run .
```

## API Endpoints
- `GET /` - Service and system information
- `GET /health` - Health check

## Configuration

The application is configured using environment variables.

| Variable | Default | Description | Example |
|---------|---------|-------------|---------|
| `HOST` | `0.0.0.0` | Host interface to bind the server to | `0.0.0.0` |
| `PORT` | `8080` | Port the server listens on | `8080` |
5 changes: 5 additions & 0 deletions app_go/docs/GO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
### Why Go?
- **Compiled binary**: produces a single executable (useful for multi-stage Docker builds).
- **Fast startup and low overhead**: good for microservices.
- **Standard library is enough**: `net/http` covers routing and HTTP server without external frameworks.
- **Great DevOps fit**: simple deployment, small runtime requirements.
217 changes: 217 additions & 0 deletions app_go/docs/LAB01.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
# Lab 1 (Bonus) — DevOps Info Service in Go

## 1. Language / Framework Selection

### Choice
I implemented the bonus service in **Go** using the standard library **net/http** package.

### Why Go?
- **Compiled binary**: produces a single executable (useful for multi-stage Docker builds).
- **Fast startup and low overhead**: good for microservices.
- **Standard library is enough**: `net/http` covers routing and HTTP server without external frameworks.
- **Great DevOps fit**: simple deployment, small runtime requirements.

### Comparison with Alternatives

| Criteria | Go (net/http) (chosen) | Rust | Java (Spring Boot) | C# (ASP.NET Core) |
|---------|--------------------------|------|---------------------|-------------------|
| Build artifact | Single binary | Single binary | JVM app + deps | .NET app + deps |
| Startup time | Fast | Fast | Usually slower | Medium |
| Runtime deps | None | None | JVM required | .NET runtime |
| HTTP stack | stdlib | frameworks (Axum/Actix) | Spring ecosystem | ASP.NET stack |
| Complexity | Low | Medium–high | Medium | Medium |
| Best fit for this lab | Excellent | Good | Overkill | Good |

---

## 2. Best Practices Applied

### 2.1 Clean Code Organization
- Clear data models (`ServiceInfo`, `Service`, `System`, `RuntimeInfo`, `RequestInfo`, `Endpoint`).
- Helper functions for concerns separation:
- `runtimeInfo()`, `requestInfo()`, `uptime()`, `isoUTCNow()`, `clientIP()`, `writeJSON()`.

### 2.2 Configuration via Environment Variables
The service is configurable via environment variables:
- `HOST` (default `0.0.0.0`)
- `PORT` (default `8080`)
- `DEBUG` (default `false`)

Implementation uses a simple helper:
```go
func getenv(key, def string) string {
v := os.Getenv(key)
if v == "" {
return def
}
return v
}
```

### 2.3 Logging Middleware
Request logging is implemented as middleware:
```go
func withLogging(logger *log.Logger) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
logger.Printf("%s %s (%s) from %s in %s",
r.Method, r.URL.Path, r.Proto, r.RemoteAddr, time.Since(start))
})
}
}
```

### 2.4 Error Handling
#### 404 Not Found
Unknown endpoints return a consistent JSON error:
```json
{
"error": "Not Found",
"message": "Endpoint does not exist"
}
```
This is implemented via a wrapper that enforces valid paths:
```go
func withNotFound(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" && r.URL.Path != "/health" {
writeJSON(w, http.StatusNotFound, ErrorResponse{
Error: "Not Found",
Message: "Endpoint does not exist",
})
return
}
next.ServeHTTP(w, r)
})
}
```
#### 500 Internal Server Error (panic recovery)
A recover middleware prevents crashes and returns a safe JSON response:
```go
func withRecover(logger *log.Logger) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if rec := recover(); rec != nil {
logger.Printf("panic recovered: %v", rec)
writeJSON(w, http.StatusInternalServerError, ErrorResponse{
Error: "Internal Server Error",
Message: "An unexpected error occurred",
})
}
}()
next.ServeHTTP(w, r)
})
}
}
```
### 2.5 Production-Friendly HTTP Server Settings
The service uses `http.Server` with timeouts:
```go
srv := &http.Server{
Addr: addr,
Handler: handler,
ReadHeaderTimeout: 5 * time.Second,
}
```
## 3. API Documentation
### 3.1 GET / — Service and System Information
**Description**: Returns service metadata, system info, runtime info, request info, and available endpoints.

**Request**:
```bash
curl -i http://127.0.0.1:8080/
```
**Response (200 OK) example**:
```json
{
"service": {
"name": "devops-info-service",
"version": "1.0.0",
"description": "DevOps course info service",
"framework": "Go net/http"
},
"system": {
"hostname": "DESKTOP-KUN1CI4",
"platform": "windows",
"platform_version": "unknown",
"architecture": "amd64",
"cpu_count": 8,
"go_version": "go1.25.6"
},
"runtime": {
"uptime_seconds": 6,
"uptime_human": "0 hours, 0 minutes",
"current_time": "2026-01-25T17:17:32.248Z",
"timezone": "UTC"
},
"request": {
"client_ip": "::1",
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36 Edg/144.0.0.0",
"method": "GET",
"path": "/"
},
"endpoints": [
{
"path": "/",
"method": "GET",
"description": "Service information"
},
{
"path": "/health",
"method": "GET",
"description": "Health check"
}
]
}
```
### 3.2 GET /health — Health Check
**Description**: Description: Simple health endpoint used for monitoring and probes.

**Request**:
```bash
curl -i http://127.0.0.1:8080/health
```
**Response (200 OK) example**:
```json
{
"status": "healthy",
"timestamp": "2026-01-25T17:19:02.582Z",
"uptime_seconds": 96
}
```
### 3.3 404 Behavior
**Request**:
```bash
curl -i http://127.0.0.1:8080/does-not-exist
```
**Response (404 Not Found)**:
```json
{
"error": "Not Found",
"message": "Endpoint does not exist"
}
```

## 4. Build & Run Instructions
### 4.1 Run locally (no build)
```bash
go run main.go
```
### 4.2 Build binary
```bash
go build -o devops-info-service main.go
```
Run:
```bash
./devops-info-service
```
### 4.3 Environment variables examples
```bash
HOST=127.0.0.1 PORT=3000 ./devops-info-service
DEBUG=true PORT=8081 ./devops-info-service
```
## 5. Challenges & Solutions
I don't know how `go` works.
Loading