Disclaimer: not really REST, but writing HTTP-controlled made the title too long.
TL;DR
When compiled with CGO_ENABLED=0
, this code produces a static binary file that can be uploaded to a server and run.
CPU burn can be started by requesting /start_cpu
and stopped by requesting /stop_cpu
.
Long version
Recently I had to implement an integration test in which I had to fire up a virtual machine and control its CPU load. The first idea was to write a simple Python web service, so I could control the CPU load via HTTP requests. The testing was being done on devstack though, and its test VM image is that of CirrOS, which only includes Busybox and no Python.
So I needed a static binary I could just scp
on the VM and run. Go turned out to be the answer to my problem. Even though I never programmed in Go before, I soon had a working HTTP-controlled staticly linked web service. To achieve static linking, the compiler and the code needs to be compiled with environment variable CGO_ENABLED=0
(issue).
Cross compilation
On top of that, Go allowed me to easily cross-compile a Linux binary on OSX just by (quickly) recompiling Go compiler with Linux support
cd /usr/local/go/src
sudo GOOS=linux GOARCH=386 CGO_ENABLED=0 ./make.bash --no-clean
and then compiling my code with additional options GOOS=linux GOARCH=386
.
Other platforms are similar, for more information take a look at An introduction to cross compilation with Go.
package main
import (
"fmt"
"net/http"
"time"
)
var burnCpu = make(chan bool)
func cpuBurn() {
var burn bool = false
for {
select {
case burn = <-burnCpu:
default:
if burn {
_ = 5*5
} else {
time.Sleep(100 * time.Millisecond)
}
}
}
}
func startCpu(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Starting CPU burn\n")
burnCpu <- true
}
func stopCpu(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Stopping CPU burn\n")
burnCpu <- false
}
func main() {
go cpuBurn()
http.HandleFunc("/start_cpu", startCpu)
http.HandleFunc("/stop_cpu", stopCpu)
http.ListenAndServe(":8080", nil)
}