refactor(metis): retire docs and loc hygiene failures
This commit is contained in:
parent
e659714335
commit
cd6058c54f
94
cmd/metis/remote_artifacts.go
Normal file
94
cmd/metis/remote_artifacts.go
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func orasLogin(registry, username, password string) error {
|
||||||
|
if strings.TrimSpace(username) == "" || strings.TrimSpace(password) == "" {
|
||||||
|
return fmt.Errorf("harbor credentials missing")
|
||||||
|
}
|
||||||
|
cmd := exec.Command("oras", "login", registry, "-u", username, "-p", password)
|
||||||
|
if out, err := cmd.CombinedOutput(); err != nil {
|
||||||
|
return fmt.Errorf("%w: %s", err, strings.TrimSpace(string(out)))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func orasPush(ref, imagePath, metadataPath string) error {
|
||||||
|
dir, args, err := orasPushInvocation(ref, imagePath, metadataPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cmd := exec.Command("oras", args...)
|
||||||
|
cmd.Dir = dir
|
||||||
|
if out, err := cmd.CombinedOutput(); err != nil {
|
||||||
|
return fmt.Errorf("%w: %s", err, strings.TrimSpace(string(out)))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func orasPushInvocation(ref, imagePath, metadataPath string) (string, []string, error) {
|
||||||
|
imageDir := filepath.Dir(imagePath)
|
||||||
|
metadataDir := filepath.Dir(metadataPath)
|
||||||
|
if imageDir != metadataDir {
|
||||||
|
return "", nil, fmt.Errorf("oras push requires artifacts in one directory: %s vs %s", imageDir, metadataDir)
|
||||||
|
}
|
||||||
|
return imageDir, []string{
|
||||||
|
"push",
|
||||||
|
ref,
|
||||||
|
fmt.Sprintf("%s:application/x-raw-disk-image", filepath.Base(imagePath)),
|
||||||
|
fmt.Sprintf("%s:application/json", filepath.Base(metadataPath)),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func orasTag(ref string, tags ...string) error {
|
||||||
|
args := append([]string{"tag", ref}, tags...)
|
||||||
|
cmd := exec.Command("oras", args...)
|
||||||
|
if out, err := cmd.CombinedOutput(); err != nil {
|
||||||
|
return fmt.Errorf("%w: %s", err, strings.TrimSpace(string(out)))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func orasPull(ref, outDir string) error {
|
||||||
|
cmd := exec.Command("oras", "pull", ref, "-o", outDir)
|
||||||
|
if out, err := cmd.CombinedOutput(); err != nil {
|
||||||
|
return fmt.Errorf("%w: %s", err, strings.TrimSpace(string(out)))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolvePulledArtifact(dir string) (string, bool, error) {
|
||||||
|
var rawPath string
|
||||||
|
var compressedPath string
|
||||||
|
err := filepath.WalkDir(dir, func(path string, d os.DirEntry, walkErr error) error {
|
||||||
|
if walkErr != nil {
|
||||||
|
return walkErr
|
||||||
|
}
|
||||||
|
if d.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case strings.HasSuffix(path, ".img.xz"):
|
||||||
|
compressedPath = path
|
||||||
|
case strings.HasSuffix(path, ".img"):
|
||||||
|
rawPath = path
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", false, err
|
||||||
|
}
|
||||||
|
if compressedPath != "" {
|
||||||
|
return compressedPath, true, nil
|
||||||
|
}
|
||||||
|
if rawPath != "" {
|
||||||
|
return rawPath, false, nil
|
||||||
|
}
|
||||||
|
return "", false, fmt.Errorf("no .img or .img.xz artifact found in %s", dir)
|
||||||
|
}
|
||||||
@ -383,91 +383,6 @@ func localDeviceScore(device service.Device) int {
|
|||||||
return score
|
return score
|
||||||
}
|
}
|
||||||
|
|
||||||
func orasLogin(registry, username, password string) error {
|
|
||||||
if strings.TrimSpace(username) == "" || strings.TrimSpace(password) == "" {
|
|
||||||
return fmt.Errorf("harbor credentials missing")
|
|
||||||
}
|
|
||||||
cmd := exec.Command("oras", "login", registry, "-u", username, "-p", password)
|
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
|
||||||
return fmt.Errorf("%w: %s", err, strings.TrimSpace(string(out)))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func orasPush(ref, imagePath, metadataPath string) error {
|
|
||||||
dir, args, err := orasPushInvocation(ref, imagePath, metadataPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
cmd := exec.Command("oras", args...)
|
|
||||||
cmd.Dir = dir
|
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
|
||||||
return fmt.Errorf("%w: %s", err, strings.TrimSpace(string(out)))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func orasPushInvocation(ref, imagePath, metadataPath string) (string, []string, error) {
|
|
||||||
imageDir := filepath.Dir(imagePath)
|
|
||||||
metadataDir := filepath.Dir(metadataPath)
|
|
||||||
if imageDir != metadataDir {
|
|
||||||
return "", nil, fmt.Errorf("oras push requires artifacts in one directory: %s vs %s", imageDir, metadataDir)
|
|
||||||
}
|
|
||||||
return imageDir, []string{
|
|
||||||
"push",
|
|
||||||
ref,
|
|
||||||
fmt.Sprintf("%s:application/x-raw-disk-image", filepath.Base(imagePath)),
|
|
||||||
fmt.Sprintf("%s:application/json", filepath.Base(metadataPath)),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func orasTag(ref string, tags ...string) error {
|
|
||||||
args := append([]string{"tag", ref}, tags...)
|
|
||||||
cmd := exec.Command("oras", args...)
|
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
|
||||||
return fmt.Errorf("%w: %s", err, strings.TrimSpace(string(out)))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func orasPull(ref, outDir string) error {
|
|
||||||
cmd := exec.Command("oras", "pull", ref, "-o", outDir)
|
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
|
||||||
return fmt.Errorf("%w: %s", err, strings.TrimSpace(string(out)))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func resolvePulledArtifact(dir string) (string, bool, error) {
|
|
||||||
var rawPath string
|
|
||||||
var compressedPath string
|
|
||||||
err := filepath.WalkDir(dir, func(path string, d os.DirEntry, walkErr error) error {
|
|
||||||
if walkErr != nil {
|
|
||||||
return walkErr
|
|
||||||
}
|
|
||||||
if d.IsDir() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
switch {
|
|
||||||
case strings.HasSuffix(path, ".img.xz"):
|
|
||||||
compressedPath = path
|
|
||||||
case strings.HasSuffix(path, ".img"):
|
|
||||||
rawPath = path
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return "", false, err
|
|
||||||
}
|
|
||||||
if compressedPath != "" {
|
|
||||||
return compressedPath, true, nil
|
|
||||||
}
|
|
||||||
if rawPath != "" {
|
|
||||||
return rawPath, false, nil
|
|
||||||
}
|
|
||||||
return "", false, fmt.Errorf("no .img or .img.xz artifact found in %s", dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasMountedChildren(children []struct {
|
func hasMountedChildren(children []struct {
|
||||||
Mountpoint string `json:"mountpoint"`
|
Mountpoint string `json:"mountpoint"`
|
||||||
}) bool {
|
}) bool {
|
||||||
|
|||||||
@ -29,6 +29,8 @@ type partitionTablePart struct {
|
|||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RootFSProgressFunc receives coarse-grained step names while Metis rewrites a
|
||||||
|
// Linux root filesystem inside a raw image.
|
||||||
type RootFSProgressFunc func(step string)
|
type RootFSProgressFunc func(step string)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
86
pkg/service/app_devices.go
Normal file
86
pkg/service/app_devices.go
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *App) cachedDevices(host string) ([]Device, error) {
|
||||||
|
host = strings.TrimSpace(host)
|
||||||
|
if host == "" {
|
||||||
|
host = a.settings.DefaultFlashHost
|
||||||
|
}
|
||||||
|
a.mu.RLock()
|
||||||
|
snapshot, ok := a.deviceStore[host]
|
||||||
|
a.mu.RUnlock()
|
||||||
|
if !ok {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(snapshot.Err) != "" {
|
||||||
|
return cloneDevices(snapshot.Devices), errors.New(snapshot.Err)
|
||||||
|
}
|
||||||
|
return cloneDevices(snapshot.Devices), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) recordDevices(host string, devices []Device, err error) {
|
||||||
|
host = strings.TrimSpace(host)
|
||||||
|
if host == "" {
|
||||||
|
host = a.settings.DefaultFlashHost
|
||||||
|
}
|
||||||
|
snapshot := deviceSnapshot{
|
||||||
|
Devices: cloneDevices(devices),
|
||||||
|
CheckedAt: time.Now().UTC(),
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
snapshot.Err = err.Error()
|
||||||
|
}
|
||||||
|
a.mu.Lock()
|
||||||
|
if existing, ok := a.deviceStore[host]; ok && len(snapshot.Devices) == 0 {
|
||||||
|
snapshot.Devices = cloneDevices(existing.Devices)
|
||||||
|
}
|
||||||
|
a.deviceStore[host] = snapshot
|
||||||
|
a.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func deviceScore(device Device) int {
|
||||||
|
score := 0
|
||||||
|
model := strings.ToLower(strings.TrimSpace(device.Model))
|
||||||
|
switch {
|
||||||
|
case strings.Contains(model, "microsd"), strings.Contains(model, "micro sd"):
|
||||||
|
score += 60
|
||||||
|
case strings.Contains(model, "sdxc"), strings.Contains(model, "sdhc"), strings.Contains(model, "sd "):
|
||||||
|
score += 50
|
||||||
|
case strings.Contains(model, "card"), strings.Contains(model, "reader"):
|
||||||
|
score += 40
|
||||||
|
}
|
||||||
|
if device.Removable {
|
||||||
|
score += 20
|
||||||
|
}
|
||||||
|
if device.Hotplug {
|
||||||
|
score += 10
|
||||||
|
}
|
||||||
|
if device.Transport == "usb" {
|
||||||
|
score += 5
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(device.Name, "mmcblk") {
|
||||||
|
score += 25
|
||||||
|
}
|
||||||
|
return score
|
||||||
|
}
|
||||||
|
|
||||||
|
func moveToFront(values []string, preferred string) []string {
|
||||||
|
if preferred == "" || len(values) < 2 {
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
out := append([]string{}, values...)
|
||||||
|
for idx, value := range out {
|
||||||
|
if value != preferred {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
copy(out[1:idx+1], out[:idx])
|
||||||
|
out[0] = preferred
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
@ -40,6 +40,7 @@ type activeNodeJobError struct {
|
|||||||
JobID string
|
JobID string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Error reports that a replacement-capable job is already active for the node.
|
||||||
func (e *activeNodeJobError) Error() string {
|
func (e *activeNodeJobError) Error() string {
|
||||||
if e == nil {
|
if e == nil {
|
||||||
return "node already has an active metis job"
|
return "node already has an active metis job"
|
||||||
@ -403,85 +404,6 @@ func cloneDevices(devices []Device) []Device {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) cachedDevices(host string) ([]Device, error) {
|
|
||||||
host = strings.TrimSpace(host)
|
|
||||||
if host == "" {
|
|
||||||
host = a.settings.DefaultFlashHost
|
|
||||||
}
|
|
||||||
a.mu.RLock()
|
|
||||||
snapshot, ok := a.deviceStore[host]
|
|
||||||
a.mu.RUnlock()
|
|
||||||
if !ok {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
if strings.TrimSpace(snapshot.Err) != "" {
|
|
||||||
return cloneDevices(snapshot.Devices), errors.New(snapshot.Err)
|
|
||||||
}
|
|
||||||
return cloneDevices(snapshot.Devices), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) recordDevices(host string, devices []Device, err error) {
|
|
||||||
host = strings.TrimSpace(host)
|
|
||||||
if host == "" {
|
|
||||||
host = a.settings.DefaultFlashHost
|
|
||||||
}
|
|
||||||
snapshot := deviceSnapshot{
|
|
||||||
Devices: cloneDevices(devices),
|
|
||||||
CheckedAt: time.Now().UTC(),
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
snapshot.Err = err.Error()
|
|
||||||
}
|
|
||||||
a.mu.Lock()
|
|
||||||
if existing, ok := a.deviceStore[host]; ok && len(snapshot.Devices) == 0 {
|
|
||||||
snapshot.Devices = cloneDevices(existing.Devices)
|
|
||||||
}
|
|
||||||
a.deviceStore[host] = snapshot
|
|
||||||
a.mu.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func deviceScore(device Device) int {
|
|
||||||
score := 0
|
|
||||||
model := strings.ToLower(strings.TrimSpace(device.Model))
|
|
||||||
switch {
|
|
||||||
case strings.Contains(model, "microsd"), strings.Contains(model, "micro sd"):
|
|
||||||
score += 60
|
|
||||||
case strings.Contains(model, "sdxc"), strings.Contains(model, "sdhc"), strings.Contains(model, "sd "):
|
|
||||||
score += 50
|
|
||||||
case strings.Contains(model, "card"), strings.Contains(model, "reader"):
|
|
||||||
score += 40
|
|
||||||
}
|
|
||||||
if device.Removable {
|
|
||||||
score += 20
|
|
||||||
}
|
|
||||||
if device.Hotplug {
|
|
||||||
score += 10
|
|
||||||
}
|
|
||||||
if device.Transport == "usb" {
|
|
||||||
score += 5
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(device.Name, "mmcblk") {
|
|
||||||
score += 25
|
|
||||||
}
|
|
||||||
return score
|
|
||||||
}
|
|
||||||
|
|
||||||
func moveToFront(values []string, preferred string) []string {
|
|
||||||
if preferred == "" || len(values) < 2 {
|
|
||||||
return values
|
|
||||||
}
|
|
||||||
out := append([]string{}, values...)
|
|
||||||
for idx, value := range out {
|
|
||||||
if value != preferred {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
copy(out[1:idx+1], out[:idx])
|
|
||||||
out[0] = preferred
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteNodeObject(node string) error {
|
func deleteNodeObject(node string) error {
|
||||||
if err := deleteNodeObjectInCluster(node); err == nil {
|
if err := deleteNodeObjectInCluster(node); err == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user