Files
florian.wildeandClaude Opus 5.5 bd4bca5399 feat(cli): proxdeploy in Go
Befehle login, servers, distros, profiles, presets, vm, lxc, template list|build, batch, status, logs --follow, cancel. Renderer im Aufbau der Vorgabe (zeichengenau per Golden-File), 24-bit/256/ohne Farbe, --ascii, --quiet, --json, --dry-run; live im Terminal, zeilenweise ohne. SSE mit Wiederverbinden und Polling als Rückfall. Typen aus openapi.json per oapi-codegen; Release-Builds per cli/bauen.sh.

Refs #013

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 15:08:41 +02:00

132 lines
3.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package konfig liest und schreibt ~/.config/proxdeploy/config.toml.
//
// url = "https://proxdeploy.example"
// token = "pd_…"
// server = "rz1" # optional: Standard für --server
//
// [instances.labor] # weitere Instanzen, Auswahl mit --instance labor
// url = "https://proxdeploy.labor"
// token = "pd_…"
//
// PROXDEPLOY_URL, PROXDEPLOY_TOKEN und PROXDEPLOY_INSTANCE gehen der Datei vor.
package konfig
import (
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
"runtime"
"github.com/BurntSushi/toml"
)
type Instanz struct {
URL string `toml:"url"`
Token string `toml:"token"`
Server string `toml:"server,omitempty"`
}
type Datei struct {
Instanz
Instanzen map[string]Instanz `toml:"instances,omitempty"`
}
// Pfad: $XDG_CONFIG_HOME/proxdeploy/config.toml, sonst ~/.config/…; unter Windows %AppData%.
func Pfad() (string, error) {
if eigener := os.Getenv("PROXDEPLOY_CONFIG"); eigener != "" {
return eigener, nil
}
basis := os.Getenv("XDG_CONFIG_HOME")
if basis == "" {
if runtime.GOOS == "windows" {
var err error
if basis, err = os.UserConfigDir(); err != nil {
return "", err
}
} else {
heim, err := os.UserHomeDir()
if err != nil {
return "", err
}
basis = filepath.Join(heim, ".config")
}
}
return filepath.Join(basis, "proxdeploy", "config.toml"), nil
}
// Lesen liefert die Datei oder eine leere, wenn es sie noch nicht gibt.
func Lesen() (Datei, string, error) {
pfad, err := Pfad()
if err != nil {
return Datei{}, "", err
}
var d Datei
if _, err := toml.DecodeFile(pfad, &d); err != nil {
if errors.Is(err, fs.ErrNotExist) {
return Datei{}, pfad, nil
}
return Datei{}, pfad, fmt.Errorf("%s: %w", pfad, err)
}
return d, pfad, nil
}
// Waehlen: die gewünschte Instanz (leer = Hauptabschnitt), überlagert von der Umgebung.
func (d Datei) Waehlen(name string) (Instanz, error) {
if name == "" {
name = os.Getenv("PROXDEPLOY_INSTANCE")
}
i := d.Instanz
if name != "" {
gefunden, ok := d.Instanzen[name]
if !ok {
return Instanz{}, fmt.Errorf("Instanz %q steht nicht in der Konfiguration", name)
}
i = gefunden
}
if url := os.Getenv("PROXDEPLOY_URL"); url != "" {
i.URL = url
}
if token := os.Getenv("PROXDEPLOY_TOKEN"); token != "" {
i.Token = token
}
return i, nil
}
// Setzen trägt eine Instanz ein (leer = Hauptabschnitt).
func (d *Datei) Setzen(name string, i Instanz) {
if name == "" {
d.Instanz = i
return
}
if d.Instanzen == nil {
d.Instanzen = map[string]Instanz{}
}
d.Instanzen[name] = i
}
// Schreiben legt die Datei mit Rechten 0600 an – sie enthält das Token.
func Schreiben(pfad string, d Datei) error {
if err := os.MkdirAll(filepath.Dir(pfad), 0o700); err != nil {
return err
}
tmp, err := os.CreateTemp(filepath.Dir(pfad), ".config-*.toml")
if err != nil {
return err
}
defer os.Remove(tmp.Name())
if err := tmp.Chmod(0o600); err != nil {
tmp.Close()
return err
}
if err := toml.NewEncoder(tmp).Encode(d); err != nil {
tmp.Close()
return err
}
if err := tmp.Close(); err != nil {
return err
}
return os.Rename(tmp.Name(), pfad)
}