* 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.
95 lines
2.2 KiB
Go
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
|
|
}
|