From 28e1ba2a790d40089cb208260dee93496080cabf Mon Sep 17 00:00:00 2001 From: Daniil Antoshin Date: Thu, 30 Jul 2026 08:52:01 +0200 Subject: [PATCH 1/2] demo: showcase changes across languages, statuses and a binary image Signed-off-by: Daniil Antoshin --- demo/config.yaml | 5 +++-- demo/go.sum | 5 +++-- demo/gpu.go | 15 ++++++++++++- demo/{old_helper.rs => helper.rs} | 4 ++++ demo/legacy.rb | 10 --------- demo/logo.png | Bin 0 -> 4922 bytes demo/server.py | 8 ++++++- demo/ui.tsx | 34 ++++++++++++++++++++++++++++++ 8 files changed, 65 insertions(+), 16 deletions(-) rename demo/{old_helper.rs => helper.rs} (74%) delete mode 100644 demo/legacy.rb create mode 100644 demo/logo.png create mode 100644 demo/ui.tsx diff --git a/demo/config.yaml b/demo/config.yaml index 8214675..d32667f 100644 --- a/demo/config.yaml +++ b/demo/config.yaml @@ -5,7 +5,8 @@ metadata: spec: driver: gpu.example.com parameters: - sharing: none - memory: 16Gi + sharing: time-sliced + memory: 24Gi + replicas: 4 nodeSelector: accelerator: nvidia diff --git a/demo/go.sum b/demo/go.sum index 489ccc9..c16f218 100644 --- a/demo/go.sum +++ b/demo/go.sum @@ -1,4 +1,5 @@ -example.com/dra v1.3.0 h1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa= -example.com/dra v1.3.0/go.mod h1:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb= +example.com/dra v1.4.0 h1:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee= +example.com/dra v1.4.0/go.mod h1:fffffffffffffffffffffffffffffffffffffffffff= k8s.io/api v0.30.0 h1:ccccccccccccccccccccccccccccccccccccccccccc= k8s.io/api v0.30.0/go.mod h1:ddddddddddddddddddddddddddddddddddddddddddd= +k8s.io/klog/v2 v2.120.1 h1:ggggggggggggggggggggggggggggggggggggggggggg= diff --git a/demo/gpu.go b/demo/gpu.go index 9fcf12a..09acfc1 100644 --- a/demo/gpu.go +++ b/demo/gpu.go @@ -3,14 +3,19 @@ package gpu import ( "context" + "errors" "fmt" ) +// ErrNodeNotFound is returned when a node has no inventory yet. +var ErrNodeNotFound = errors.New("node not found") + // DeviceInfo describes a single GPU exposed to a pod. type DeviceInfo struct { Name string Driver string UUID string + Shared bool } // StatusController reconciles GPU claims against node inventory. @@ -21,16 +26,24 @@ type StatusController struct { func (c *StatusController) getGPUStatus(info DeviceInfo, node string) (string, error) { devices, ok := c.nodes[node] if !ok { - return "", fmt.Errorf("node %q not found", node) + return "", fmt.Errorf("%w: %q", ErrNodeNotFound, node) } for _, d := range devices { if d.UUID == info.UUID { + if d.Shared { + return "shared", nil + } return "allocated", nil } } return "pending", nil } +// Count returns how many devices a node exposes. +func (c *StatusController) Count(node string) int { + return len(c.nodes[node]) +} + func (c *StatusController) Reconcile(ctx context.Context, node string) error { _, err := c.getGPUStatus(DeviceInfo{}, node) return err diff --git a/demo/old_helper.rs b/demo/helper.rs similarity index 74% rename from demo/old_helper.rs rename to demo/helper.rs index 28f3f5e..41240a3 100644 --- a/demo/old_helper.rs +++ b/demo/helper.rs @@ -6,3 +6,7 @@ pub fn format_uuid(raw: &str) -> String { pub fn is_valid(uuid: &str) -> bool { uuid.len() == 36 && uuid.chars().filter(|c| *c == '-').count() == 4 } + +pub fn short(uuid: &str) -> &str { + uuid.split('-').next().unwrap_or(uuid) +} diff --git a/demo/legacy.rb b/demo/legacy.rb deleted file mode 100644 index bf52dda..0000000 --- a/demo/legacy.rb +++ /dev/null @@ -1,10 +0,0 @@ -# Legacy ruby reporter, superseded by the Go controller. -class Reporter - def initialize(nodes) - @nodes = nodes - end - - def report - @nodes.map { |n| "#{n}: ok" }.join("\n") - end -end diff --git a/demo/logo.png b/demo/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..67042d65457f3925c1605f7cdc5c1b90c38f64b6 GIT binary patch literal 4922 zcmb`LX;2eq7=ZI3fq)$0{NxOha9@ESlzMT5BP~QgdeDNQoK0&bptaH}A95%W+d=>Z zL2wX3oemSR<7nHFh=|Z)2-GQJ9YBZ#kU~lwX*-d0JN?_A@6PVG|8}1DnP>LfS!uE` z-rUsDlt!bO3ljLL)IIXwi(y2qSH(qBG@1<(@T1a>JhoGf85xvi(^SWli87Ah|IUe# z|BehEk9WOqQfR3$R<`TJufEo=7Z@_E-4iRlgJ(GjGWVnt{t;`o-l-jlRleJnLO&eu zNIDs~^KY{)A=x99KD>GVcYCuRoCw(d()qRG*^w&0@Rc1$)@C1^3?ggY<_P3bg>zVC z8(HSIwVz*Y%@&q(e8zK!Wb8f1-93IxyPSGaSm7D)_|U@m#nG~@?7_sQkQ`;Xhu<&z zANA&p9%p+gGj0~oDJ#5!rjGs@Mo<6{)N`z|hk?35kP8r$2CM8~pbitX69{S*t1t}I zOM*7RK&{STE>Kez1hIjj7BCm6sjmpK0fJIvE>KfKf_Oks%a{w)l#-y$Kv1(-4%Ad2 zL4H6`OIQxnR1ZN;Kv45o4%E~Eg0=%etzbD&Q!4}+13^8-5}>AB3GxDhTEr5drrHR? zKv2)H1gNQf1cd`Z{e~q#O-&JG2?RBVwLnenA}9z5>N(Z|HFcXH77&yMYk`_7C5SL# zzJfNMVy(u2!Q}9p7%ABUf?7`OIkWU)wNG*;pGU4dZ2mpI|rVWXw~;xET?zt>AEVKfuV_&XLQ4sB5RJI&NJqWbBU>~ zPfAyGqvNNJq2jTwn6s|OjLaN@^ZOed4%+*tU(3IH#^nnO=ZK>D{zj+ITz8cGK7V&T zs1y;OGFnu0rIhIr*J>z8?HsQ4h;K89eWT$@@};=*MoI5|yQsPp-;QG9PB(M&23zTG zzWvRlJnw$nrg&lNEy=UN^TvDj{qUFe)lVXY$iywOmid7@UuxwQC9@TW5i(m|K#;Ui(>_fTB{t-#OC0FJ2JbE!}d>J(09&^-EYg z0i>&MgRc7$NLL}H%MVD`uOh`Xl&%%5U5C;|)l~tci&cvB-axwUixj(|bS+}-D3C5f z)l~zeOGN4N1=2MkQn2Vuw}fi0RmVVey_?`vs6(%MXzzstX^7p`hnIi8AgBp*`R>I6 zFKehe*rscw>3Y`isclX-mLDCQ8ItmF&y$;f%na9rvu+a|UDpCM;xsj4Akc{GA_ZXp zy>F=PwH>GkJ*Dd`kgh&TR{)T%RgppurHk5Q`(Sj5HdvV!#f=%6Gv8DH#At$8A-^X& GtNb6_vs91( literal 0 HcmV?d00001 diff --git a/demo/server.py b/demo/server.py index 2c60903..cc992be 100644 --- a/demo/server.py +++ b/demo/server.py @@ -1,6 +1,6 @@ """A tiny async status server for the DRA controller.""" import asyncio -from dataclasses import dataclass +from dataclasses import dataclass, field @dataclass @@ -8,6 +8,7 @@ class Claim: name: str driver: str ready: bool = False + devices: list[str] = field(default_factory=list) class Server: @@ -18,5 +19,10 @@ async def add(self, claim: Claim) -> None: await asyncio.sleep(0) self.claims.append(claim) + async def ready(self, name: str) -> None: + for c in self.claims: + if c.name == name: + c.ready = True + def pending(self) -> list[Claim]: return [c for c in self.claims if not c.ready] diff --git a/demo/ui.tsx b/demo/ui.tsx new file mode 100644 index 0000000..ab43dc4 --- /dev/null +++ b/demo/ui.tsx @@ -0,0 +1,34 @@ +// Copyright 2026 Daniil Antoshin +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { createSignal, For } from "solid-js"; + +interface Device { + uuid: string; + status: "allocated" | "pending" | "shared"; +} + +export function DeviceList(props: { devices: Device[] }) { + const [filter, setFilter] = createSignal(""); + const shown = () => + props.devices.filter((d) => d.uuid.includes(filter())); + return ( +
+ setFilter(e.currentTarget.value)} /> +
    + {(d) =>
  • {d.uuid}
  • }
    +
