Created
November 8, 2023 04:33
-
-
Save taion809/8ef80bb6f60fb7227101db4db07ab224 to your computer and use it in GitHub Desktop.
HTMX SSE K8S Demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"encoding/json" | |
"fmt" | |
"log" | |
"net/http" | |
"github.com/go-chi/chi" | |
"github.com/go-chi/chi/middleware" | |
v1 "k8s.io/apimachinery/pkg/apis/meta/v1" | |
"k8s.io/apimachinery/pkg/watch" | |
"k8s.io/client-go/kubernetes" | |
"k8s.io/client-go/tools/clientcmd" | |
) | |
var clientset *kubernetes.Clientset | |
func generateK8sEvents(ctx context.Context) (watch.Interface, error) { | |
events, err := clientset.CoreV1().Events("").Watch(ctx, v1.ListOptions{}) | |
if err != nil { | |
return nil, err | |
} | |
return events, nil | |
} | |
func index(w http.ResponseWriter, r *http.Request) { | |
w.WriteHeader(http.StatusOK) | |
w.Write([]byte(indexTmpl)) | |
} | |
func events(w http.ResponseWriter, r *http.Request) { | |
flush, ok := w.(http.Flusher) | |
if !ok { | |
log.Println("Error casting ResponseWriter to Flusher, SSE is not supported") | |
w.WriteHeader(http.StatusInternalServerError) | |
return | |
} | |
events, err := generateK8sEvents(r.Context()) | |
if err != nil { | |
w.WriteHeader(http.StatusInternalServerError) | |
w.Write([]byte(err.Error())) | |
return | |
} | |
defer events.Stop() | |
w.Header().Set("Content-Type", "text/event-stream") | |
card := fmt.Sprintf(cardTemplate, "Initial", "initial k8s event", "") | |
fmt.Fprintf(w, "data: %s\n\n", card) | |
flush.Flush() | |
for event := range events.ResultChan() { | |
log.Println("Event from events api", event.Type) | |
// fuck this stupid api | |
b, err := json.Marshal(event) | |
if err != nil { | |
log.Println("Failed to write to stream", err) | |
break | |
} | |
var extract map[string]interface{} | |
err = json.Unmarshal(b, &extract) | |
if err != nil { | |
log.Println("Failed to write to stream", err) | |
break | |
} | |
obj := extract["Object"].(map[string]interface{}) | |
card = fmt.Sprintf(cardTemplate, obj["reason"], obj["message"], obj["lastTimestamp"]) | |
fmt.Fprintf(w, "data: %v\n\n", card) | |
flush.Flush() | |
} | |
} | |
func main() { | |
// uses the current context in kubeconfig | |
// path-to-kubeconfig -- for example, /root/.kube/config | |
config, err := clientcmd.BuildConfigFromFlags("", "/home/nicholas/.kube/config") | |
if err != nil { | |
log.Fatalln("Unable to open k8s kube config", err) | |
} | |
// creates the clientset | |
clientset, err = kubernetes.NewForConfig(config) | |
if err != nil { | |
log.Fatalln("Unable to create k8s clientset", err) | |
} | |
r := chi.NewRouter() | |
r.Use(middleware.Logger) | |
r.Get("/", index) | |
r.Get("/events", events) | |
fmt.Println("starting server :3000") | |
if err := http.ListenAndServe(":3000", r); err != nil { | |
log.Fatalln(err) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
var indexTmpl = ` | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<title>Hello Everybody!</title> | |
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css"> | |
<script src="https://unpkg.com/[email protected]" integrity="sha384-rgjA7mptc2ETQqXoYC3/zJvkU7K/aP44Y+z7xQuJiVnB/422P/Ak+F/AqFR7E4Wr" crossorigin="anonymous"></script> | |
<script src="https://unpkg.com/htmx.org/dist/ext/sse.js"></script> | |
</head> | |
<body> | |
<section class="section"> | |
<div class="container"> | |
<h1 class="title"> | |
Hello World | |
</h1> | |
<div id="eventStream"> | |
<p>waiting...</p> | |
</div> | |
<div hx-ext="sse" sse-connect="/events" sse-swap="message" hx-swap="afterbegin" hx-target="#eventStream"> | |
Waiting for k8s events... | |
</div> | |
</div> | |
</section> | |
</body> | |
</html> | |
` | |
var cardTemplate = `<div class="card" style="margin-bottom:10px"><header class="card-header"><p class="card-header-title">%s</p></header><div class="card-content"><div class="content">%s<br><span>Received: <strong>%s</strong></span></div></div>` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment