Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework device subcommand and client APIs to support lookup by UUID #414

Merged
merged 27 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ef4a8cd
client: Split out functions to for device
doanac Jun 4, 2024
851ac90
client: Start moving to a "DeviceApi"
doanac Jun 4, 2024
ad2bc10
client: Use DeviceApi for rename operation
doanac Jun 4, 2024
dc0a726
client: Use DeviceApi for group configuration
doanac Jun 4, 2024
e30ebc1
client: Use DeviceAPI for Delete operation
doanac Jun 4, 2024
00c8d91
client: Move to DeviceApi for delete-denied
doanac Jun 4, 2024
c4d3617
client: Move to DeviceApi for updates
doanac Jun 4, 2024
09122e6
client: Move to DeviceApi for update events
doanac Jun 4, 2024
f2c90bf
client: Move to DeviceApi for apps-states
doanac Jun 4, 2024
a9b4e34
client: Use DeviceApi for config operations
doanac Jun 4, 2024
4a734d9
device: Remove deprecated `updates_list`
doanac Jun 6, 2024
7a3d9c0
device: Include name in `show` command
doanac Jun 6, 2024
351b78b
Introduce foundation for consistent device look ups
doanac Jun 6, 2024
c004e4a
devices: Move `show` to use getDevice API
doanac Jun 6, 2024
ad4d697
device: Move `updates` to getDeviceApi
doanac Jun 6, 2024
6e38426
device: Update `rename` to use getDeviceApi
doanac Jun 6, 2024
cc76a97
device: Update `delete` to use getDeviceApi
doanac Jun 6, 2024
a2724b1
device: Update `chown` to use getDeviceApi
doanac Jun 6, 2024
5707a61
device: Update `apps-states` to use getDeviceApi
doanac Jun 6, 2024
8a82460
device: Update `config delete` to use getDeviceApi
doanac Jun 6, 2024
323591d
device: Update `config group` to use getDeviceApi
doanac Jun 6, 2024
11983e5
device: Update `config log` to use getDeviceApi
doanac Jun 6, 2024
0998598
device: Update `config rotate-certs` to use getDeviceApi
doanac Jun 6, 2024
c5e2546
device: Update `config set` to use getDevice
doanac Jun 6, 2024
d79811f
device: Update `config updates` to use getDevice
doanac Jun 6, 2024
2645c52
device: Update `config wireguard` to use getDeviceApi
doanac Jun 6, 2024
89be418
device: Add `--by-uuid` support to all subcommands
doanac Jun 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
356 changes: 0 additions & 356 deletions client/foundries.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"fmt"
"io"
"net/http"
netUrl "net/url"
"os"
"strconv"
"strings"
Expand Down Expand Up @@ -48,56 +47,6 @@ type ConfigCreateRequest struct {
Files []ConfigFile `json:"files"`
}

type DeviceConfig struct {
CreatedAt string `json:"created-at"`
AppliedAt string `json:"applied-at"` // This is not present in factory config
CreatedBy string `json:"created-by"`
Reason string `json:"reason"`
Files []ConfigFile `json:"files"`
}

type DeviceConfigList struct {
Configs []DeviceConfig `json:"config"`
Total int `json:"total"`
Next *string `json:"next"`
}

type NetInfo struct {
Hostname string `json:"hostname"`
Ipv4 string `json:"local_ipv4"`
MAC string `json:"mac"`
}

type Update struct {
CorrelationId string `json:"correlation-id"`
Target string `json:"target"`
Version string `json:"version"`
Time string `json:"time"`
}

type UpdateList struct {
Updates []Update `json:"updates"`
Total int `json:"total"`
Next *string `json:"next"`
}

type EventType struct {
Id string `json:"id"`
}

type EventDetail struct {
Version string `json:"version"`
TargetName string `json:"targetName"`
Success *bool `json:"success,omitempty"`
Details string `json:"details"`
}

type UpdateEvent struct {
Time string `json:"deviceTime"`
Type EventType `json:"eventType"`
Detail EventDetail `json:"event"`
}

