mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 01:13:00 +02:00
webui: fix more wrappers decoding keyed GETs as bare nodes
Three more RESTCONF wrappers assume the response to a keyed GET is the bare node, when the server nests it under the full parent path: the container resource-usage stats always read zero, the WireGuard listen port never populated, and resetting advertised link modes silently re-enabled auto-negotiation on links where it was forced off. Same class of bug as the firewall zone reset fix: the decode matches nothing and the zero value is used as if valid. Model the full nesting in all three wrappers, reusing the existing container list wrapper. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
@@ -1369,15 +1369,22 @@ func (h *ConfigureInterfacesHandler) ResetEthernetAdvertised(w http.ResponseWrit
|
||||
name := r.PathValue("name")
|
||||
base := ifacePath(name) + "/ieee802-ethernet-interface:ethernet"
|
||||
|
||||
// Keyed GETs nest the requested node under its full parent path.
|
||||
var resp struct {
|
||||
AN struct {
|
||||
Enable *bool `json:"enable"`
|
||||
} `json:"ieee802-ethernet-interface:auto-negotiation"`
|
||||
Interfaces struct {
|
||||
Interface []struct {
|
||||
Ethernet struct {
|
||||
AN struct {
|
||||
Enable *bool `json:"enable"`
|
||||
} `json:"auto-negotiation"`
|
||||
} `json:"ieee802-ethernet-interface:ethernet"`
|
||||
} `json:"interface"`
|
||||
} `json:"ietf-interfaces:interfaces"`
|
||||
}
|
||||
enable := true // YANG default
|
||||
if err := h.RC.Get(r.Context(), base+"/auto-negotiation", &resp); err == nil {
|
||||
if resp.AN.Enable != nil {
|
||||
enable = *resp.AN.Enable
|
||||
if ifs := resp.Interfaces.Interface; len(ifs) > 0 && ifs[0].Ethernet.AN.Enable != nil {
|
||||
enable = *ifs[0].Ethernet.AN.Enable
|
||||
}
|
||||
} else if !restconf.IsNotFound(err) {
|
||||
log.Printf("configure interfaces %s reset advertised get: %v", name, err)
|
||||
|
||||
@@ -46,11 +46,6 @@ type containerListWrapper struct {
|
||||
} `json:"infix-containers:containers"`
|
||||
}
|
||||
|
||||
// containerResourceUsageWrapper wraps the RESTCONF resource-usage response.
|
||||
type containerResourceUsageWrapper struct {
|
||||
ResourceUsage containerResourceUsageJSON `json:"infix-containers:resource-usage"`
|
||||
}
|
||||
|
||||
// ContainerEntry holds display-ready data for a single container row.
|
||||
type ContainerEntry struct {
|
||||
Name string
|
||||
@@ -106,13 +101,16 @@ func (h *ContainersHandler) Overview(w http.ResponseWriter, r *http.Request) {
|
||||
defer wg.Done()
|
||||
path := fmt.Sprintf("/data/infix-containers:containers/container=%s/resource-usage",
|
||||
url.PathEscape(name))
|
||||
var w containerResourceUsageWrapper
|
||||
var w containerListWrapper // keyed GETs nest under the full parent path
|
||||
if err := h.RC.Get(ctx, path, &w); err != nil {
|
||||
log.Printf("restconf resource-usage %s: %v", name, err)
|
||||
return
|
||||
}
|
||||
if len(w.Containers.Container) == 0 {
|
||||
return
|
||||
}
|
||||
mu.Lock()
|
||||
usages[idx] = w.ResourceUsage
|
||||
usages[idx] = w.Containers.Container[0].ResourceUsage
|
||||
mu.Unlock()
|
||||
}(i, c.Name)
|
||||
}
|
||||
|
||||
@@ -21,8 +21,13 @@ type wgConfigJSON struct {
|
||||
}
|
||||
|
||||
// wgIfaceConfigWrapper is used to fetch per-interface WireGuard config.
|
||||
// Keyed GETs nest the requested node under its full parent path.
|
||||
type wgIfaceConfigWrapper struct {
|
||||
WireGuard *wgConfigJSON `json:"infix-interfaces:wireguard"`
|
||||
Interfaces struct {
|
||||
Interface []struct {
|
||||
WireGuard *wgConfigJSON `json:"infix-interfaces:wireguard"`
|
||||
} `json:"interface"`
|
||||
} `json:"ietf-interfaces:interfaces"`
|
||||
}
|
||||
|
||||
// WGPeer holds display-ready data for a single WireGuard peer.
|
||||
@@ -128,8 +133,9 @@ func buildWGTunnel(ctx context.Context, rc *restconf.Client, iface ifaceJSON) WG
|
||||
// Fetch ListenPort from config endpoint (separate from oper-state).
|
||||
var cfgWrap wgIfaceConfigWrapper
|
||||
path := fmt.Sprintf("/data/ietf-interfaces:interfaces/interface=%s/infix-interfaces:wireguard", iface.Name)
|
||||
if err := rc.Get(ctx, path, &cfgWrap); err == nil && cfgWrap.WireGuard != nil {
|
||||
tunnel.ListenPort = cfgWrap.WireGuard.ListenPort
|
||||
if err := rc.Get(ctx, path, &cfgWrap); err == nil &&
|
||||
len(cfgWrap.Interfaces.Interface) > 0 && cfgWrap.Interfaces.Interface[0].WireGuard != nil {
|
||||
tunnel.ListenPort = cfgWrap.Interfaces.Interface[0].WireGuard.ListenPort
|
||||
}
|
||||
|
||||
// Build peers from embedded peer-status.
|
||||
|
||||
Reference in New Issue
Block a user