Files
unitdore/cmd/syncup.go
Hein cb9187bfbd fix(cmd): improve editor selection logic in edit command
* Enhance the editor selection to check for nvim and nano before defaulting to vi.
* Return an error if no suitable editor is found.
fix(cmd): track unchanged units in syncup command
* Add tracking for unchanged units during syncup process.
* Update completion message to include count of unchanged units.
fix(runtime): change command type to slice in podman container
* Update command field in podmanContainer struct to be a slice of strings.
* Adjust ListRunning method to join command slice into a single string for output.
fix(ci): enhance release notes generation in workflow
* Collect commit messages since the last tag for release notes.
* Format release body to include detailed change log.
2026-04-08 13:21:53 +02:00

95 lines
2.2 KiB
Go

package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/warkanum/unitdore/config"
"github.com/warkanum/unitdore/runtime"
)
var syncupCmd = &cobra.Command{
Use: "syncup",
Short: "Discover running containers and sync them into the config",
Long: `Syncup queries all available runtimes for running containers and adds
any new ones to the config file. Existing entries are never removed.
It also reconciles: if a configured unit's container no longer exists,
it is marked disabled with a reason.`,
RunE: runSyncup,
}
func init() {
rootCmd.AddCommand(syncupCmd)
}
func runSyncup(cmd *cobra.Command, args []string) error {
cfg, err := config.LoadOrEmpty(configPath)
if err != nil {
return err
}
added := 0
unchanged := 0
discovered := map[string]bool{}
// Discover running containers across all runtimes
for _, rt := range runtime.Available() {
containers, err := rt.ListRunning()
if err != nil {
fmt.Fprintf(os.Stderr, "warning: %s discovery failed: %v\n", rt.Name(), err)
continue
}
for _, c := range containers {
discovered[c.Name] = true
unit := config.Unit{
Name: c.Name,
Runtime: c.Runtime,
Order: len(cfg.Units) + 1,
Enabled: true,
}
if cfg.AddUnit(unit) {
fmt.Printf(" + added: %s (%s)\n", c.Name, c.Runtime)
added++
} else {
unchanged++
}
}
}
// Reconcile: check if existing units' containers still exist
disabled := 0
reenabled := 0
for i := range cfg.Units {
u := &cfg.Units[i]
rt := runtime.Get(u.Runtime)
if rt == nil {
continue
}
exists, err := rt.Exists(u.Name)
if err != nil {
fmt.Fprintf(os.Stderr, "warning: checking %s: %v\n", u.Name, err)
continue
}
if !exists && u.Enabled {
u.Enabled = false
u.DisabledReason = "container not found"
fmt.Printf(" ! disabled: %s (container not found)\n", u.Name)
disabled++
} else if exists && !u.Enabled && u.DisabledReason == "container not found" {
u.Enabled = true
u.DisabledReason = ""
fmt.Printf(" ✓ re-enabled: %s (container found)\n", u.Name)
reenabled++
}
}
if err := cfg.Save(configPath); err != nil {
return err
}
fmt.Printf("\nDone. Added: %d Unchanged: %d Disabled: %d Re-enabled: %d\n", added, unchanged, disabled, reenabled)
return nil
}