type ChangeMeta struct {
CreatedBy string `json:"created-by"`
CreatedAt string `json:"created-at"`
Expand All @@ -113,90 +62,6 @@ type DeviceGroup struct {
ChangeMeta ChangeMeta `json:"change-meta"`
}

type AppServiceState struct {
Name string `json:"name"`
Hash string `json:"hash"`
State string `json:"state"`
Status string `json:"status"`
Health string `json:"health"`
ImageUri string `json:"image"`
Logs string `json:"logs"`
}

type AppState struct {
Services []AppServiceState `json:"services"`
State string `json:"state"`
Uri string `json:"uri"`
}

type AppsState struct {
Ostree string `json:"ostree"`
DeviceTime string `json:"deviceTime"`
Apps map[string]AppState `json:"apps,omitempty"`
}

type AppsStates struct {
States []AppsState `json:"apps-states"`
}

type Device struct {
Uuid string `json:"uuid"`
Name string `json:"name"`
Owner string `json:"owner"`
Factory string `json:"factory"`
GroupName string `json:"device-group"` // Returned in List API
Group *DeviceGroup `json:"group"` // Returned in Get API
LastSeen string `json:"last-seen"`
OstreeHash string `json:"ostree-hash"`
LmpVer string `json:"lmp-ver,omitempty"`
DockerApps []string `json:"docker-apps,omitempty"`
Tag string `json:"tag,omitempty"`
Network *NetInfo `json:"network-info,omitempty"`
Hardware *json.RawMessage `json:"hardware-info,omitempty"`
TargetName string `json:"target-name"`
Status string `json:"status"`
CurrentUpdate string `json:"current-update"`
UpToDate bool `json:"up-to-date"`
PublicKey string `json:"public-key"`
ActiveConfig *DeviceConfig `json:"active-config,omitempty"`
AktualizrToml string `json:"aktualizr-toml,omitempty"`
IsProd bool `json:"is-prod"`
IsWave bool `json:"is-wave"`
ChangeMeta ChangeMeta `json:"change-meta"`
Secondaries []struct {
Serial string `json:"serial"`
TargetName string `json:"target-name"`
HardwareId string `json:"hardware-id"`
} `json:"secondary-ecus"`
AppsState *AppsState `json:"apps-state,omitempty"`
}

type DeviceList struct {
Devices []Device `json:"devices"`
Total int `json:"total"`
Next *string `json:"next"`
}

type DockerApp struct {
FileName string `json:"filename"`
Uri string `json:"uri"`
}

type ComposeApp struct {
Uri string `json:"uri"`
}

func (a ComposeApp) Hash() string {
parts := strings.SplitN(a.Uri, "@sha256:", 2)
return parts[len(parts)-1]
}

func (a ComposeApp) Name() string {
parts := strings.SplitN(a.Uri, "@sha256:", 2)
nameStartIndx := strings.LastIndexByte(parts[0], '/')
return parts[0][nameStartIndx+1:]
}

type JobservBuild struct {
ID int `json:"build_id"`
}
Expand Down Expand Up @@ -483,23 +348,6 @@ func AsHttpError(err error) *HttpError {
}
}

func (d Device) Online(inactiveHoursThreshold int) bool {
if len(d.LastSeen) == 0 {
return false
}
t, err := time.Parse(time.RFC3339, d.LastSeen)
if err == nil {
duration := time.Since(t)
if duration.Hours() > float64(inactiveHoursThreshold) {
return false
}
} else {
logrus.Error(err)
return false
}
return true
}

