From 6d186ed81303ff1b86c4bc6e85ad04cfeb5dd1f2 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Sat, 1 Jun 2024 17:52:56 +0200 Subject: [PATCH] add blinkstick blinkenlights --- podstatus/app.py | 62 ++++++++++++++++++++++++++++++++++++++---------- poetry.lock | 26 +++++++++++++++++++- pyproject.toml | 1 + 3 files changed, 75 insertions(+), 14 deletions(-) diff --git a/podstatus/app.py b/podstatus/app.py index 5311608..fcec935 100644 --- a/podstatus/app.py +++ b/podstatus/app.py @@ -1,10 +1,12 @@ import logging import os import random +import time from kubernetes import client, config as k8sconfig, watch from flask import Flask, render_template, Response, jsonify from flask_bootstrap import Bootstrap5 from threading import Thread, Event +from blinkstick import blinkstick from config import * @@ -23,27 +25,58 @@ else: k8sconfig.load_incluster_config() +# Kubernetes setup v1 = client.CoreV1Api() namespace = config.K8S_NAMESPACE +# Threading setup stop_event = Event() -@app.route("/") -def index(): - return render_template("index.html") +# Blinkstick setup +bstick = blinkstick.find_first() +led_per_pod = 3 + + +def set_led_color(pod_index, color): + start_led = pod_index * led_per_pod + for i in range(start_led, start_led + led_per_pod): + bstick.set_color(channel=0, index=i, hex=color) + time.sleep(0.1) + def watch_pods(): w = watch.Watch() + pod_index_map = {} for event in w.stream(v1.list_namespaced_pod, namespace, timeout_seconds=0): if stop_event.is_set(): break - pod = event['object'] - pod_status = { - "name": pod.metadata.name, - "status": pod.status.phase, - "index": pod.metadata.labels.get("statefulset.kubernetes.io/pod-name", "unknown"), - } - yield f'data: {pod_status}\n\n' + pod = event["object"] + pod_name = pod.metadata.name + pod_status = pod.status.phase + pod_index = pod.metadata.labels.get( + "statefulset.kubernetes.io/pod-name", "unknown" + ) + + if pod_index not in pod_index_map: + pod_index_map[pod_index] = len(pod_index_map) + + color = ( + "#008000" + if pod_status == "Running" + else "#ffff00" if pod_status == "Pending" else "#ff0000" + ) + set_led_color(pod_index_map[pod_index], color) + + yield f'data: {{"name": "{pod_name}", "status": "{pod_status}", "index": "{pod_index}"}}\n\n' + + +### Routes + + +@app.route("/") +def index(): + return render_template("index.html") + @app.route("/chaos") def chaos(): @@ -56,14 +89,17 @@ def chaos(): else: return jsonify({"message": "No pods available to delete"}), 404 + @app.route("/stream") def stream(): - return Response(watch_pods(), content_type='text/event-stream') + return Response(watch_pods(), content_type="text/event-stream") -@app.route("/shutdown", methods=['POST']) + +@app.route("/shutdown", methods=["POST"]) def shutdown(): stop_event.set() - return 'Shutting down...' + return "Shutting down..." + if __name__ == "__main__": flask_debug = True if config.LOG_LEVEL == "DEBUG" else False diff --git a/poetry.lock b/poetry.lock index 5308213..4fa8afb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -74,6 +74,20 @@ files = [ {file = "blinker-1.8.2.tar.gz", hash = "sha256:8f77b09d3bf7c795e969e9486f39c2c5e9c39d4ee07424be2bc594ece9642d83"}, ] +[[package]] +name = "blinkstick" +version = "1.2.0" +description = "Python package to control BlinkStick USB devices." +optional = false +python-versions = "*" +files = [ + {file = "BlinkStick-1.2.0-py3-none-any.whl", hash = "sha256:eeabbb207180b46f92aec392dd508c24e6ddaede6101f4eb54e7a91bed424d08"}, + {file = "BlinkStick-1.2.0.tar.gz", hash = "sha256:a9324e04a3733c89476182bddeb109b4487de0dc7d01f587e07e191d501cb365"}, +] + +[package.dependencies] +pywinusb = "*" + [[package]] name = "bootstrap-flask" version = "2.4.0" @@ -792,6 +806,16 @@ files = [ {file = "pyusb-1.2.1.tar.gz", hash = "sha256:a4cc7404a203144754164b8b40994e2849fde1cfff06b08492f12fff9d9de7b9"}, ] +[[package]] +name = "pywinusb" +version = "0.4.2" +description = "A package that simplifies USB/HID communications on windows" +optional = false +python-versions = "*" +files = [ + {file = "pywinusb-0.4.2.zip", hash = "sha256:e2f5e89f7b74239ca4843721a9bda0fc99014750630c189a176ec0e1b35e86df"}, +] + [[package]] name = "pyyaml" version = "6.0.1" @@ -1001,4 +1025,4 @@ email = ["email-validator"] [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "22ecfe1db5115220addde002e9a8cb0a57df00a6e9bc9b3db1e3161d0733f517" +content-hash = "c17e1d090da0460aef76108c07ae37ae9153f50e58bbce92af2e4a248a9991e9" diff --git a/pyproject.toml b/pyproject.toml index 726f742..d0e5aff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,7 @@ brother-ql-web = "^0.2.1" gunicorn = "^22.0.0" kubernetes = "^29.0.0" flask-sse = "^1.0.0" +blinkstick = "^1.2.0" [tool.poetry.group.dev.dependencies]