+
+ ); +} From c5df26d17afd86281b4627d1af4f7a7f62455be3 Mon Sep 17 00:00:00 2001 From: Daniil Antoshin Date: Thu, 30 Jul 2026 10:12:41 +0200 Subject: [PATCH 2/2] demo: files for the highlight.js fallback (swift, dockerfile, sql) Signed-off-by: Daniil Antoshin --- demo/Dockerfile | 8 ++++++++ demo/metrics.swift | 16 ++++++++++++++++ demo/queries | 5 +++++ 3 files changed, 29 insertions(+) create mode 100644 demo/Dockerfile create mode 100644 demo/metrics.swift create mode 100644 demo/queries diff --git a/demo/Dockerfile b/demo/Dockerfile new file mode 100644 index 0000000..a4cd692 --- /dev/null +++ b/demo/Dockerfile @@ -0,0 +1,8 @@ +FROM golang:1.24 AS build +WORKDIR /src +COPY . . +RUN go build -o /out/inventory ./... + +FROM gcr.io/distroless/static +COPY --from=build /out/inventory /inventory +ENTRYPOINT ["/inventory"] diff --git a/demo/metrics.swift b/demo/metrics.swift new file mode 100644 index 0000000..c39c975 --- /dev/null +++ b/demo/metrics.swift @@ -0,0 +1,16 @@ +import Foundation + +struct GPUMetrics { + let uuid: String + let utilization: Double + let memoryUsed: UInt64 + + var isSaturated: Bool { + utilization > 0.9 + } +} + +func summarize(_ samples: [GPUMetrics]) -> String { + let busy = samples.filter { $0.isSaturated }.count + return "\(busy)/\(samples.count) GPUs saturated" +} diff --git a/demo/queries b/demo/queries new file mode 100644 index 0000000..9fb4963 --- /dev/null +++ b/demo/queries @@ -0,0 +1,5 @@ +SELECT node, COUNT(*) AS gpus, SUM(memory_gb) AS total_memory +FROM inventory +WHERE status = 'ready' +GROUP BY node +ORDER BY total_memory DESC;