@@ -89,6 +89,7 @@ func ResumeAll(cfg *config.Config, u *ui.UI) {
8989 u .Warnf ("Could not read recorded agent %s: %v" , name , err )
9090 continue
9191 }
92+ warnIfWalletWouldRegenerate (cfg , name , data , u )
9293 nsErr := kubectl .PipeCommands (bin , kubeconfig ,
9394 []string {"create" , "namespace" , Namespace (name ), "--dry-run=client" , "-o" , "yaml" },
9495 []string {"apply" , "-f" , "-" })
@@ -102,3 +103,37 @@ func ResumeAll(cfg *config.Config, u *ui.UI) {
102103 u .Successf ("Re-applied agent %s" , name )
103104 }
104105}
106+
107+ // warnIfWalletWouldRegenerate flags the funds-stranding edge: replaying a
108+ // wallet-bearing agent against a cluster that lost its keystore Secret
109+ // (full recreation without a prior `obol stack import`) makes the
110+ // controller mint a FRESH wallet — anything held at the old address is
111+ // stranded unless the operator restores the keystore first. Best-effort:
112+ // an unreachable cluster or a wallet-less agent stays silent.
113+ func warnIfWalletWouldRegenerate (cfg * config.Config , name string , manifest []byte , u * ui.UI ) {
114+ var doc struct {
115+ Spec struct {
116+ Wallet struct {
117+ Create bool `yaml:"create"`
118+ } `yaml:"wallet"`
119+ } `yaml:"spec"`
120+ }
121+ if err := yaml .Unmarshal (manifest , & doc ); err != nil || ! doc .Spec .Wallet .Create {
122+ return
123+ }
124+ bin , kubeconfig := kubectl .Paths (cfg )
125+ if err := kubectl .RunSilent (bin , kubeconfig ,
126+ "get" , "namespace" , Namespace (name )); err != nil {
127+ // Namespace itself is gone — full recreation. The keystore Secret
128+ // check below would also fail, but distinguish nothing: same warning.
129+ u .Warnf ("Agent %s declares a wallet but its namespace is gone — the controller will mint a NEW wallet on replay. " +
130+ "If the old wallet held funds, restore the keystore first: 'obol stack import <backup> --cluster-only' or 'obol agent wallet restore'." , name )
131+ return
132+ }
133+ if err := kubectl .RunSilent (bin , kubeconfig ,
134+ "get" , "secret" , "remote-signer-keystore" , "-n" , Namespace (name )); err != nil {
135+ u .Warnf ("Agent %s declares a wallet but namespace %s has no keystore Secret — the controller will mint a NEW wallet. " +
136+ "If the old wallet held funds, restore it first: 'obol stack import <backup> --cluster-only' or 'obol agent wallet restore'." ,
137+ name , Namespace (name ))
138+ }
139+ }
0 commit comments