func NewApiClient(serverUrl string, config Config, caCertPath string, version string) *Api {
tlsCfg := &tls.Config{
InsecureSkipVerify: config.InsecureSkipVerify,
Expand Down Expand Up @@ -767,210 +615,6 @@ func (a *Api) Delete(url string, data []byte) (*[]byte, error) {
}
}

func (a *Api) DeviceGet(factory, device string) (*Device, error) {
url := a.serverUrl + "/ota/devices/" + device + "/?factory=" + factory
body, err := a.Get(url)
if err != nil {
return nil, err
}
d := Device{}
err = json.Unmarshal(*body, &d)
if err != nil {
return nil, err
}
return &d, nil
}

func (a *Api) DeviceList(filterBy map[string]string, sortBy string, page, limit uint64) (*DeviceList, error) {
url := a.serverUrl + "/ota/devices/?"
query := netUrl.Values{}
for key, val := range filterBy {
if len(val) > 0 {
query.Set(key, val)
}
}
if len(sortBy) > 0 {
query.Set("sortby", sortBy)
}
if page > 1 {
query.Set("page", strconv.FormatUint(page, 10))
}
query.Set("limit", strconv.FormatUint(limit, 10))
url += query.Encode()
logrus.Debugf("DeviceList with url: %s", url)
return a.DeviceListCont(url)
}

func (a *Api) DeviceListCont(url string) (*DeviceList, error) {
logrus.Debugf("DeviceListCont with url: %s", url)
body, err := a.Get(url)
if err != nil {
return nil, err
}

devices := DeviceList{}
err = json.Unmarshal(*body, &devices)
if err != nil {
return nil, err
}
return &devices, nil
}

func (a *Api) DeviceListDenied(factory string, page, limit uint64) (*DeviceList, error) {
url := a.serverUrl + "/ota/factories/" + factory + "/denied-devices/"
url += fmt.Sprintf("?limit=%d&page=%d", limit, page)
return a.DeviceListCont(url)
}

func (a *Api) DeviceChown(factory, name, owner string) error {
body := map[string]string{"owner": owner}
data, err := json.Marshal(body)
if err != nil {
return err
}
url := a.serverUrl + "/ota/devices/" + name + "/?factory=" + factory
_, err = a.Patch(url, data)
return err
}

func (a *Api) DeviceRename(factory, curName, newName string) error {
body := map[string]string{"name": newName}
data, err := json.Marshal(body)
if err != nil {
return err
}
url := a.serverUrl + "/ota/devices/" + curName + "/?factory=" + factory
_, err = a.Patch(url, data)
return err
}

func (a *Api) DeviceSetGroup(factory, device, group string) error {
body := map[string]string{"group": group}
data, err := json.Marshal(body)
if err != nil {
return err
}
url := a.serverUrl + "/ota/devices/" + device + "/?factory=" + factory
_, err = a.Patch(url, data)
return err
}

func (a *Api) DeviceDelete(factory, device string) error {
bytes := []byte{}
url := a.serverUrl + "/ota/devices/" + device + "/?factory=" + factory
_, err := a.Delete(url, bytes)
return err
}

func (a *Api) DeviceDeleteDenied(factory, uuid string) error {
bytes := []byte{}
url := a.serverUrl + "/ota/factories/" + factory + "/denied-devices/" + uuid + "/"
_, err := a.Delete(url, bytes)
return err
}

func (a *Api) DeviceListUpdates(factory, device string) (*UpdateList, error) {
url := a.serverUrl + "/ota/devices/" + device + "/updates/?factory=" + factory
return a.DeviceListUpdatesCont(url)
}

func (a *Api) DeviceListUpdatesCont(url string) (*UpdateList, error) {
body, err := a.Get(url)
if err != nil {
return nil, err
}

updates := UpdateList{}
err = json.Unmarshal(*body, &updates)
if err != nil {
return nil, err
}
return &updates, nil
}

func (a *Api) DeviceUpdateEvents(factory, device, correlationId string) ([]UpdateEvent, error) {
var events []UpdateEvent
url := a.serverUrl + "/ota/devices/" + device + "/updates/" + correlationId + "/?factory=" + factory
body, err := a.Get(url)
if err != nil {
return nil, err
}
err = json.Unmarshal(*body, &events)
if err != nil {
return events, err
}
return events, nil
}

func (a *Api) DeviceCreateConfig(factory, device string, cfg ConfigCreateRequest) error {
data, err := json.Marshal(cfg)
if err != nil {
return err
}

url := a.serverUrl + "/ota/devices/" + device + "/config/?factory=" + factory
logrus.Debug("Creating new device config")
_, err = a.Post(url, data)
return err
}

func (a *Api) DevicePatchConfig(factory, device string, cfg ConfigCreateRequest, force bool) error {
data, err := json.Marshal(cfg)
if err != nil {
return err
}

url := a.serverUrl + "/ota/devices/" + device + "/config/?factory=" + factory
if force {
url += "&force=1"
}
logrus.Debug("Patching device config")
_, err = a.Patch(url, data)
return err
}

func (a *Api) DeviceListConfig(factory, device string) (*DeviceConfigList, error) {
url := a.serverUrl + "/ota/devices/" + device + "/config/?factory=" + factory
logrus.Debugf("DeviceListConfig with url: %s", url)
return a.DeviceListConfigCont(url)
}

func (a *Api) DeviceListConfigCont(url string) (*DeviceConfigList, error) {
body, err := a.Get(url)
if err != nil {
return nil, err
}

config := DeviceConfigList{}
err = json.Unmarshal(*body, &config)
if err != nil {
return nil, err
}
return &config, nil
}

func (a *Api) DeviceDeleteConfig(factory, device, filename string) error {
url := a.serverUrl + "/ota/devices/" + device + "/config/" + filename + "/?factory=" + factory
logrus.Debugf("Deleting config file: %s", url)
_, err := a.Delete(url, nil)
return err
}

func (a *Api) DeviceGetAppsStates(factory, device string) (*AppsStates, error) {
url := a.serverUrl + "/ota/devices/" + device + "/apps-states/?factory=" + factory
body, err := a.Get(url)
if err != nil {
return nil, err
}

states := AppsStates{}
err = json.Unmarshal(*body, &states)
if err != nil {
return nil, err
}
return &states, nil
}

func (a *Api) FactoryCreateConfig(factory string, cfg ConfigCreateRequest) error {
data, err := json.Marshal(cfg)
if err != nil {
Expand Down
Loading
Loading