Compare commits
No commits in common. "44001bb7e7708119d544c8f2ee094654ac23dcc2" and "3e29e04ac3266629f3d6578e6e72917235129c01" have entirely different histories.
44001bb7e7
...
3e29e04ac3
31 changed files with 59 additions and 1670 deletions
3
Makefile
3
Makefile
|
@ -17,9 +17,6 @@ build-server:
|
||||||
|
|
||||||
build: build-ui build-server
|
build: build-ui build-server
|
||||||
|
|
||||||
generate-apiclient:
|
|
||||||
openapi-generator generate -i openapi.yml -g typescript-axios -o ${UI_DIR}/src/sebrauc-client -p "supportsES6=true"
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f build/*
|
rm -f build/*
|
||||||
rm -rf ${UI_DIR}/dist/**
|
rm -rf ${UI_DIR}/dist/**
|
||||||
|
|
1
go.sum
1
go.sum
|
@ -19,7 +19,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/savsgio/gotils v0.0.0-20210921075833-21a6215cb0e4 h1:ocK/D6lCgLji37Z2so4xhMl46se1ntReQQCUIU4BWI8=
|
github.com/savsgio/gotils v0.0.0-20210921075833-21a6215cb0e4 h1:ocK/D6lCgLji37Z2so4xhMl46se1ntReQQCUIU4BWI8=
|
||||||
github.com/savsgio/gotils v0.0.0-20210921075833-21a6215cb0e4/go.mod h1:oejLrk1Y/5zOF+c/aHtXqn3TFlzzbAgPWg8zBiAHDas=
|
github.com/savsgio/gotils v0.0.0-20210921075833-21a6215cb0e4/go.mod h1:oejLrk1Y/5zOF+c/aHtXqn3TFlzzbAgPWg8zBiAHDas=
|
||||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
|
43
openapi.yml
43
openapi.yml
|
@ -118,10 +118,6 @@ components:
|
||||||
SystemInfo:
|
SystemInfo:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
hostname:
|
|
||||||
description: Hostname of the system
|
|
||||||
type: string
|
|
||||||
example: "raspberrypi3"
|
|
||||||
os_name:
|
os_name:
|
||||||
description: Name of the os distribution
|
description: Name of the os distribution
|
||||||
type: string
|
type: string
|
||||||
|
@ -142,21 +138,21 @@ components:
|
||||||
description: Compatible firmware variant
|
description: Compatible firmware variant
|
||||||
type: string
|
type: string
|
||||||
example: "rpi-prod"
|
example: "rpi-prod"
|
||||||
|
rauc_booted:
|
||||||
|
description: Currently booted rootfs
|
||||||
|
type: string
|
||||||
|
example: "rootfs.0"
|
||||||
|
rauc_boot_primary:
|
||||||
|
description: Primary rootfs to boot from
|
||||||
|
type: string
|
||||||
|
example: "rootfs.1"
|
||||||
rauc_rootfs:
|
rauc_rootfs:
|
||||||
description: List of RAUC root filesystems
|
description: List of RAUC root filesystems
|
||||||
type: object
|
type: object
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
$ref: "#/components/schemas/Rootfs"
|
$ref: "#/components/schemas/RaucFS"
|
||||||
required:
|
|
||||||
- hostname
|
|
||||||
- os_name
|
|
||||||
- os_version
|
|
||||||
- uptime
|
|
||||||
- rauc_compatible
|
|
||||||
- rauc_variant
|
|
||||||
- rauc_rootfs
|
|
||||||
|
|
||||||
Rootfs:
|
RaucFS:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
device:
|
device:
|
||||||
|
@ -167,6 +163,11 @@ components:
|
||||||
description: Filesystem
|
description: Filesystem
|
||||||
type: string
|
type: string
|
||||||
example: ext4
|
example: ext4
|
||||||
|
state:
|
||||||
|
description: Current state of filesystem
|
||||||
|
type: string
|
||||||
|
enum: [active, inactive, booted]
|
||||||
|
example: booted
|
||||||
mountpoint:
|
mountpoint:
|
||||||
description: Mount path (null when not mounted)
|
description: Mount path (null when not mounted)
|
||||||
type: string
|
type: string
|
||||||
|
@ -175,19 +176,6 @@ components:
|
||||||
bootable:
|
bootable:
|
||||||
description: "Is the filesystem bootable"
|
description: "Is the filesystem bootable"
|
||||||
type: boolean
|
type: boolean
|
||||||
booted:
|
|
||||||
description: "Is the filesystem booted"
|
|
||||||
type: boolean
|
|
||||||
primary:
|
|
||||||
description: "Is the filesystem the next boot target"
|
|
||||||
type: boolean
|
|
||||||
required:
|
|
||||||
- device
|
|
||||||
- type
|
|
||||||
- mountpoint
|
|
||||||
- bootable
|
|
||||||
- booted
|
|
||||||
- primary
|
|
||||||
|
|
||||||
StatusMessage:
|
StatusMessage:
|
||||||
type: object
|
type: object
|
||||||
|
@ -200,5 +188,4 @@ components:
|
||||||
type: string
|
type: string
|
||||||
example: Update started
|
example: Update started
|
||||||
required:
|
required:
|
||||||
- success
|
|
||||||
- msg
|
- msg
|
||||||
|
|
|
@ -41,34 +41,22 @@ LastError: Failed to check bundle identifier: Invalid identifier. ` +
|
||||||
idle
|
idle
|
||||||
Installing ` + "/app/demo` failed"
|
Installing ` + "/app/demo` failed"
|
||||||
|
|
||||||
const statusJson = `{"compatible":"TSGRain","variant":"dev","booted":"A",` +
|
|
||||||
`"boot_primary":"rootfs.0","slots":[{"rootfs.1":{"class":"rootfs",` +
|
|
||||||
`"device":"/dev/mmcblk0p3","type":"ext4","bootname":"B","state":"inactive",` +
|
|
||||||
`"parent":null,"mountpoint":null,"boot_status":"good"}},{"rootfs.0":` +
|
|
||||||
`{"class":"rootfs","device":"/dev/mmcblk0p2","type":"ext4","bootname":"A",` +
|
|
||||||
`"state":"booted","parent":null,"mountpoint":"/","boot_status":"good"}}]}`
|
|
||||||
|
|
||||||
func printLinesWithDelay(lines string) {
|
|
||||||
for _, line := range strings.Split(lines, "\n") {
|
|
||||||
fmt.Println(line)
|
|
||||||
time.Sleep(500 * time.Millisecond)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
arg := ""
|
arg := ""
|
||||||
if len(os.Args) > 1 {
|
if len(os.Args) > 1 {
|
||||||
arg = os.Args[1]
|
arg = os.Args[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var lines string
|
||||||
switch arg {
|
switch arg {
|
||||||
case "fail":
|
case "fail":
|
||||||
printLinesWithDelay(outputFailure)
|
lines = outputFailure
|
||||||
case "install":
|
|
||||||
printLinesWithDelay(outputSuccess)
|
|
||||||
case "status":
|
|
||||||
fmt.Println(statusJson)
|
|
||||||
default:
|
default:
|
||||||
os.Exit(1)
|
lines = outputSuccess
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, line := range strings.Split(lines, "\n") {
|
||||||
|
fmt.Println(line)
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
ID=tsgrain
|
|
||||||
NAME="TSGRain distro"
|
|
||||||
VERSION="0.0.1"
|
|
||||||
VERSION_ID=0.0.1
|
|
||||||
PRETTY_NAME="TSGRain distro 0.0.1"
|
|
|
@ -70,7 +70,7 @@ func (r *Rauc) RunRauc(updateFile string) error {
|
||||||
}
|
}
|
||||||
r.broadcast <- r.GetStatusJson()
|
r.broadcast <- r.GetStatusJson()
|
||||||
|
|
||||||
cmd := util.CommandFromString(fmt.Sprintf("%s install %s", util.RaucCmd, updateFile))
|
cmd := util.CommandFromString(fmt.Sprintf("%s %s", util.UpdateCmd, updateFile))
|
||||||
|
|
||||||
readPipe, _ := cmd.StdoutPipe()
|
readPipe, _ := cmd.StdoutPipe()
|
||||||
cmd.Stderr = cmd.Stdout
|
cmd.Stderr = cmd.Stdout
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.thetadev.de/TSGRain/SEBRAUC/src/rauc"
|
"code.thetadev.de/TSGRain/SEBRAUC/src/rauc"
|
||||||
"code.thetadev.de/TSGRain/SEBRAUC/src/sysinfo"
|
|
||||||
"code.thetadev.de/TSGRain/SEBRAUC/src/util"
|
"code.thetadev.de/TSGRain/SEBRAUC/src/util"
|
||||||
"code.thetadev.de/TSGRain/SEBRAUC/ui"
|
"code.thetadev.de/TSGRain/SEBRAUC/ui"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
@ -89,7 +88,6 @@ func (srv *SEBRAUCServer) Run() error {
|
||||||
app.Get("/api/ws", websocket.New(srv.hub.Handler))
|
app.Get("/api/ws", websocket.New(srv.hub.Handler))
|
||||||
app.Post("/api/update", srv.controllerUpdate)
|
app.Post("/api/update", srv.controllerUpdate)
|
||||||
app.Get("/api/status", srv.controllerStatus)
|
app.Get("/api/status", srv.controllerStatus)
|
||||||
app.Get("/api/info", srv.controllerInfo)
|
|
||||||
app.Post("/api/reboot", srv.controllerReboot)
|
app.Post("/api/reboot", srv.controllerReboot)
|
||||||
|
|
||||||
// Start messaging hub
|
// Start messaging hub
|
||||||
|
@ -133,17 +131,6 @@ func (srv *SEBRAUCServer) controllerStatus(c *fiber.Ctx) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *SEBRAUCServer) controllerInfo(c *fiber.Ctx) error {
|
|
||||||
info, err := sysinfo.GetSysinfo()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Context().SetStatusCode(200)
|
|
||||||
_ = c.JSON(info)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (srv *SEBRAUCServer) controllerReboot(c *fiber.Ctx) error {
|
func (srv *SEBRAUCServer) controllerReboot(c *fiber.Ctx) error {
|
||||||
go util.Reboot(5 * time.Second)
|
go util.Reboot(5 * time.Second)
|
||||||
|
|
||||||
|
|
|
@ -1,180 +0,0 @@
|
||||||
package sysinfo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"code.thetadev.de/TSGRain/SEBRAUC/src/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SystemInfo struct {
|
|
||||||
Hostname string `json:"hostname"`
|
|
||||||
OsName string `json:"os_name"`
|
|
||||||
OsVersion string `json:"os_version"`
|
|
||||||
Uptime int `json:"uptime"`
|
|
||||||
RaucCompatible string `json:"rauc_compatible"`
|
|
||||||
RaucVariant string `json:"rauc_variant"`
|
|
||||||
RaucRootfs map[string]Rootfs `json:"rauc_rootfs"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Rootfs struct {
|
|
||||||
Device string `json:"device"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
bootname string
|
|
||||||
Mountpoint *string `json:"mountpoint"`
|
|
||||||
Bootable bool `json:"bootable"`
|
|
||||||
Booted bool `json:"booted"`
|
|
||||||
Primary bool `json:"primary"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type raucInfo struct {
|
|
||||||
Compatible string `json:"compatible"`
|
|
||||||
Variant string `json:"variant"`
|
|
||||||
Booted string `json:"booted"`
|
|
||||||
BootPrimary string `json:"boot_primary"`
|
|
||||||
Slots []map[string]raucFS `json:"slots"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type raucFS struct {
|
|
||||||
Class string `json:"class"`
|
|
||||||
Device string `json:"device"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
Bootname string `json:"bootname"`
|
|
||||||
State string `json:"state"`
|
|
||||||
Mountpoint *string `json:"mountpoint"`
|
|
||||||
BootStatus string `json:"boot_status"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type osRelease struct {
|
|
||||||
OsName string `json:"os_name"`
|
|
||||||
OsVersion string `json:"os_version"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
rexpOsName = regexp.MustCompile(`(?m)^NAME="(.+)"`)
|
|
||||||
rexpOsVersion = regexp.MustCompile(`(?m)^VERSION="(.+)"`)
|
|
||||||
rexpUptime = regexp.MustCompile(`^\d+`)
|
|
||||||
)
|
|
||||||
|
|
||||||
func parseRaucInfo(raucInfoJson []byte) (raucInfo, error) {
|
|
||||||
res := raucInfo{}
|
|
||||||
err := json.Unmarshal(raucInfoJson, &res)
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseOsRelease(osReleaseFile string) (osRelease, error) {
|
|
||||||
osReleaseTxt, err := os.ReadFile(osReleaseFile)
|
|
||||||
if err != nil {
|
|
||||||
return osRelease{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
nameMatch := rexpOsName.FindSubmatch(osReleaseTxt)
|
|
||||||
versionMatch := rexpOsVersion.FindSubmatch(osReleaseTxt)
|
|
||||||
|
|
||||||
name := ""
|
|
||||||
if nameMatch != nil {
|
|
||||||
name = string(nameMatch[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
version := ""
|
|
||||||
if versionMatch != nil {
|
|
||||||
version = string(versionMatch[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
return osRelease{
|
|
||||||
OsName: name,
|
|
||||||
OsVersion: version,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func mapRootfs(rinf raucInfo) map[string]Rootfs {
|
|
||||||
res := make(map[string]Rootfs)
|
|
||||||
|
|
||||||
for _, slot := range rinf.Slots {
|
|
||||||
for name, fs := range slot {
|
|
||||||
if fs.Class == "rootfs" {
|
|
||||||
res[name] = Rootfs{
|
|
||||||
Device: fs.Device,
|
|
||||||
Type: fs.Type,
|
|
||||||
bootname: fs.Bootname,
|
|
||||||
Mountpoint: fs.Mountpoint,
|
|
||||||
Bootable: fs.BootStatus == "good",
|
|
||||||
Booted: fs.State == "booted",
|
|
||||||
Primary: rinf.BootPrimary == name,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func getFSNameFromBootname(rfslist map[string]Rootfs, bootname string) string {
|
|
||||||
for name, rfs := range rfslist {
|
|
||||||
if rfs.bootname == bootname {
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "n/a"
|
|
||||||
}
|
|
||||||
|
|
||||||
func mapSysinfo(rinf raucInfo, osr osRelease, uptime int, hostname string) SystemInfo {
|
|
||||||
rfslist := mapRootfs(rinf)
|
|
||||||
|
|
||||||
return SystemInfo{
|
|
||||||
Hostname: hostname,
|
|
||||||
OsName: osr.OsName,
|
|
||||||
OsVersion: osr.OsVersion,
|
|
||||||
Uptime: uptime,
|
|
||||||
RaucCompatible: rinf.Compatible,
|
|
||||||
RaucVariant: rinf.Variant,
|
|
||||||
RaucRootfs: rfslist,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUptime() (int, error) {
|
|
||||||
uptimeRaw, err := os.ReadFile("/proc/uptime")
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
uptimeChars := rexpUptime.Find(uptimeRaw)
|
|
||||||
return strconv.Atoi(string(uptimeChars))
|
|
||||||
}
|
|
||||||
|
|
||||||
func getHostname() string {
|
|
||||||
hostname, err := os.ReadFile("/etc/hostname")
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return strings.TrimSpace(string(hostname))
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetSysinfo() (SystemInfo, error) {
|
|
||||||
cmd := util.CommandFromString(util.RaucCmd + " status")
|
|
||||||
rinfJson, err := cmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
return SystemInfo{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
rinf, err := parseRaucInfo(rinfJson)
|
|
||||||
if err != nil {
|
|
||||||
return SystemInfo{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
osinf, err := parseOsRelease("/etc/os-release")
|
|
||||||
if err != nil {
|
|
||||||
return SystemInfo{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
uptime, err := getUptime()
|
|
||||||
if err != nil {
|
|
||||||
return SystemInfo{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
hostname := getHostname()
|
|
||||||
|
|
||||||
return mapSysinfo(rinf, osinf, uptime, hostname), nil
|
|
||||||
}
|
|
|
@ -1,122 +0,0 @@
|
||||||
package sysinfo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"code.thetadev.de/TSGRain/SEBRAUC/src/fixtures"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
const statusJson = `{"compatible":"TSGRain","variant":"dev","booted":"A",` +
|
|
||||||
`"boot_primary":"rootfs.0","slots":[{"rootfs.1":{"class":"rootfs",` +
|
|
||||||
`"device":"/dev/mmcblk0p3","type":"ext4","bootname":"B","state":"inactive",` +
|
|
||||||
`"parent":null,"mountpoint":null,"boot_status":"good"}},{"rootfs.0":` +
|
|
||||||
`{"class":"rootfs","device":"/dev/mmcblk0p2","type":"ext4","bootname":"A",` +
|
|
||||||
`"state":"booted","parent":null,"mountpoint":"/","boot_status":"good"}}]}`
|
|
||||||
|
|
||||||
var mountRoot = "/"
|
|
||||||
|
|
||||||
var expectedRaucInfo = raucInfo{
|
|
||||||
Compatible: "TSGRain",
|
|
||||||
Variant: "dev",
|
|
||||||
Booted: "A",
|
|
||||||
BootPrimary: "rootfs.0",
|
|
||||||
Slots: []map[string]raucFS{
|
|
||||||
{
|
|
||||||
"rootfs.1": {
|
|
||||||
Class: "rootfs",
|
|
||||||
Device: "/dev/mmcblk0p3",
|
|
||||||
Type: "ext4",
|
|
||||||
Bootname: "B",
|
|
||||||
State: "inactive",
|
|
||||||
Mountpoint: nil,
|
|
||||||
BootStatus: "good",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"rootfs.0": {
|
|
||||||
Class: "rootfs",
|
|
||||||
Device: "/dev/mmcblk0p2",
|
|
||||||
Type: "ext4",
|
|
||||||
Bootname: "A",
|
|
||||||
State: "booted",
|
|
||||||
Mountpoint: &mountRoot,
|
|
||||||
BootStatus: "good",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var expectedRootfsList = map[string]Rootfs{
|
|
||||||
"rootfs.0": {
|
|
||||||
Device: "/dev/mmcblk0p2",
|
|
||||||
Type: "ext4",
|
|
||||||
bootname: "A",
|
|
||||||
Mountpoint: &mountRoot,
|
|
||||||
Bootable: true,
|
|
||||||
Booted: true,
|
|
||||||
Primary: true,
|
|
||||||
},
|
|
||||||
"rootfs.1": {
|
|
||||||
Device: "/dev/mmcblk0p3",
|
|
||||||
Type: "ext4",
|
|
||||||
bootname: "B",
|
|
||||||
Mountpoint: nil,
|
|
||||||
Bootable: true,
|
|
||||||
Booted: false,
|
|
||||||
Primary: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseRaucInfo(t *testing.T) {
|
|
||||||
info, err := parseRaucInfo([]byte(statusJson))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.Equal(t, expectedRaucInfo, info)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseOsRelease(t *testing.T) {
|
|
||||||
testfiles := fixtures.GetTestfilesDir()
|
|
||||||
osReleaseFile := filepath.Join(testfiles, "os-release")
|
|
||||||
|
|
||||||
osRel, err := parseOsRelease(osReleaseFile)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
expected := osRelease{
|
|
||||||
OsName: "TSGRain distro",
|
|
||||||
OsVersion: "0.0.1",
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.Equal(t, expected, osRel)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMapRootfsList(t *testing.T) {
|
|
||||||
rootfsList := mapRootfs(expectedRaucInfo)
|
|
||||||
|
|
||||||
assert.Equal(t, expectedRootfsList, rootfsList)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetFSNameFromBootname(t *testing.T) {
|
|
||||||
rootfsList := mapRootfs(expectedRaucInfo)
|
|
||||||
|
|
||||||
assert.Equal(t, "rootfs.0", getFSNameFromBootname(rootfsList, "A"))
|
|
||||||
assert.Equal(t, "rootfs.1", getFSNameFromBootname(rootfsList, "B"))
|
|
||||||
assert.Equal(t, "n/a", getFSNameFromBootname(rootfsList, "C"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetSysinfo(t *testing.T) {
|
|
||||||
sysinfo, err := GetSysinfo()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.Greater(t, sysinfo.Uptime, 0)
|
|
||||||
assert.Equal(t, "TSGRain", sysinfo.RaucCompatible)
|
|
||||||
assert.Equal(t, "dev", sysinfo.RaucVariant)
|
|
||||||
assert.Equal(t, expectedRootfsList, sysinfo.RaucRootfs)
|
|
||||||
}
|
|
|
@ -5,7 +5,7 @@ package util
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RebootCmd = "shutdown -r 0"
|
RebootCmd = "shutdown -r 0"
|
||||||
RaucCmd = "rauc"
|
UpdateCmd = "rauc install"
|
||||||
|
|
||||||
TestMode = false
|
TestMode = false
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,7 +5,7 @@ package util
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RebootCmd = "touch /tmp/sebrauc_reboot_test"
|
RebootCmd = "touch /tmp/sebrauc_reboot_test"
|
||||||
RaucCmd = "go run code.thetadev.de/TSGRain/SEBRAUC/src/fixtures/rauc_mock"
|
UpdateCmd = "go run code.thetadev.de/TSGRain/SEBRAUC/src/fixtures/rauc_mock"
|
||||||
|
|
||||||
TestMode = true
|
TestMode = true
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import {Component} from "preact"
|
import {Component} from "preact"
|
||||||
import {mdiTriangleOutline} from "@mdi/js"
|
import {mdiTriangleOutline} from "@mdi/js"
|
||||||
import Icon from "../Icon/Icon"
|
import Icon from "../Icon/Icon"
|
||||||
import colors from "../../util/colors"
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
source?: string
|
source?: string
|
||||||
|
@ -21,7 +20,7 @@ export default class Alert extends Component<Props> {
|
||||||
return (
|
return (
|
||||||
<div class="alert">
|
<div class="alert">
|
||||||
<span>
|
<span>
|
||||||
<Icon icon={mdiTriangleOutline} color={colors.RED} />
|
<Icon icon={mdiTriangleOutline} color="#FF0039" />
|
||||||
{msg}
|
{msg}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import {mdiCheckCircleOutline, mdiRestore} from "@mdi/js"
|
import {mdiCheckCircleOutline, mdiRestore} from "@mdi/js"
|
||||||
|
import axios, {AxiosError, AxiosResponse} from "axios"
|
||||||
import {Component} from "preact"
|
import {Component} from "preact"
|
||||||
import {sebraucApi} from "../../util/apiUrls"
|
import {apiUrl} from "../../util/apiUrls"
|
||||||
import Icon from "../Icon/Icon"
|
import Icon from "../Icon/Icon"
|
||||||
|
|
||||||
export default class Reboot extends Component {
|
export default class Reboot extends Component {
|
||||||
|
@ -8,9 +9,9 @@ export default class Reboot extends Component {
|
||||||
const res = confirm("Reboot the system?")
|
const res = confirm("Reboot the system?")
|
||||||
if (!res) return
|
if (!res) return
|
||||||
|
|
||||||
sebraucApi
|
axios
|
||||||
.startReboot()
|
.post(apiUrl + "/reboot")
|
||||||
.then((response) => {
|
.then((response: AxiosResponse) => {
|
||||||
const msg = response.data.msg
|
const msg = response.data.msg
|
||||||
|
|
||||||
if (msg !== undefined) {
|
if (msg !== undefined) {
|
||||||
|
@ -19,7 +20,7 @@ export default class Reboot extends Component {
|
||||||
alert("No response")
|
alert("No response")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error: AxiosError) => {
|
||||||
if (error.response) {
|
if (error.response) {
|
||||||
const msg = error.response.data.msg
|
const msg = error.response.data.msg
|
||||||
|
|
||||||
|
|
|
@ -1,159 +0,0 @@
|
||||||
import {Component} from "preact"
|
|
||||||
import {SystemInfo} from "../../sebrauc-client"
|
|
||||||
import {sebraucApi} from "../../util/apiUrls"
|
|
||||||
import {secondsToString} from "../../util/functions"
|
|
||||||
import Icon from "../Icon/Icon"
|
|
||||||
import {
|
|
||||||
mdiAlphaVCircleOutline,
|
|
||||||
mdiCheckCircleOutline,
|
|
||||||
mdiCircleOutline,
|
|
||||||
mdiClockOutline,
|
|
||||||
mdiCloseCircleOutline,
|
|
||||||
mdiMonitor,
|
|
||||||
mdiPenguin,
|
|
||||||
mdiTagMultipleOutline,
|
|
||||||
mdiTagOutline,
|
|
||||||
} from "@mdi/js"
|
|
||||||
import colors from "../../util/colors"
|
|
||||||
|
|
||||||
type Props = {}
|
|
||||||
|
|
||||||
type State = {
|
|
||||||
sysinfo: SystemInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class SysinfoCard extends Component<Props, State> {
|
|
||||||
constructor(props?: Props | undefined, context?: any) {
|
|
||||||
super(props, context)
|
|
||||||
this.fetchInfo()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fetchInfo = () => {
|
|
||||||
sebraucApi
|
|
||||||
.getInfo()
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status == 200) {
|
|
||||||
this.setState({sysinfo: response.data})
|
|
||||||
} else {
|
|
||||||
console.log("error fetching info", response.data)
|
|
||||||
console.log("error fetching info", response.data)
|
|
||||||
window.setTimeout(this.fetchInfo, 3000)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((reason) => {
|
|
||||||
console.log("error fetching info", reason)
|
|
||||||
window.setTimeout(this.fetchInfo, 3000)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private renderSysinfo() {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div className="card">
|
|
||||||
<p class="top">System information</p>
|
|
||||||
<table class="table no-bottom-border">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Icon icon={mdiMonitor} /> Hostname
|
|
||||||
</td>
|
|
||||||
<td>{this.state.sysinfo.hostname}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Icon icon={mdiPenguin} /> Operating system
|
|
||||||
</td>
|
|
||||||
<td>{this.state.sysinfo.os_name}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Icon icon={mdiAlphaVCircleOutline} /> OS version
|
|
||||||
</td>
|
|
||||||
<td>{this.state.sysinfo.os_version}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Icon icon={mdiClockOutline} /> Uptime
|
|
||||||
</td>
|
|
||||||
<td>{secondsToString(this.state.sysinfo.uptime)}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Icon icon={mdiTagOutline} /> Compatible FW
|
|
||||||
</td>
|
|
||||||
<td>{this.state.sysinfo.rauc_compatible}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Icon icon={mdiTagMultipleOutline} /> Compatible FW
|
|
||||||
variant
|
|
||||||
</td>
|
|
||||||
<td>{this.state.sysinfo.rauc_variant}</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="card">
|
|
||||||
<p class="top">Rootfs slots</p>
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="table no-bottom-border">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th></th>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Device</th>
|
|
||||||
<th>Mountpoint</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{Object.keys(this.state.sysinfo.rauc_rootfs).map(
|
|
||||||
(k, i) => {
|
|
||||||
const rfs = this.state.sysinfo.rauc_rootfs[k]
|
|
||||||
let icon = mdiCircleOutline
|
|
||||||
let iconColor = colors.BLUE
|
|
||||||
|
|
||||||
if (!rfs.bootable) {
|
|
||||||
icon = mdiCloseCircleOutline
|
|
||||||
iconColor = colors.RED
|
|
||||||
} else if (rfs.primary) {
|
|
||||||
icon = mdiCheckCircleOutline
|
|
||||||
iconColor = colors.GREEN
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<tr key={i}>
|
|
||||||
<td>
|
|
||||||
<Icon
|
|
||||||
icon={icon}
|
|
||||||
color={iconColor}
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
<td>{k}</td>
|
|
||||||
<td>{rfs.device}</td>
|
|
||||||
<td>{rfs.mountpoint}</td>
|
|
||||||
</tr>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private renderLoadingAnimation() {
|
|
||||||
return (
|
|
||||||
<div className="card">
|
|
||||||
<p>loading sysinfo...</p>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
if (this.state.sysinfo) {
|
|
||||||
return this.renderSysinfo()
|
|
||||||
}
|
|
||||||
return this.renderLoadingAnimation()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +1,11 @@
|
||||||
.updater-view {
|
.uploader {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
max-width: 600px;
|
max-width: 500px;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
|
|
||||||
> * {
|
> * {
|
||||||
|
@ -18,8 +18,8 @@
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
margin-top: 25px;
|
padding: 15px 8px;
|
||||||
margin-bottom: 8px;
|
margin: 8px 0;
|
||||||
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
|
@ -29,14 +29,6 @@
|
||||||
.top {
|
.top {
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.pad {
|
|
||||||
padding: 15px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:first-of-type {
|
|
||||||
margin-top: 8px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert {
|
.alert {
|
||||||
|
@ -50,9 +42,3 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-top-right {
|
|
||||||
position: absolute;
|
|
||||||
top: 20px;
|
|
||||||
right: 20px;
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,10 +5,10 @@ import Dropzone from "../Dropzone/Dropzone"
|
||||||
import ProgressCircle from "../ProgressCircle/ProgressCircle"
|
import ProgressCircle from "../ProgressCircle/ProgressCircle"
|
||||||
import Icon from "../Icon/Icon"
|
import Icon from "../Icon/Icon"
|
||||||
import "./Updater.scss"
|
import "./Updater.scss"
|
||||||
|
import axios from "axios"
|
||||||
import Alert from "./Alert"
|
import Alert from "./Alert"
|
||||||
import Reboot from "./Reboot"
|
import Reboot from "./Reboot"
|
||||||
import {sebraucApi, wsUrl} from "../../util/apiUrls"
|
import {apiUrl, wsUrl} from "../../util/apiUrls"
|
||||||
import colors from "../../util/colors"
|
|
||||||
|
|
||||||
class UploadStatus {
|
class UploadStatus {
|
||||||
uploading = false
|
uploading = false
|
||||||
|
@ -50,7 +50,7 @@ type State = {
|
||||||
wsConnected: boolean
|
wsConnected: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class UpdaterCard extends Component<Props, State> {
|
export default class Updater extends Component<Props, State> {
|
||||||
private dropzoneRef = createRef<Dropzone>()
|
private dropzoneRef = createRef<Dropzone>()
|
||||||
private conn: WebSocket | undefined
|
private conn: WebSocket | undefined
|
||||||
|
|
||||||
|
@ -77,13 +77,19 @@ export default class UpdaterCard extends Component<Props, State> {
|
||||||
if (files.length === 0) return
|
if (files.length === 0) return
|
||||||
const newFile = files[0]
|
const newFile = files[0]
|
||||||
|
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append("updateFile", newFile)
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
uploadStatus: new UploadStatus(true, newFile.size, 0),
|
uploadStatus: new UploadStatus(true, newFile.size, 0),
|
||||||
uploadFilename: newFile.name,
|
uploadFilename: newFile.name,
|
||||||
})
|
})
|
||||||
|
|
||||||
sebraucApi
|
axios
|
||||||
.startUpdate(newFile, {
|
.post(apiUrl + "/update", formData, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "multipart/form-data",
|
||||||
|
},
|
||||||
onUploadProgress: (progressEvent: {loaded: number; total: number}) => {
|
onUploadProgress: (progressEvent: {loaded: number; total: number}) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
uploadStatus: UploadStatus.fromProgressEvent(progressEvent),
|
uploadStatus: UploadStatus.fromProgressEvent(progressEvent),
|
||||||
|
@ -126,6 +132,8 @@ export default class UpdaterCard extends Component<Props, State> {
|
||||||
JSON.parse(messages[i])
|
JSON.parse(messages[i])
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
console.log(this.state.raucStatus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -155,9 +163,9 @@ export default class UpdaterCard extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private circleColor(): string {
|
private circleColor(): string {
|
||||||
if (this.state.raucStatus.installing) return colors.RED
|
if (this.state.raucStatus.installing) return "#FF0039"
|
||||||
if (this.state.uploadStatus.uploading) return colors.GREEN
|
if (this.state.uploadStatus.uploading) return "#148420"
|
||||||
return colors.BLUE
|
return "#1f85de"
|
||||||
}
|
}
|
||||||
|
|
||||||
private circlePercentage(): number {
|
private circlePercentage(): number {
|
||||||
|
@ -187,13 +195,12 @@ export default class UpdaterCard extends Component<Props, State> {
|
||||||
topText = "Updating firmware"
|
topText = "Updating firmware"
|
||||||
bottomText = this.state.raucStatus.message
|
bottomText = this.state.raucStatus.message
|
||||||
} else {
|
} else {
|
||||||
topText = "Firmware update"
|
topText = "Upload firmware package"
|
||||||
bottomText = "Upload *.raucb FW package"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div class="uploader">
|
||||||
<div class="card pad">
|
<div class="card upload">
|
||||||
<div>
|
<div>
|
||||||
<p class="top">{topText}</p>
|
<p class="top">{topText}</p>
|
||||||
</div>
|
</div>
|
|
@ -1,48 +0,0 @@
|
||||||
import {mdiInformation, mdiUpload} from "@mdi/js"
|
|
||||||
import {Component} from "preact"
|
|
||||||
import Icon from "../Icon/Icon"
|
|
||||||
import SysinfoCard from "./SysinfoCard"
|
|
||||||
import UpdaterCard from "./UpdaterCard"
|
|
||||||
import "./Updater.scss"
|
|
||||||
|
|
||||||
type Props = {}
|
|
||||||
|
|
||||||
type State = {
|
|
||||||
flipped: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class UpdaterView extends Component<Props, State> {
|
|
||||||
constructor(props?: Props | undefined, context?: any) {
|
|
||||||
super(props, context)
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
flipped: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private flipCard = () => {
|
|
||||||
this.setState({flipped: !this.state.flipped})
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
class="iconButton button-top-right"
|
|
||||||
onClick={this.flipCard}
|
|
||||||
aria-label={
|
|
||||||
this.state.flipped
|
|
||||||
? "Switch to updater"
|
|
||||||
: "Switch to system info"
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Icon icon={this.state.flipped ? mdiUpload : mdiInformation} />
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div className="updater-view">
|
|
||||||
{!this.state.flipped ? <UpdaterCard /> : <SysinfoCard />}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {Component} from "preact"
|
import {Component} from "preact"
|
||||||
import UpdaterView from "./Updater/UpdaterView"
|
import Updater from "./Updater/Updater"
|
||||||
import logo from "../assets/logo.svg"
|
import logo from "../assets/logo.svg"
|
||||||
import {version} from "../util/version"
|
import {version} from "../util/version"
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ export default class App extends Component {
|
||||||
<div>
|
<div>
|
||||||
<img src={logo} alt="SEBRAUC" height="64" />
|
<img src={logo} alt="SEBRAUC" height="64" />
|
||||||
{version}
|
{version}
|
||||||
<UpdaterView />
|
<Updater />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
# OpenAPI Generator Ignore
|
|
||||||
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
|
|
||||||
|
|
||||||
# Use this file to prevent files from being overwritten by the generator.
|
|
||||||
# The patterns follow closely to .gitignore or .dockerignore.
|
|
||||||
|
|
||||||
# As an example, the C# client generator defines ApiClient.cs.
|
|
||||||
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
|
|
||||||
#ApiClient.cs
|
|
||||||
|
|
||||||
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
|
|
||||||
#foo/*/qux
|
|
||||||
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
|
|
||||||
|
|
||||||
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
|
|
||||||
#foo/**/qux
|
|
||||||
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
|
|
||||||
|
|
||||||
# You can also negate patterns with an exclamation (!).
|
|
||||||
# For example, you can ignore all files in a docs folder with the file extension .md:
|
|
||||||
#docs/*.md
|
|
||||||
# Then explicitly reverse the ignore rule for a single file:
|
|
||||||
#!docs/README.md
|
|
||||||
|
|
||||||
/.gitignore
|
|
||||||
/.npmignore
|
|
||||||
/git_push.sh
|
|
|
@ -1,5 +0,0 @@
|
||||||
api.ts
|
|
||||||
base.ts
|
|
||||||
common.ts
|
|
||||||
configuration.ts
|
|
||||||
index.ts
|
|
|
@ -1 +0,0 @@
|
||||||
5.3.0
|
|
|
@ -1,539 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* SEBRAUC
|
|
||||||
* REST API for the SEBRAUC firmware updater
|
|
||||||
*
|
|
||||||
* The version of the OpenAPI document: 0.1.0
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
||||||
* https://openapi-generator.tech
|
|
||||||
* Do not edit the class manually.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {Configuration} from "./configuration"
|
|
||||||
import globalAxios, {AxiosPromise, AxiosInstance, AxiosRequestConfig} from "axios"
|
|
||||||
// Some imports not used depending on template conditions
|
|
||||||
// @ts-ignore
|
|
||||||
import {
|
|
||||||
DUMMY_BASE_URL,
|
|
||||||
assertParamExists,
|
|
||||||
setApiKeyToObject,
|
|
||||||
setBasicAuthToObject,
|
|
||||||
setBearerAuthToObject,
|
|
||||||
setOAuthToObject,
|
|
||||||
setSearchParams,
|
|
||||||
serializeDataIfNeeded,
|
|
||||||
toPathString,
|
|
||||||
createRequestFunction,
|
|
||||||
} from "./common"
|
|
||||||
// @ts-ignore
|
|
||||||
import {
|
|
||||||
BASE_PATH,
|
|
||||||
COLLECTION_FORMATS,
|
|
||||||
RequestArgs,
|
|
||||||
BaseAPI,
|
|
||||||
RequiredError,
|
|
||||||
} from "./base"
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @interface RaucStatus
|
|
||||||
*/
|
|
||||||
export interface RaucStatus {
|
|
||||||
/**
|
|
||||||
* True if the installer is running
|
|
||||||
* @type {boolean}
|
|
||||||
* @memberof RaucStatus
|
|
||||||
*/
|
|
||||||
installing: boolean
|
|
||||||
/**
|
|
||||||
* Installation progress
|
|
||||||
* @type {number}
|
|
||||||
* @memberof RaucStatus
|
|
||||||
*/
|
|
||||||
percent: number
|
|
||||||
/**
|
|
||||||
* Current installation step
|
|
||||||
* @type {string}
|
|
||||||
* @memberof RaucStatus
|
|
||||||
*/
|
|
||||||
message: string
|
|
||||||
/**
|
|
||||||
* Installation error message
|
|
||||||
* @type {string}
|
|
||||||
* @memberof RaucStatus
|
|
||||||
*/
|
|
||||||
last_error: string
|
|
||||||
/**
|
|
||||||
* Full command line output of the current installation
|
|
||||||
* @type {string}
|
|
||||||
* @memberof RaucStatus
|
|
||||||
*/
|
|
||||||
log: string
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @interface Rootfs
|
|
||||||
*/
|
|
||||||
export interface Rootfs {
|
|
||||||
/**
|
|
||||||
* Block device
|
|
||||||
* @type {string}
|
|
||||||
* @memberof Rootfs
|
|
||||||
*/
|
|
||||||
device: string
|
|
||||||
/**
|
|
||||||
* Filesystem
|
|
||||||
* @type {string}
|
|
||||||
* @memberof Rootfs
|
|
||||||
*/
|
|
||||||
type: string
|
|
||||||
/**
|
|
||||||
* Mount path (null when not mounted)
|
|
||||||
* @type {string}
|
|
||||||
* @memberof Rootfs
|
|
||||||
*/
|
|
||||||
mountpoint: string | null
|
|
||||||
/**
|
|
||||||
* Is the filesystem bootable
|
|
||||||
* @type {boolean}
|
|
||||||
* @memberof Rootfs
|
|
||||||
*/
|
|
||||||
bootable: boolean
|
|
||||||
/**
|
|
||||||
* Is the filesystem booted
|
|
||||||
* @type {boolean}
|
|
||||||
* @memberof Rootfs
|
|
||||||
*/
|
|
||||||
booted: boolean
|
|
||||||
/**
|
|
||||||
* Is the filesystem the next boot target
|
|
||||||
* @type {boolean}
|
|
||||||
* @memberof Rootfs
|
|
||||||
*/
|
|
||||||
primary: boolean
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @interface StatusMessage
|
|
||||||
*/
|
|
||||||
export interface StatusMessage {
|
|
||||||
/**
|
|
||||||
* Is operation successful
|
|
||||||
* @type {boolean}
|
|
||||||
* @memberof StatusMessage
|
|
||||||
*/
|
|
||||||
success: boolean
|
|
||||||
/**
|
|
||||||
* Success message
|
|
||||||
* @type {string}
|
|
||||||
* @memberof StatusMessage
|
|
||||||
*/
|
|
||||||
msg: string
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @interface SystemInfo
|
|
||||||
*/
|
|
||||||
export interface SystemInfo {
|
|
||||||
/**
|
|
||||||
* Hostname of the system
|
|
||||||
* @type {string}
|
|
||||||
* @memberof SystemInfo
|
|
||||||
*/
|
|
||||||
hostname: string
|
|
||||||
/**
|
|
||||||
* Name of the os distribution
|
|
||||||
* @type {string}
|
|
||||||
* @memberof SystemInfo
|
|
||||||
*/
|
|
||||||
os_name: string
|
|
||||||
/**
|
|
||||||
* Operating system version
|
|
||||||
* @type {string}
|
|
||||||
* @memberof SystemInfo
|
|
||||||
*/
|
|
||||||
os_version: string
|
|
||||||
/**
|
|
||||||
* System uptime in seconds
|
|
||||||
* @type {number}
|
|
||||||
* @memberof SystemInfo
|
|
||||||
*/
|
|
||||||
uptime: number
|
|
||||||
/**
|
|
||||||
* Compatible firmware name
|
|
||||||
* @type {string}
|
|
||||||
* @memberof SystemInfo
|
|
||||||
*/
|
|
||||||
rauc_compatible: string
|
|
||||||
/**
|
|
||||||
* Compatible firmware variant
|
|
||||||
* @type {string}
|
|
||||||
* @memberof SystemInfo
|
|
||||||
*/
|
|
||||||
rauc_variant: string
|
|
||||||
/**
|
|
||||||
* List of RAUC root filesystems
|
|
||||||
* @type {{ [key: string]: Rootfs; }}
|
|
||||||
* @memberof SystemInfo
|
|
||||||
*/
|
|
||||||
rauc_rootfs: {[key: string]: Rootfs}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DefaultApi - axios parameter creator
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const DefaultApiAxiosParamCreator = function (configuration?: Configuration) {
|
|
||||||
return {
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {*} [options] Override http request option.
|
|
||||||
* @throws {RequiredError}
|
|
||||||
*/
|
|
||||||
getInfo: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
|
||||||
const localVarPath = `/info`
|
|
||||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
|
||||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL)
|
|
||||||
let baseOptions
|
|
||||||
if (configuration) {
|
|
||||||
baseOptions = configuration.baseOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
const localVarRequestOptions = {method: "GET", ...baseOptions, ...options}
|
|
||||||
const localVarHeaderParameter = {} as any
|
|
||||||
const localVarQueryParameter = {} as any
|
|
||||||
|
|
||||||
setSearchParams(localVarUrlObj, localVarQueryParameter)
|
|
||||||
let headersFromBaseOptions =
|
|
||||||
baseOptions && baseOptions.headers ? baseOptions.headers : {}
|
|
||||||
localVarRequestOptions.headers = {
|
|
||||||
...localVarHeaderParameter,
|
|
||||||
...headersFromBaseOptions,
|
|
||||||
...options.headers,
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
url: toPathString(localVarUrlObj),
|
|
||||||
options: localVarRequestOptions,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {*} [options] Override http request option.
|
|
||||||
* @throws {RequiredError}
|
|
||||||
*/
|
|
||||||
getStatus: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
|
||||||
const localVarPath = `/status`
|
|
||||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
|
||||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL)
|
|
||||||
let baseOptions
|
|
||||||
if (configuration) {
|
|
||||||
baseOptions = configuration.baseOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
const localVarRequestOptions = {method: "GET", ...baseOptions, ...options}
|
|
||||||
const localVarHeaderParameter = {} as any
|
|
||||||
const localVarQueryParameter = {} as any
|
|
||||||
|
|
||||||
setSearchParams(localVarUrlObj, localVarQueryParameter)
|
|
||||||
let headersFromBaseOptions =
|
|
||||||
baseOptions && baseOptions.headers ? baseOptions.headers : {}
|
|
||||||
localVarRequestOptions.headers = {
|
|
||||||
...localVarHeaderParameter,
|
|
||||||
...headersFromBaseOptions,
|
|
||||||
...options.headers,
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
url: toPathString(localVarUrlObj),
|
|
||||||
options: localVarRequestOptions,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {*} [options] Override http request option.
|
|
||||||
* @throws {RequiredError}
|
|
||||||
*/
|
|
||||||
startReboot: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
|
||||||
const localVarPath = `/reboot`
|
|
||||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
|
||||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL)
|
|
||||||
let baseOptions
|
|
||||||
if (configuration) {
|
|
||||||
baseOptions = configuration.baseOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
const localVarRequestOptions = {method: "POST", ...baseOptions, ...options}
|
|
||||||
const localVarHeaderParameter = {} as any
|
|
||||||
const localVarQueryParameter = {} as any
|
|
||||||
|
|
||||||
setSearchParams(localVarUrlObj, localVarQueryParameter)
|
|
||||||
let headersFromBaseOptions =
|
|
||||||
baseOptions && baseOptions.headers ? baseOptions.headers : {}
|
|
||||||
localVarRequestOptions.headers = {
|
|
||||||
...localVarHeaderParameter,
|
|
||||||
...headersFromBaseOptions,
|
|
||||||
...options.headers,
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
url: toPathString(localVarUrlObj),
|
|
||||||
options: localVarRequestOptions,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {any} [updateFile]
|
|
||||||
* @param {*} [options] Override http request option.
|
|
||||||
* @throws {RequiredError}
|
|
||||||
*/
|
|
||||||
startUpdate: async (
|
|
||||||
updateFile?: any,
|
|
||||||
options: AxiosRequestConfig = {}
|
|
||||||
): Promise<RequestArgs> => {
|
|
||||||
const localVarPath = `/update`
|
|
||||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
|
||||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL)
|
|
||||||
let baseOptions
|
|
||||||
if (configuration) {
|
|
||||||
baseOptions = configuration.baseOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
const localVarRequestOptions = {method: "POST", ...baseOptions, ...options}
|
|
||||||
const localVarHeaderParameter = {} as any
|
|
||||||
const localVarQueryParameter = {} as any
|
|
||||||
const localVarFormParams = new ((configuration &&
|
|
||||||
configuration.formDataCtor) ||
|
|
||||||
FormData)()
|
|
||||||
|
|
||||||
if (updateFile !== undefined) {
|
|
||||||
localVarFormParams.append("updateFile", updateFile as any)
|
|
||||||
}
|
|
||||||
|
|
||||||
localVarHeaderParameter["Content-Type"] = "multipart/form-data"
|
|
||||||
|
|
||||||
setSearchParams(localVarUrlObj, localVarQueryParameter)
|
|
||||||
let headersFromBaseOptions =
|
|
||||||
baseOptions && baseOptions.headers ? baseOptions.headers : {}
|
|
||||||
localVarRequestOptions.headers = {
|
|
||||||
...localVarHeaderParameter,
|
|
||||||
...headersFromBaseOptions,
|
|
||||||
...options.headers,
|
|
||||||
}
|
|
||||||
localVarRequestOptions.data = localVarFormParams
|
|
||||||
|
|
||||||
return {
|
|
||||||
url: toPathString(localVarUrlObj),
|
|
||||||
options: localVarRequestOptions,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DefaultApi - functional programming interface
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const DefaultApiFp = function (configuration?: Configuration) {
|
|
||||||
const localVarAxiosParamCreator = DefaultApiAxiosParamCreator(configuration)
|
|
||||||
return {
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {*} [options] Override http request option.
|
|
||||||
* @throws {RequiredError}
|
|
||||||
*/
|
|
||||||
async getInfo(
|
|
||||||
options?: AxiosRequestConfig
|
|
||||||
): Promise<
|
|
||||||
(axios?: AxiosInstance, basePath?: string) => AxiosPromise<SystemInfo>
|
|
||||||
> {
|
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.getInfo(options)
|
|
||||||
return createRequestFunction(
|
|
||||||
localVarAxiosArgs,
|
|
||||||
globalAxios,
|
|
||||||
BASE_PATH,
|
|
||||||
configuration
|
|
||||||
)
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {*} [options] Override http request option.
|
|
||||||
* @throws {RequiredError}
|
|
||||||
*/
|
|
||||||
async getStatus(
|
|
||||||
options?: AxiosRequestConfig
|
|
||||||
): Promise<
|
|
||||||
(axios?: AxiosInstance, basePath?: string) => AxiosPromise<RaucStatus>
|
|
||||||
> {
|
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.getStatus(options)
|
|
||||||
return createRequestFunction(
|
|
||||||
localVarAxiosArgs,
|
|
||||||
globalAxios,
|
|
||||||
BASE_PATH,
|
|
||||||
configuration
|
|
||||||
)
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {*} [options] Override http request option.
|
|
||||||
* @throws {RequiredError}
|
|
||||||
*/
|
|
||||||
async startReboot(
|
|
||||||
options?: AxiosRequestConfig
|
|
||||||
): Promise<
|
|
||||||
(axios?: AxiosInstance, basePath?: string) => AxiosPromise<StatusMessage>
|
|
||||||
> {
|
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.startReboot(
|
|
||||||
options
|
|
||||||
)
|
|
||||||
return createRequestFunction(
|
|
||||||
localVarAxiosArgs,
|
|
||||||
globalAxios,
|
|
||||||
BASE_PATH,
|
|
||||||
configuration
|
|
||||||
)
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {any} [updateFile]
|
|
||||||
* @param {*} [options] Override http request option.
|
|
||||||
* @throws {RequiredError}
|
|
||||||
*/
|
|
||||||
async startUpdate(
|
|
||||||
updateFile?: any,
|
|
||||||
options?: AxiosRequestConfig
|
|
||||||
): Promise<
|
|
||||||
(axios?: AxiosInstance, basePath?: string) => AxiosPromise<StatusMessage>
|
|
||||||
> {
|
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.startUpdate(
|
|
||||||
updateFile,
|
|
||||||
options
|
|
||||||
)
|
|
||||||
return createRequestFunction(
|
|
||||||
localVarAxiosArgs,
|
|
||||||
globalAxios,
|
|
||||||
BASE_PATH,
|
|
||||||
configuration
|
|
||||||
)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DefaultApi - factory interface
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const DefaultApiFactory = function (
|
|
||||||
configuration?: Configuration,
|
|
||||||
basePath?: string,
|
|
||||||
axios?: AxiosInstance
|
|
||||||
) {
|
|
||||||
const localVarFp = DefaultApiFp(configuration)
|
|
||||||
return {
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {*} [options] Override http request option.
|
|
||||||
* @throws {RequiredError}
|
|
||||||
*/
|
|
||||||
getInfo(options?: any): AxiosPromise<SystemInfo> {
|
|
||||||
return localVarFp
|
|
||||||
.getInfo(options)
|
|
||||||
.then((request) => request(axios, basePath))
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {*} [options] Override http request option.
|
|
||||||
* @throws {RequiredError}
|
|
||||||
*/
|
|
||||||
getStatus(options?: any): AxiosPromise<RaucStatus> {
|
|
||||||
return localVarFp
|
|
||||||
.getStatus(options)
|
|
||||||
.then((request) => request(axios, basePath))
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {*} [options] Override http request option.
|
|
||||||
* @throws {RequiredError}
|
|
||||||
*/
|
|
||||||
startReboot(options?: any): AxiosPromise<StatusMessage> {
|
|
||||||
return localVarFp
|
|
||||||
.startReboot(options)
|
|
||||||
.then((request) => request(axios, basePath))
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {any} [updateFile]
|
|
||||||
* @param {*} [options] Override http request option.
|
|
||||||
* @throws {RequiredError}
|
|
||||||
*/
|
|
||||||
startUpdate(updateFile?: any, options?: any): AxiosPromise<StatusMessage> {
|
|
||||||
return localVarFp
|
|
||||||
.startUpdate(updateFile, options)
|
|
||||||
.then((request) => request(axios, basePath))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DefaultApi - object-oriented interface
|
|
||||||
* @export
|
|
||||||
* @class DefaultApi
|
|
||||||
* @extends {BaseAPI}
|
|
||||||
*/
|
|
||||||
export class DefaultApi extends BaseAPI {
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {*} [options] Override http request option.
|
|
||||||
* @throws {RequiredError}
|
|
||||||
* @memberof DefaultApi
|
|
||||||
*/
|
|
||||||
public getInfo(options?: AxiosRequestConfig) {
|
|
||||||
return DefaultApiFp(this.configuration)
|
|
||||||
.getInfo(options)
|
|
||||||
.then((request) => request(this.axios, this.basePath))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {*} [options] Override http request option.
|
|
||||||
* @throws {RequiredError}
|
|
||||||
* @memberof DefaultApi
|
|
||||||
*/
|
|
||||||
public getStatus(options?: AxiosRequestConfig) {
|
|
||||||
return DefaultApiFp(this.configuration)
|
|
||||||
.getStatus(options)
|
|
||||||
.then((request) => request(this.axios, this.basePath))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {*} [options] Override http request option.
|
|
||||||
* @throws {RequiredError}
|
|
||||||
* @memberof DefaultApi
|
|
||||||
*/
|
|
||||||
public startReboot(options?: AxiosRequestConfig) {
|
|
||||||
return DefaultApiFp(this.configuration)
|
|
||||||
.startReboot(options)
|
|
||||||
.then((request) => request(this.axios, this.basePath))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {any} [updateFile]
|
|
||||||
* @param {*} [options] Override http request option.
|
|
||||||
* @throws {RequiredError}
|
|
||||||
* @memberof DefaultApi
|
|
||||||
*/
|
|
||||||
public startUpdate(updateFile?: any, options?: AxiosRequestConfig) {
|
|
||||||
return DefaultApiFp(this.configuration)
|
|
||||||
.startUpdate(updateFile, options)
|
|
||||||
.then((request) => request(this.axios, this.basePath))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* SEBRAUC
|
|
||||||
* REST API for the SEBRAUC firmware updater
|
|
||||||
*
|
|
||||||
* The version of the OpenAPI document: 0.1.0
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
||||||
* https://openapi-generator.tech
|
|
||||||
* Do not edit the class manually.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {Configuration} from "./configuration"
|
|
||||||
// Some imports not used depending on template conditions
|
|
||||||
// @ts-ignore
|
|
||||||
import globalAxios, {AxiosPromise, AxiosInstance, AxiosRequestConfig} from "axios"
|
|
||||||
|
|
||||||
export const BASE_PATH = "http://localhost:8080/api".replace(/\/+$/, "")
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const COLLECTION_FORMATS = {
|
|
||||||
csv: ",",
|
|
||||||
ssv: " ",
|
|
||||||
tsv: "\t",
|
|
||||||
pipes: "|",
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @interface RequestArgs
|
|
||||||
*/
|
|
||||||
export interface RequestArgs {
|
|
||||||
url: string
|
|
||||||
options: AxiosRequestConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @class BaseAPI
|
|
||||||
*/
|
|
||||||
export class BaseAPI {
|
|
||||||
protected configuration: Configuration | undefined
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
configuration?: Configuration,
|
|
||||||
protected basePath: string = BASE_PATH,
|
|
||||||
protected axios: AxiosInstance = globalAxios
|
|
||||||
) {
|
|
||||||
if (configuration) {
|
|
||||||
this.configuration = configuration
|
|
||||||
this.basePath = configuration.basePath || this.basePath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @class RequiredError
|
|
||||||
* @extends {Error}
|
|
||||||
*/
|
|
||||||
export class RequiredError extends Error {
|
|
||||||
name: "RequiredError" = "RequiredError"
|
|
||||||
constructor(public field: string, msg?: string) {
|
|
||||||
super(msg)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,181 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* SEBRAUC
|
|
||||||
* REST API for the SEBRAUC firmware updater
|
|
||||||
*
|
|
||||||
* The version of the OpenAPI document: 0.1.0
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
||||||
* https://openapi-generator.tech
|
|
||||||
* Do not edit the class manually.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {Configuration} from "./configuration"
|
|
||||||
import {RequiredError, RequestArgs} from "./base"
|
|
||||||
import {AxiosInstance, AxiosResponse} from "axios"
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const DUMMY_BASE_URL = "https://example.com"
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @throws {RequiredError}
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const assertParamExists = function (
|
|
||||||
functionName: string,
|
|
||||||
paramName: string,
|
|
||||||
paramValue: unknown
|
|
||||||
) {
|
|
||||||
if (paramValue === null || paramValue === undefined) {
|
|
||||||
throw new RequiredError(
|
|
||||||
paramName,
|
|
||||||
`Required parameter ${paramName} was null or undefined when calling ${functionName}.`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const setApiKeyToObject = async function (
|
|
||||||
object: any,
|
|
||||||
keyParamName: string,
|
|
||||||
configuration?: Configuration
|
|
||||||
) {
|
|
||||||
if (configuration && configuration.apiKey) {
|
|
||||||
const localVarApiKeyValue =
|
|
||||||
typeof configuration.apiKey === "function"
|
|
||||||
? await configuration.apiKey(keyParamName)
|
|
||||||
: await configuration.apiKey
|
|
||||||
object[keyParamName] = localVarApiKeyValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const setBasicAuthToObject = function (
|
|
||||||
object: any,
|
|
||||||
configuration?: Configuration
|
|
||||||
) {
|
|
||||||
if (configuration && (configuration.username || configuration.password)) {
|
|
||||||
object["auth"] = {
|
|
||||||
username: configuration.username,
|
|
||||||
password: configuration.password,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const setBearerAuthToObject = async function (
|
|
||||||
object: any,
|
|
||||||
configuration?: Configuration
|
|
||||||
) {
|
|
||||||
if (configuration && configuration.accessToken) {
|
|
||||||
const accessToken =
|
|
||||||
typeof configuration.accessToken === "function"
|
|
||||||
? await configuration.accessToken()
|
|
||||||
: await configuration.accessToken
|
|
||||||
object["Authorization"] = "Bearer " + accessToken
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const setOAuthToObject = async function (
|
|
||||||
object: any,
|
|
||||||
name: string,
|
|
||||||
scopes: string[],
|
|
||||||
configuration?: Configuration
|
|
||||||
) {
|
|
||||||
if (configuration && configuration.accessToken) {
|
|
||||||
const localVarAccessTokenValue =
|
|
||||||
typeof configuration.accessToken === "function"
|
|
||||||
? await configuration.accessToken(name, scopes)
|
|
||||||
: await configuration.accessToken
|
|
||||||
object["Authorization"] = "Bearer " + localVarAccessTokenValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const setSearchParams = function (url: URL, ...objects: any[]) {
|
|
||||||
const searchParams = new URLSearchParams(url.search)
|
|
||||||
for (const object of objects) {
|
|
||||||
for (const key in object) {
|
|
||||||
if (Array.isArray(object[key])) {
|
|
||||||
searchParams.delete(key)
|
|
||||||
for (const item of object[key]) {
|
|
||||||
searchParams.append(key, item)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
searchParams.set(key, object[key])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
url.search = searchParams.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const serializeDataIfNeeded = function (
|
|
||||||
value: any,
|
|
||||||
requestOptions: any,
|
|
||||||
configuration?: Configuration
|
|
||||||
) {
|
|
||||||
const nonString = typeof value !== "string"
|
|
||||||
const needsSerialization =
|
|
||||||
nonString && configuration && configuration.isJsonMime
|
|
||||||
? configuration.isJsonMime(requestOptions.headers["Content-Type"])
|
|
||||||
: nonString
|
|
||||||
return needsSerialization
|
|
||||||
? JSON.stringify(value !== undefined ? value : {})
|
|
||||||
: value || ""
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const toPathString = function (url: URL) {
|
|
||||||
return url.pathname + url.search + url.hash
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
*/
|
|
||||||
export const createRequestFunction = function (
|
|
||||||
axiosArgs: RequestArgs,
|
|
||||||
globalAxios: AxiosInstance,
|
|
||||||
BASE_PATH: string,
|
|
||||||
configuration?: Configuration
|
|
||||||
) {
|
|
||||||
return <T = unknown, R = AxiosResponse<T>>(
|
|
||||||
axios: AxiosInstance = globalAxios,
|
|
||||||
basePath: string = BASE_PATH
|
|
||||||
) => {
|
|
||||||
const axiosRequestArgs = {
|
|
||||||
...axiosArgs.options,
|
|
||||||
url: (configuration?.basePath || basePath) + axiosArgs.url,
|
|
||||||
}
|
|
||||||
return axios.request<T, R>(axiosRequestArgs)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,123 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* SEBRAUC
|
|
||||||
* REST API for the SEBRAUC firmware updater
|
|
||||||
*
|
|
||||||
* The version of the OpenAPI document: 0.1.0
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
||||||
* https://openapi-generator.tech
|
|
||||||
* Do not edit the class manually.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export interface ConfigurationParameters {
|
|
||||||
apiKey?:
|
|
||||||
| string
|
|
||||||
| Promise<string>
|
|
||||||
| ((name: string) => string)
|
|
||||||
| ((name: string) => Promise<string>)
|
|
||||||
username?: string
|
|
||||||
password?: string
|
|
||||||
accessToken?:
|
|
||||||
| string
|
|
||||||
| Promise<string>
|
|
||||||
| ((name?: string, scopes?: string[]) => string)
|
|
||||||
| ((name?: string, scopes?: string[]) => Promise<string>)
|
|
||||||
basePath?: string
|
|
||||||
baseOptions?: any
|
|
||||||
formDataCtor?: new () => any
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Configuration {
|
|
||||||
/**
|
|
||||||
* parameter for apiKey security
|
|
||||||
* @param name security name
|
|
||||||
* @memberof Configuration
|
|
||||||
*/
|
|
||||||
apiKey?:
|
|
||||||
| string
|
|
||||||
| Promise<string>
|
|
||||||
| ((name: string) => string)
|
|
||||||
| ((name: string) => Promise<string>)
|
|
||||||
/**
|
|
||||||
* parameter for basic security
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof Configuration
|
|
||||||
*/
|
|
||||||
username?: string
|
|
||||||
/**
|
|
||||||
* parameter for basic security
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof Configuration
|
|
||||||
*/
|
|
||||||
password?: string
|
|
||||||
/**
|
|
||||||
* parameter for oauth2 security
|
|
||||||
* @param name security name
|
|
||||||
* @param scopes oauth2 scope
|
|
||||||
* @memberof Configuration
|
|
||||||
*/
|
|
||||||
accessToken?:
|
|
||||||
| string
|
|
||||||
| Promise<string>
|
|
||||||
| ((name?: string, scopes?: string[]) => string)
|
|
||||||
| ((name?: string, scopes?: string[]) => Promise<string>)
|
|
||||||
/**
|
|
||||||
* override base path
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
* @memberof Configuration
|
|
||||||
*/
|
|
||||||
basePath?: string
|
|
||||||
/**
|
|
||||||
* base options for axios calls
|
|
||||||
*
|
|
||||||
* @type {any}
|
|
||||||
* @memberof Configuration
|
|
||||||
*/
|
|
||||||
baseOptions?: any
|
|
||||||
/**
|
|
||||||
* The FormData constructor that will be used to create multipart form data
|
|
||||||
* requests. You can inject this here so that execution environments that
|
|
||||||
* do not support the FormData class can still run the generated client.
|
|
||||||
*
|
|
||||||
* @type {new () => FormData}
|
|
||||||
*/
|
|
||||||
formDataCtor?: new () => any
|
|
||||||
|
|
||||||
constructor(param: ConfigurationParameters = {}) {
|
|
||||||
this.apiKey = param.apiKey
|
|
||||||
this.username = param.username
|
|
||||||
this.password = param.password
|
|
||||||
this.accessToken = param.accessToken
|
|
||||||
this.basePath = param.basePath
|
|
||||||
this.baseOptions = param.baseOptions
|
|
||||||
this.formDataCtor = param.formDataCtor
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the given MIME is a JSON MIME.
|
|
||||||
* JSON MIME examples:
|
|
||||||
* application/json
|
|
||||||
* application/json; charset=UTF8
|
|
||||||
* APPLICATION/JSON
|
|
||||||
* application/vnd.company+json
|
|
||||||
* @param mime - MIME (Multipurpose Internet Mail Extensions)
|
|
||||||
* @return True if the given MIME is JSON, false otherwise.
|
|
||||||
*/
|
|
||||||
public isJsonMime(mime: string): boolean {
|
|
||||||
const jsonMime: RegExp = new RegExp(
|
|
||||||
"^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$",
|
|
||||||
"i"
|
|
||||||
)
|
|
||||||
return (
|
|
||||||
mime !== null &&
|
|
||||||
(jsonMime.test(mime) ||
|
|
||||||
mime.toLowerCase() === "application/json-patch+json")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
/**
|
|
||||||
* SEBRAUC
|
|
||||||
* REST API for the SEBRAUC firmware updater
|
|
||||||
*
|
|
||||||
* The version of the OpenAPI document: 0.1.0
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
||||||
* https://openapi-generator.tech
|
|
||||||
* Do not edit the class manually.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export * from "./api"
|
|
||||||
export * from "./configuration"
|
|
|
@ -1,5 +1,3 @@
|
||||||
@use "table";
|
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
.table-wrapper {
|
|
||||||
width: 100%;
|
|
||||||
overflow-x: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table {
|
|
||||||
border-top: 1px solid #ccc;
|
|
||||||
border-bottom: 1px solid #ccc;
|
|
||||||
border-collapse: collapse;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
&.no-bottom-border {
|
|
||||||
&,
|
|
||||||
> tr:last-child,
|
|
||||||
:not(thead) tr:last-child {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table caption {
|
|
||||||
font-size: 1.5em;
|
|
||||||
margin: 0.5em 0 0.75em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table tr {
|
|
||||||
border-bottom: 1px solid #ddd;
|
|
||||||
padding: 0.35em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table th,
|
|
||||||
.table td {
|
|
||||||
padding: 0.625em;
|
|
||||||
text-align: left;
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
color: #1f85de;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table th {
|
|
||||||
font-size: 0.85em;
|
|
||||||
letter-spacing: 0.085em;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
|
@ -1,5 +1,3 @@
|
||||||
import {Configuration, DefaultApi} from "../sebrauc-client"
|
|
||||||
|
|
||||||
let apiHost = document.location.host
|
let apiHost = document.location.host
|
||||||
const httpProto = document.location.protocol
|
const httpProto = document.location.protocol
|
||||||
const wsProto = httpProto === "https:" ? "wss:" : "ws:"
|
const wsProto = httpProto === "https:" ? "wss:" : "ws:"
|
||||||
|
@ -11,10 +9,4 @@ if (import.meta.env.VITE_API_HOST !== undefined) {
|
||||||
const apiUrl = `${httpProto}//${apiHost}/api`
|
const apiUrl = `${httpProto}//${apiHost}/api`
|
||||||
const wsUrl = `${wsProto}//${apiHost}/api/ws`
|
const wsUrl = `${wsProto}//${apiHost}/api/ws`
|
||||||
|
|
||||||
let apicfg = new Configuration({
|
export {apiUrl, wsUrl}
|
||||||
basePath: apiUrl,
|
|
||||||
})
|
|
||||||
|
|
||||||
const sebraucApi = new DefaultApi(apicfg)
|
|
||||||
|
|
||||||
export {apiUrl, wsUrl, sebraucApi}
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
class colors {
|
|
||||||
static readonly RED = "#FF0039"
|
|
||||||
static readonly GREEN = "#148420"
|
|
||||||
static readonly BLUE = "#1f85de"
|
|
||||||
}
|
|
||||||
|
|
||||||
export default colors
|
|
|
@ -1,18 +0,0 @@
|
||||||
function secondsToString(seconds: number): string {
|
|
||||||
const numyears = Math.floor(seconds / 31536000)
|
|
||||||
const numdays = Math.floor((seconds % 31536000) / 86400)
|
|
||||||
const numhours = Math.floor(((seconds % 31536000) % 86400) / 3600)
|
|
||||||
const numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60)
|
|
||||||
const numseconds = (((seconds % 31536000) % 86400) % 3600) % 60
|
|
||||||
|
|
||||||
let res = []
|
|
||||||
if (numyears > 0) res.push(numyears + "yr")
|
|
||||||
if (numdays > 0) res.push(numdays + "d")
|
|
||||||
if (numhours > 0) res.push(numhours + "h")
|
|
||||||
if (numminutes > 0) res.push(numminutes + "m")
|
|
||||||
if (seconds < 60) res.push(numseconds + "s")
|
|
||||||
|
|
||||||
return res.join(" ")
|
|
||||||
}
|
|
||||||
|
|
||||||
export {secondsToString}
|
|
Loading…
Reference in a new issue