DEVICE-002: ARM machine-ID fallback — device-tree model + /etc/machine-id combo, then /proc/cpuinfo Serial (all-zero rejected), before the weak hostname fallback. Hardware-bound IDs on DMI-less devices. DEVICE-001: agent detects device_type (server/desktop/phone/tablet) from /sys signals — system battery (scope=Device peripherals excluded, UPS excluded), DRM connector state, framebuffer min-dimension for phone/tablet split. Reports device_type/device_model/os_distro in registration and system-info paths. SERVER-001: migration 061 — device_type, device_type_manual (operator override, never agent-written), device_model, os_distro on agents. effective_device_type computed into every serialized agent. SERVER-002: PUT /admin/agents/:id/device-type — set/clear override, enum-validated, journaled. WEB-001: device-type icons + fleet filter, device model in list, detail header badge with reclassify dropdown, os_distro surfaced. INSTALL-003: arm64 install path unblocked — helper (required manifest component) now cross-built aarch64-unknown-linux-musl via rust-lld in the server image, signed at boot (helperArches += arm64), listed in the release manifest. Install template already handled uname -m and pacman. Plus in-flight: desktop tray wiring, enrollment page polish, CI workflow updates, RAF session-broker/pacman-scanner docs, native installer scaffold.
64 lines
1.9 KiB
Go
64 lines
1.9 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestLoadEnvFile_DoesNotOverrideExistingEnv(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "redflag.env")
|
|
content := "REDFLAG_TEST_A=from_file\nREDFLAG_TEST_B=from_file\n"
|
|
if err := os.WriteFile(path, []byte(content), 0o600); err != nil {
|
|
t.Fatalf("write test file: %v", err)
|
|
}
|
|
|
|
os.Unsetenv("REDFLAG_TEST_A")
|
|
t.Setenv("REDFLAG_TEST_B", "already_set")
|
|
|
|
if err := loadEnvFile(path); err != nil {
|
|
t.Fatalf("loadEnvFile: %v", err)
|
|
}
|
|
|
|
if got := os.Getenv("REDFLAG_TEST_A"); got != "from_file" {
|
|
t.Errorf("REDFLAG_TEST_A = %q, want %q (should be set from file)", got, "from_file")
|
|
}
|
|
if got := os.Getenv("REDFLAG_TEST_B"); got != "already_set" {
|
|
t.Errorf("REDFLAG_TEST_B = %q, want %q (existing env var must win)", got, "already_set")
|
|
}
|
|
}
|
|
|
|
func TestLoadEnvFile_SkipsCommentsAndBlankLines(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "redflag.env")
|
|
content := "# a comment\n\nREDFLAG_TEST_C=\"quoted\"\n \nREDFLAG_TEST_D='single'\n"
|
|
if err := os.WriteFile(path, []byte(content), 0o600); err != nil {
|
|
t.Fatalf("write test file: %v", err)
|
|
}
|
|
os.Unsetenv("REDFLAG_TEST_C")
|
|
os.Unsetenv("REDFLAG_TEST_D")
|
|
|
|
if err := loadEnvFile(path); err != nil {
|
|
t.Fatalf("loadEnvFile: %v", err)
|
|
}
|
|
|
|
if got := os.Getenv("REDFLAG_TEST_C"); got != "quoted" {
|
|
t.Errorf("REDFLAG_TEST_C = %q, want %q", got, "quoted")
|
|
}
|
|
if got := os.Getenv("REDFLAG_TEST_D"); got != "single" {
|
|
t.Errorf("REDFLAG_TEST_D = %q, want %q", got, "single")
|
|
}
|
|
}
|
|
|
|
func TestLoadNativeConfigFile_NoopWhenAbsent(t *testing.T) {
|
|
dir := t.TempDir()
|
|
t.Setenv("REDFLAG_CONFIG_FILE", filepath.Join(dir, "does-not-exist.env"))
|
|
os.Unsetenv("REDFLAG_TEST_SHOULD_NOT_APPEAR")
|
|
|
|
loadNativeConfigFile() // must not panic or error when the file is missing
|
|
|
|
if _, ok := os.LookupEnv("REDFLAG_TEST_SHOULD_NOT_APPEAR"); ok {
|
|
t.Error("expected no env var to be set when config file is absent")
|
|
}
|
|
}
|