diff options
author | Tyler Davis <tydavis@gmail.com> | 2018-02-07 11:42:12 -0800 |
---|---|---|
committer | Tyler Davis <tydavis@gmail.com> | 2018-02-07 11:42:12 -0800 |
commit | dea2f586c826bd296a745deb16bf2d58b9acfc8b (patch) | |
tree | 103a875e492d158bb1114d59f73ffcde4c83adb9 /main.go | |
parent | 642acfe6b68d21d2cb6162d8016b5132db444e39 (diff) | |
download | show-readiness-dea2f586c826bd296a745deb16bf2d58b9acfc8b.tar.gz show-readiness-dea2f586c826bd296a745deb16bf2d58b9acfc8b.zip |
Update with locks, and scratch container
Diffstat (limited to 'main.go')
-rw-r--r-- | main.go | 58 |
1 files changed, 39 insertions, 19 deletions
@@ -5,46 +5,73 @@ import ( "log" "net/http" "os" + "sync" "time" ) +// Globals are generally discouraged, but this is a very simple program, and we +// are designing with concurrent access in mind. + +// Creating a custom struct with a lock, so we can lock access to the object +type status struct { + value int + sync.Mutex +} + // ReadyValue indiciates the program is ready to receive traffic -var ReadyValue = http.StatusOK +var ReadyValue = status{value: http.StatusOK} // LiveValue indiciates the program is alive and should not be terminated -var LiveValue = http.StatusOK +var LiveValue = status{value: http.StatusOK} var hostname string func makeNotReady(w http.ResponseWriter, r *http.Request) { - ReadyValue = http.StatusBadRequest + // Lock access to the variable, then set our global ReadyValue to a failing + // value before sending the response + ReadyValue.Lock() + ReadyValue.value = http.StatusBadRequest + ReadyValue.Unlock() w.Header().Set("responding-pod", hostname) fmt.Fprintf(w, "%s", "Set Readiness Value to a failure state") } +// Hitting this endpoint (by any means) will func makePodReady(w http.ResponseWriter, r *http.Request) { - ReadyValue = http.StatusOK + ReadyValue.Lock() + ReadyValue.value = http.StatusOK + ReadyValue.Unlock() w.Header().Set("responding-pod", hostname) fmt.Fprintf(w, "%s", "Set Readiness Value to successful (OK) state") } +// This function guarantees Kubernetes will kill the pod func killMe(w http.ResponseWriter, r *http.Request) { - LiveValue = http.StatusBadRequest + LiveValue.Lock() + LiveValue.value = http.StatusBadRequest + LiveValue.Unlock() w.Header().Set("responding-pod", hostname) fmt.Fprintf(w, "%s", "Set Liveness Value to a failure state") } +// Provides Ready state to Kubernetes for receiving/stopping traffic func readinessCheck(w http.ResponseWriter, r *http.Request) { w.Header().Set("responding-pod", hostname) - http.Error(w, "Responding with ReadyValue", ReadyValue) + ReadyValue.Lock() + http.Error(w, "Responding with ReadyValue", ReadyValue.value) + ReadyValue.Unlock() } +// Endpoint checked internally by Kubernetes func livenessCheck(w http.ResponseWriter, r *http.Request) { w.Header().Set("responding-pod", hostname) - http.Error(w, "Responding with LiveValue", LiveValue) + LiveValue.Lock() + http.Error(w, "Responding with LiveValue", LiveValue.value) + LiveValue.Unlock() } +// The default endpoint func rootHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("responding-pod", hostname) fmt.Fprintf(w, "%s", "I'm serving traffic!") @@ -54,21 +81,14 @@ func main() { // Force log output to stdout for Docker log.SetOutput(os.Stdout) - // Configurable delay for startup - var delay = (1 * time.Second) - if os.Getenv("APPDELAY") != "" { - var err error - delay, err = time.ParseDuration(os.Getenv("APPDELAY")) - if err != nil { - log.Fatalf("Failed to parse time duration: %v", err) - } - } - time.Sleep(delay) - // Finish startup hostname, _ = os.Hostname() log.Println("Service started on port 80") + // Set up a custom mutex to add custom handlers. [Note] this level of breakout + // is not required, as we could reasonably compact this into a single call, + // but would lose some readability. This also makes it easy for us to use a + // custom muxer (e.g. gorillamux), custom server, etc mux := http.NewServeMux() mux.HandleFunc("/", rootHandler) mux.HandleFunc("/ping", livenessCheck) @@ -84,8 +104,8 @@ func main() { WriteTimeout: 3 * time.Second, } + // Actually run our server if err := server.ListenAndServe(); err != nil { log.Fatalln(err) } - } |