@@ -28,6 +28,9 @@ func (h Handler) Create(cmd *cobra.Command, args []string) error {
2828 if err != nil {
2929 return err
3030 }
31+ if done , jsonErr := cmdcore .MaybeOutputJSON (cmd , vm ); done {
32+ return jsonErr
33+ }
3134 logger := log .WithFunc ("cmd.vm.create" )
3235 logger .Infof (ctx , "VM created: %s (name: %s, state: %s)" , vm .ID , vm .Config .Name , vm .State )
3336 logger .Infof (ctx , "start with: cocoon vm start %s" , vm .ID )
@@ -40,12 +43,28 @@ func (h Handler) Run(cmd *cobra.Command, args []string) error {
4043 return err
4144 }
4245 logger := log .WithFunc ("cmd.vm.run" )
43- logger .Infof (ctx , "VM created: %s (name: %s)" , vm .ID , vm .Config .Name )
46+ wantJSON := cmdcore .WantJSON (cmd )
47+ if ! wantJSON {
48+ logger .Infof (ctx , "VM created: %s (name: %s)" , vm .ID , vm .Config .Name )
49+ }
4450
4551 started , err := hyper .Start (ctx , []string {vm .ID })
4652 if err != nil {
4753 return fmt .Errorf ("start VM %s: %w" , vm .ID , err )
4854 }
55+ if wantJSON {
56+ // Re-inspect to capture post-start state (running, PID, IP).
57+ // On failure, fall back to pre-start vm and surface the reason so the
58+ // caller doesn't silently consume stale JSON.
59+ info , inspectErr := hyper .Inspect (ctx , vm .ID )
60+ switch {
61+ case inspectErr != nil :
62+ logger .Warnf (ctx , "inspect after start failed: %v (json payload may be stale)" , inspectErr )
63+ case info != nil :
64+ vm = info
65+ }
66+ return cmdcore .OutputJSON (vm )
67+ }
4968 for _ , id := range started {
5069 logger .Infof (ctx , "started: %s" , id )
5170 }
@@ -110,6 +129,9 @@ func (h Handler) Clone(cmd *cobra.Command, args []string) error {
110129 return fmt .Errorf ("clone VM: %w" , cloneErr )
111130 }
112131
132+ if done , jsonErr := cmdcore .MaybeOutputJSON (cmd , vm ); done {
133+ return jsonErr
134+ }
113135 logger .Infof (ctx , "VM cloned: %s (name: %s)" , vm .ID , vm .Config .Name )
114136 printPostCloneHints (vm , networkConfigs )
115137 return nil
@@ -156,7 +178,7 @@ func (h Handler) Restore(cmd *cobra.Command, args []string) error {
156178 return err
157179 }
158180
159- done , directErr := h .restoreDirect (ctx , snapRef , vmRef , vmCfg , snapBackend , hyper , logger )
181+ done , directErr := h .restoreDirect (ctx , cmd , snapRef , vmRef , vmCfg , snapBackend , hyper , logger )
160182 if done {
161183 return directErr
162184 }
@@ -179,6 +201,9 @@ func (h Handler) Restore(cmd *cobra.Command, args []string) error {
179201 return fmt .Errorf ("restore: %w" , err )
180202 }
181203
204+ if done , jsonErr := cmdcore .MaybeOutputJSON (cmd , result ); done {
205+ return jsonErr
206+ }
182207 logger .Infof (ctx , "VM %s restored (state: %s)" , result .ID , result .State )
183208 return nil
184209}
@@ -194,14 +219,20 @@ func (h Handler) cloneDirect(ctx context.Context, cmd *cobra.Command, conf *conf
194219 return err
195220 }
196221
197- logger .Infof (ctx , "cloning VM from snapshot %s (direct) ..." , snapRef )
222+ wantJSON := cmdcore .WantJSON (cmd )
223+ if ! wantJSON {
224+ logger .Infof (ctx , "cloning VM from snapshot %s (direct) ..." , snapRef )
225+ }
198226
199227 vm , cloneErr := dcr .DirectClone (ctx , vmID , vmCfg , networkConfigs , cfg , dataDir )
200228 if cloneErr != nil {
201229 rollbackNetwork (ctx , netProvider , vmID )
202230 return fmt .Errorf ("clone VM: %w" , cloneErr )
203231 }
204232
233+ if wantJSON {
234+ return cmdcore .OutputJSON (vm )
235+ }
205236 logger .Infof (ctx , "VM cloned: %s (name: %s)" , vm .ID , vm .Config .Name )
206237 printPostCloneHints (vm , networkConfigs )
207238 return nil
@@ -251,7 +282,7 @@ func (h Handler) prepareClone(ctx context.Context, cmd *cobra.Command, conf *con
251282 return vmCfg , vmID , netProvider , networkConfigs , nil
252283}
253284
254- func (h Handler ) restoreDirect (ctx context.Context , snapRef , vmRef string , vmCfg * types.VMConfig , snapBackend snapshot.Snapshot , hyper hypervisor.Hypervisor , logger * log.Fields ) (bool , error ) {
285+ func (h Handler ) restoreDirect (ctx context.Context , cmd * cobra. Command , snapRef , vmRef string , vmCfg * types.VMConfig , snapBackend snapshot.Snapshot , hyper hypervisor.Hypervisor , logger * log.Fields ) (bool , error ) {
255286 da , ok := snapBackend .(snapshot.Direct )
256287 if ! ok {
257288 return false , nil
@@ -266,12 +297,18 @@ func (h Handler) restoreDirect(ctx context.Context, snapRef, vmRef string, vmCfg
266297 return true , fmt .Errorf ("open snapshot: %w" , err )
267298 }
268299
269- logger .Infof (ctx , "restoring VM %s from snapshot %s (direct) ..." , vmRef , snapRef )
300+ wantJSON := cmdcore .WantJSON (cmd )
301+ if ! wantJSON {
302+ logger .Infof (ctx , "restoring VM %s from snapshot %s (direct) ..." , vmRef , snapRef )
303+ }
270304 result , err := dcr .DirectRestore (ctx , vmRef , vmCfg , dataDir )
271305 if err != nil {
272306 return true , fmt .Errorf ("restore: %w" , err )
273307 }
274308
309+ if wantJSON {
310+ return true , cmdcore .OutputJSON (result )
311+ }
275312 logger .Infof (ctx , "VM %s restored (state: %s)" , result .ID , result .State )
276313 return true , nil
277314}
0 commit comments