From 8d48aed4a4b9fc671b877152a3fb1a38f7f9b228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matev=C5=BE=20Jekovec?= Date: Thu, 22 Jan 2026 09:51:18 +0100 Subject: [PATCH] cmd/rofl/machine: Support provider:machine-id directly --- cmd/rofl/machine/logs.go | 14 +-- cmd/rofl/machine/mgmt.go | 139 ++++++++++++--------- cmd/rofl/machine/show.go | 260 +++++++++++++++++++-------------------- 3 files changed, 215 insertions(+), 198 deletions(-) diff --git a/cmd/rofl/machine/logs.go b/cmd/rofl/machine/logs.go index 3e3023f7..547d0c40 100644 --- a/cmd/rofl/machine/logs.go +++ b/cmd/rofl/machine/logs.go @@ -20,28 +20,20 @@ import ( ) var logsCmd = &cobra.Command{ - Use: "logs []", + Use: "logs [ | :]", Short: "Show logs from the given machine", Args: cobra.MaximumNArgs(1), Run: func(_ *cobra.Command, args []string) { - _, deployment, npa := roflCommon.LoadManifestAndSetNPA(&roflCommon.ManifestOptions{ + _, _, machineID, _, _, providerAddr, npa := resolveMachineManifestNpa(args, &roflCommon.ManifestOptions{ NeedAppID: true, NeedAdmin: false, }) - machine, _, machineID := resolveMachine(args, deployment) - // Establish connection with the target network. ctx := context.Background() conn, err := connection.Connect(ctx, npa.Network) cobra.CheckErr(err) - // Resolve provider address. - providerAddr, _, err := common.ResolveLocalAccountOrAddress(npa.Network, machine.Provider) - if err != nil { - cobra.CheckErr(fmt.Sprintf("Invalid provider address: %s", err)) - } - providerDsc, err := conn.Runtime(npa.ParaTime).ROFLMarket.Provider(ctx, client.RoundLatest, *providerAddr) cobra.CheckErr(err) @@ -54,7 +46,7 @@ var logsCmd = &cobra.Command{ } var schedulerRAK ed25519.PublicKey if err := schedulerRAK.UnmarshalText([]byte(schedulerRAKRaw)); err != nil { - cobra.CheckErr(fmt.Sprintf("Malformed scheduler RAK metadata: %s", err)) + cobra.CheckErr(fmt.Errorf("malformed scheduler RAK metadata: %w", err)) } pk := types.PublicKey{PublicKey: schedulerRAK} diff --git a/cmd/rofl/machine/mgmt.go b/cmd/rofl/machine/mgmt.go index dcf0c851..8e2face3 100644 --- a/cmd/rofl/machine/mgmt.go +++ b/cmd/rofl/machine/mgmt.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "os" + "strings" "github.com/spf13/cobra" @@ -20,13 +21,14 @@ import ( buildRoflProvider "github.com/oasisprotocol/cli/build/rofl/provider" "github.com/oasisprotocol/cli/build/rofl/scheduler" "github.com/oasisprotocol/cli/cmd/common" + roflCmdBuild "github.com/oasisprotocol/cli/cmd/rofl/build" roflCommon "github.com/oasisprotocol/cli/cmd/rofl/common" cliConfig "github.com/oasisprotocol/cli/config" ) var ( restartCmd = &cobra.Command{ - Use: "restart []", + Use: "restart [ | :]", Short: "Restart a running machine or start a stopped one", Args: cobra.MaximumNArgs(1), Run: func(_ *cobra.Command, args []string) { @@ -42,7 +44,7 @@ var ( } stopCmd = &cobra.Command{ - Use: "stop []", + Use: "stop [ | :]", Short: "Stop a machine", Aliases: []string{"terminate"}, Args: cobra.MaximumNArgs(1), @@ -59,30 +61,21 @@ var ( } removeCmd = &cobra.Command{ - Use: "remove []", + Use: "remove [ | :]", Short: "Cancel rental and remove the machine", Aliases: []string{"cancel", "rm"}, Args: cobra.MaximumNArgs(1), Run: func(_ *cobra.Command, args []string) { - txCfg := common.GetTransactionConfig() - - manifest, deployment, npa := roflCommon.LoadManifestAndSetNPA(&roflCommon.ManifestOptions{ + machine, machineName, machineID, manifest, _, providerAddr, npa := resolveMachineManifestNpa(args, &roflCommon.ManifestOptions{ NeedAppID: true, NeedAdmin: false, }) - machine, machineName, machineID := resolveMachine(args, deployment) - - // Resolve provider address. - providerAddr, _, err := common.ResolveLocalAccountOrAddress(npa.Network, machine.Provider) - if err != nil { - cobra.CheckErr(fmt.Sprintf("Invalid provider address: %s", err)) - } - // When not in offline mode, connect to the given network endpoint. ctx := context.Background() + var err error var conn connection.Connection - if !txCfg.Offline { + if !common.GetTransactionConfig().Offline { conn, err = connection.Connect(ctx, npa.Network) cobra.CheckErr(err) } @@ -111,20 +104,21 @@ var ( // Update manifest to clear the machine ID as it has been cancelled. machine.ID = "" - if err = manifest.Save(); err != nil { - cobra.CheckErr(fmt.Errorf("failed to update manifest: %w", err)) + if manifest != nil { + if err = manifest.Save(); err != nil { + cobra.CheckErr(fmt.Errorf("failed to update manifest: %w", err)) + } } }, } changeAdminCmd = &cobra.Command{ - Use: "change-admin [] ", + Use: "change-admin [ | :] ", Short: "Change the machine administrator", Args: cobra.RangeArgs(1, 2), Run: func(_ *cobra.Command, args []string) { txCfg := common.GetTransactionConfig() - - _, deployment, npa := roflCommon.LoadManifestAndSetNPA(&roflCommon.ManifestOptions{ + machine, machineName, machineID, _, _, providerAddr, npa := resolveMachineManifestNpa(args, &roflCommon.ManifestOptions{ NeedAppID: true, NeedAdmin: false, }) @@ -134,25 +128,15 @@ var ( case 1: // Just admin address. newAdminAddress = args[0] - args = nil case 2: // Machine and admin address. newAdminAddress = args[1] - args = args[:1] - } - - machine, machineName, machineID := resolveMachine(args, deployment) - - // Resolve provider address. - providerAddr, _, err := common.ResolveLocalAccountOrAddress(npa.Network, machine.Provider) - if err != nil { - cobra.CheckErr(fmt.Sprintf("Invalid provider address: %s", err)) } // Resolve new admin address. newAdminAddr, _, err := common.ResolveLocalAccountOrAddress(npa.Network, newAdminAddress) if err != nil { - cobra.CheckErr(fmt.Sprintf("Invalid admin address: %s", err)) + cobra.CheckErr(fmt.Errorf("invalid admin address: %w", err)) } // When not in offline mode, connect to the given network endpoint. @@ -196,13 +180,13 @@ var ( } topUpCmd = &cobra.Command{ - Use: "top-up []", + Use: "top-up [ | :]", Short: "Top-up payment for a machine", Args: cobra.MaximumNArgs(1), Run: func(_ *cobra.Command, args []string) { txCfg := common.GetTransactionConfig() - _, deployment, npa := roflCommon.LoadManifestAndSetNPA(&roflCommon.ManifestOptions{ + machine, machineName, machineID, _, _, providerAddr, npa := resolveMachineManifestNpa(args, &roflCommon.ManifestOptions{ NeedAppID: true, NeedAdmin: false, }) @@ -213,14 +197,6 @@ var ( ctx = context.WithValue(ctx, config.ContextKeyParaTimeCfg, npa.ParaTime) } - machine, machineName, machineID := resolveMachine(args, deployment) - - // Resolve provider address. - providerAddr, _, err := common.ResolveLocalAccountOrAddress(npa.Network, machine.Provider) - if err != nil { - cobra.CheckErr(fmt.Sprintf("invalid provider address: %s", err)) - } - // Parse machine payment term. if roflCommon.Term == "" { cobra.CheckErr("no term period specified. Use --term to specify it") @@ -231,6 +207,7 @@ var ( } // When not in offline mode, connect to the given network endpoint. + var err error var conn connection.Connection var offer *roflmarket.Offer if !txCfg.Offline { @@ -240,7 +217,7 @@ var ( // Fetch chosen offer, so we can calculate price. offers, err := conn.Runtime(npa.ParaTime).ROFLMarket.Offers(ctx, client.RoundLatest, *providerAddr) if err != nil { - cobra.CheckErr(fmt.Errorf("failed to query provider: %s", err)) + cobra.CheckErr(fmt.Errorf("failed to query provider: %w", err)) } for _, of := range offers { @@ -249,6 +226,18 @@ var ( break } } + if offer == nil { + machineDsc, err := conn.Runtime(npa.ParaTime).ROFLMarket.Instance(ctx, client.RoundLatest, *providerAddr, machineID) + if err != nil { + cobra.CheckErr(fmt.Errorf("failed to query machine: %w", err)) + } + for _, of := range offers { + if of.ID == machineDsc.Offer { + offer = of + break + } + } + } if offer == nil { cobra.CheckErr(fmt.Errorf("unable to find existing machine offer (%s) among market offers", machine.Offer)) } @@ -295,7 +284,56 @@ var ( } ) -func resolveMachine(args []string, deployment *buildRofl.Deployment) (*buildRofl.Machine, string, roflmarket.InstanceID) { +func resolveMachineManifestNpa(args []string, manifestOpts *roflCommon.ManifestOptions) (machineCfg *buildRofl.Machine, machineName string, machineID roflmarket.InstanceID, manifest *buildRofl.Manifest, extraCfg *roflCmdBuild.AppExtraConfig, providerAddr *types.Address, npa *common.NPASelection) { + var err error + machineCfg, machineName, machineID = resolveMachineFromArgs(args) + if machineCfg != nil { + cfg := cliConfig.Global() + npa = common.GetNPASelection(cfg) + } else { + var deployment *buildRofl.Deployment + manifest, deployment, npa = roflCommon.LoadManifestAndSetNPA(manifestOpts) + + machineCfg, machineName, machineID = resolveMachineFromManifest(args, deployment) + + var appID rofl.AppID + if err = appID.UnmarshalText([]byte(deployment.AppID)); err != nil { + cobra.CheckErr(fmt.Errorf("malformed app id: %w", err)) + } + + if extraCfg, err = roflCmdBuild.ValidateApp(manifest, roflCmdBuild.ValidationOpts{ + Offline: true, + }); err != nil { + cobra.CheckErr(fmt.Errorf("failed to validate app: %w", err)) + } + } + + if providerAddr, _, err = common.ResolveLocalAccountOrAddress(npa.Network, machineCfg.Provider); err != nil { + cobra.CheckErr(fmt.Errorf("invalid provider address: %w", err)) + } + + return machineCfg, machineName, machineID, manifest, extraCfg, providerAddr, npa +} + +func resolveMachineFromArgs(args []string) (*buildRofl.Machine, string, roflmarket.InstanceID) { + if len(args) > 0 { + parts := strings.Split(args[0], ":") + if len(parts) == 2 { + m := &buildRofl.Machine{ + Provider: parts[0], + ID: parts[1], + } + var machineID roflmarket.InstanceID + if err := machineID.UnmarshalText([]byte(m.ID)); err != nil { + cobra.CheckErr(fmt.Errorf("malformed machine ID: %w", err)) + } + return m, args[0], machineID + } + } + return nil, "", roflmarket.InstanceID{} +} + +func resolveMachineFromManifest(args []string, deployment *buildRofl.Deployment) (*buildRofl.Machine, string, roflmarket.InstanceID) { machineName := buildRofl.DefaultMachineName if len(args) > 0 { machineName = args[0] @@ -333,25 +371,16 @@ func resolveMachine(args []string, deployment *buildRofl.Deployment) (*buildRofl } func queueCommand(cliArgs []string, method string, args any, msgAfter string) { - txCfg := common.GetTransactionConfig() - - _, deployment, npa := roflCommon.LoadManifestAndSetNPA(&roflCommon.ManifestOptions{ + machine, machineName, machineID, _, _, providerAddr, npa := resolveMachineManifestNpa(cliArgs, &roflCommon.ManifestOptions{ NeedAppID: true, NeedAdmin: false, }) - machine, machineName, machineID := resolveMachine(cliArgs, deployment) - - // Resolve provider address. - providerAddr, _, err := common.ResolveLocalAccountOrAddress(npa.Network, machine.Provider) - if err != nil { - cobra.CheckErr(fmt.Sprintf("Invalid provider address: %s", err)) - } - // When not in offline mode, connect to the given network endpoint. ctx := context.Background() + var err error var conn connection.Connection - if !txCfg.Offline { + if !common.GetTransactionConfig().Offline { conn, err = connection.Connect(ctx, npa.Network) cobra.CheckErr(err) } diff --git a/cmd/rofl/machine/show.go b/cmd/rofl/machine/show.go index 65c3ed01..243c17ce 100644 --- a/cmd/rofl/machine/show.go +++ b/cmd/rofl/machine/show.go @@ -25,42 +25,34 @@ import ( roflCommon "github.com/oasisprotocol/cli/cmd/rofl/common" ) +type machineShowOutput struct { + Name string `json:"name,omitempty"` + MachineID roflmarket.InstanceID `json:"machine_id,omitempty"` + Machine *roflmarket.Instance `json:"machine,omitempty"` + MachineCommands []*roflmarket.QueuedCommand `json:"machine_commands,omitempty"` + Provider *roflmarket.Provider `json:"provider,omitempty"` + Replica *rofl.Registration `json:"replica,omitempty"` +} + var showCmd = &cobra.Command{ - Use: "show []", + Use: "show [ | :]", Short: "Show information about a machine", Args: cobra.MaximumNArgs(1), Run: func(_ *cobra.Command, args []string) { - manifest, deployment, npa := roflCommon.LoadManifestAndSetNPA(&roflCommon.ManifestOptions{ + var out machineShowOutput + _, machineName, machineID, _, extraCfg, providerAddr, npa := resolveMachineManifestNpa(args, &roflCommon.ManifestOptions{ NeedAppID: true, NeedAdmin: false, }) - - machine, machineName, machineID := resolveMachine(args, deployment) - - var appID rofl.AppID - if err := appID.UnmarshalText([]byte(deployment.AppID)); err != nil { - cobra.CheckErr(fmt.Sprintf("malformed app id: %s", err)) - } - - extraCfg, err := roflCmdBuild.ValidateApp(manifest, roflCmdBuild.ValidationOpts{ - Offline: true, - }) - if err != nil { - cobra.CheckErr(fmt.Sprintf("failed to validate app: %s", err)) - } + out.Name = machineName + out.MachineID = machineID // Establish connection with the target network. ctx := context.Background() conn, err := connection.Connect(ctx, npa.Network) cobra.CheckErr(err) - // Resolve provider address. - providerAddr, _, err := common.ResolveLocalAccountOrAddress(npa.Network, machine.Provider) - if err != nil { - cobra.CheckErr(fmt.Sprintf("Invalid provider address: %s", err)) - } - - insDsc, err := conn.Runtime(npa.ParaTime).ROFLMarket.Instance(ctx, client.RoundLatest, *providerAddr, machineID) + out.Machine, err = conn.Runtime(npa.ParaTime).ROFLMarket.Instance(ctx, client.RoundLatest, *providerAddr, out.MachineID) if err != nil { // The "instance not found" error originates from Rust code, so we can't compare it nicely here. if strings.Contains(err.Error(), "instance not found") { @@ -73,152 +65,156 @@ var showCmd = &cobra.Command{ } cobra.CheckErr(err) } - if common.OutputFormat() == common.FormatJSON { - data, err := json.MarshalIndent(insDsc, "", " ") - cobra.CheckErr(err) - fmt.Printf("%s\n", data) - return - } - insCmds, err := conn.Runtime(npa.ParaTime).ROFLMarket.InstanceCommands(ctx, client.RoundLatest, *providerAddr, machineID) + out.MachineCommands, err = conn.Runtime(npa.ParaTime).ROFLMarket.InstanceCommands(ctx, client.RoundLatest, *providerAddr, out.MachineID) cobra.CheckErr(err) - providerDsc, err := conn.Runtime(npa.ParaTime).ROFLMarket.Provider(ctx, client.RoundLatest, *providerAddr) + out.Provider, err = conn.Runtime(npa.ParaTime).ROFLMarket.Provider(ctx, client.RoundLatest, *providerAddr) cobra.CheckErr(err) - var schedulerDsc *rofl.Registration - switch schedulerRAKRaw, ok := insDsc.Metadata[scheduler.MetadataKeySchedulerRAK]; ok { + switch schedulerRAKRaw, ok := out.Machine.Metadata[scheduler.MetadataKeySchedulerRAK]; ok { case true: var schedulerRAK ed25519.PublicKey if err := schedulerRAK.UnmarshalText([]byte(schedulerRAKRaw)); err != nil { - cobra.CheckErr(fmt.Sprintf("Malformed scheduler RAK metadata: %s", err)) + cobra.CheckErr(fmt.Errorf("malformed scheduler RAK metadata: %w", err)) } pk := types.PublicKey{PublicKey: schedulerRAK} - schedulerDsc, _ = conn.Runtime(npa.ParaTime).ROFL.AppInstance(ctx, client.RoundLatest, providerDsc.SchedulerApp, pk) + out.Replica, _ = conn.Runtime(npa.ParaTime).ROFL.AppInstance(ctx, client.RoundLatest, out.Provider.SchedulerApp, pk) default: } - paidUntil := time.Unix(int64(insDsc.PaidUntil), 0) - expired := !time.Now().Before(paidUntil) - - fmt.Printf("Name: %s\n", machineName) - fmt.Printf("Provider: %s\n", insDsc.Provider) - fmt.Printf("ID: %s\n", insDsc.ID) - fmt.Printf("Offer: %s\n", insDsc.Offer) - fmt.Printf("Status: %s", insDsc.Status) - if expired { - fmt.Printf(" (EXPIRED)") - } - fmt.Println() - fmt.Printf("Creator: %s\n", insDsc.Creator) - fmt.Printf("Admin: %s\n", insDsc.Admin) - switch insDsc.NodeID { - case nil: - fmt.Printf("Node ID: \n") - default: - fmt.Printf("Node ID: %s\n", insDsc.NodeID) + if common.OutputFormat() == common.FormatJSON { + data, err := json.MarshalIndent(out, "", " ") + cobra.CheckErr(err) + fmt.Printf("%s\n", data) + } else { + prettyPrintMachine(npa, &out, extraCfg) } + }, +} - fmt.Printf("Created at: %s\n", time.Unix(int64(insDsc.CreatedAt), 0)) - fmt.Printf("Updated at: %s\n", time.Unix(int64(insDsc.UpdatedAt), 0)) - fmt.Printf("Paid until: %s\n", paidUntil) +// prettyPrintMachine prints a compact human-readable info of the ROFL machine. +func prettyPrintMachine(npa *common.NPASelection, out *machineShowOutput, extraCfg *roflCmdBuild.AppExtraConfig) { + paidUntil := time.Unix(int64(out.Machine.PaidUntil), 0) //nolint:gosec + expired := !time.Now().Before(paidUntil) + + fmt.Printf("Name: %s\n", out.Name) + fmt.Printf("Provider: %s\n", out.Machine.Provider) + fmt.Printf("ID: %s\n", out.Machine.ID) + fmt.Printf("Offer: %s\n", out.Machine.Offer) + fmt.Printf("Status: %s", out.Machine.Status) + if expired { + fmt.Printf(" (EXPIRED)") + } + fmt.Println() + fmt.Printf("Creator: %s\n", out.Machine.Creator) + fmt.Printf("Admin: %s\n", out.Machine.Admin) + switch out.Machine.NodeID { + case nil: + fmt.Printf("Node ID: \n") + default: + fmt.Printf("Node ID: %s\n", out.Machine.NodeID) + } - if schedulerDsc != nil { - if proxyDomain, ok := schedulerDsc.Metadata[scheduler.MetadataKeyProxyDomain]; ok { - numericMachineID := binary.BigEndian.Uint64(machineID[:]) - proxyDomain = fmt.Sprintf("m%d.%s", numericMachineID, proxyDomain) + fmt.Printf("Created at: %s\n", time.Unix(int64(out.Machine.CreatedAt), 0)) //nolint:gosec + fmt.Printf("Updated at: %s\n", time.Unix(int64(out.Machine.UpdatedAt), 0)) //nolint:gosec + fmt.Printf("Paid until: %s\n", paidUntil) - fmt.Printf("Proxy:\n") - fmt.Printf(" Domain: %s\n", proxyDomain) + if out.Replica != nil { + if proxyDomain, ok := out.Replica.Metadata[scheduler.MetadataKeyProxyDomain]; ok { + numericMachineID := binary.BigEndian.Uint64(out.MachineID[:]) + proxyDomain = fmt.Sprintf("m%d.%s", numericMachineID, proxyDomain) - showMachinePorts(extraCfg, appID, insDsc, proxyDomain) - } + fmt.Printf("Proxy:\n") + fmt.Printf(" Domain: %s\n", proxyDomain) + + prettyPrintMachinePorts(extraCfg, out.Machine.Deployment.AppID, out.Machine, proxyDomain) } + } - if len(insDsc.Metadata) > 0 { - fmt.Printf("Metadata:\n") - for key, value := range insDsc.Metadata { - fmt.Printf(" %s: %s\n", key, value) - } + if len(out.Machine.Metadata) > 0 { + fmt.Printf("Metadata:\n") + for key, value := range out.Machine.Metadata { + fmt.Printf(" %s: %s\n", key, value) } + } - fmt.Printf("Resources:\n") + fmt.Printf("Resources:\n") - fmt.Printf(" TEE: ") - switch insDsc.Resources.TEE { - case roflmarket.TeeTypeSGX: - fmt.Printf("Intel SGX\n") - case roflmarket.TeeTypeTDX: - fmt.Printf("Intel TDX\n") - default: - fmt.Printf("[unknown: %d]\n", insDsc.Resources.TEE) - } + fmt.Printf(" TEE: ") + switch out.Machine.Resources.TEE { + case roflmarket.TeeTypeSGX: + fmt.Printf("Intel SGX\n") + case roflmarket.TeeTypeTDX: + fmt.Printf("Intel TDX\n") + default: + fmt.Printf("[unknown: %d]\n", out.Machine.Resources.TEE) + } - fmt.Printf(" Memory: %d MiB\n", insDsc.Resources.Memory) - fmt.Printf(" vCPUs: %d\n", insDsc.Resources.CPUCount) - fmt.Printf(" Storage: %d MiB\n", insDsc.Resources.Storage) - if insDsc.Resources.GPU != nil { - fmt.Printf(" GPU:\n") - if insDsc.Resources.GPU.Model != "" { - fmt.Printf(" Model: %s\n", insDsc.Resources.GPU.Model) - } else { - fmt.Printf(" Model: \n") - } - fmt.Printf(" Count: %d\n", insDsc.Resources.GPU.Count) + fmt.Printf(" Memory: %d MiB\n", out.Machine.Resources.Memory) + fmt.Printf(" vCPUs: %d\n", out.Machine.Resources.CPUCount) + fmt.Printf(" Storage: %d MiB\n", out.Machine.Resources.Storage) + if out.Machine.Resources.GPU != nil { + fmt.Printf(" GPU:\n") + if out.Machine.Resources.GPU.Model != "" { + fmt.Printf(" Model: %s\n", out.Machine.Resources.GPU.Model) + } else { + fmt.Printf(" Model: \n") } + fmt.Printf(" Count: %d\n", out.Machine.Resources.GPU.Count) + } - switch insDsc.Deployment { - default: - fmt.Printf("Deployment:\n") - fmt.Printf(" App ID: %s\n", insDsc.Deployment.AppID) + switch out.Machine.Deployment { + default: + fmt.Printf("Deployment:\n") + fmt.Printf(" App ID: %s\n", out.Machine.Deployment.AppID) - if len(insDsc.Deployment.Metadata) > 0 { - fmt.Printf(" Metadata:\n") - for key, value := range insDsc.Deployment.Metadata { - fmt.Printf(" %s: %s\n", key, value) - } + if len(out.Machine.Deployment.Metadata) > 0 { + fmt.Printf(" Metadata:\n") + for key, value := range out.Machine.Deployment.Metadata { + fmt.Printf(" %s: %s\n", key, value) } - case nil: - fmt.Printf("Deployment: \n") } + case nil: + fmt.Printf("Deployment: \n") + } - // Show commands. - fmt.Printf("Commands:\n") - if len(insCmds) > 0 { - for _, qc := range insCmds { - fmt.Printf(" - ID: %s\n", qc.ID) - - var cmd scheduler.Command - err := cbor.Unmarshal(qc.Cmd, &cmd) - switch err { - case nil: - // Decodable scheduler command. - fmt.Printf(" Method: %s\n", cmd.Method) - fmt.Printf(" Args:\n") - - switch cmd.Method { - case scheduler.MethodDeploy: - showCommandArgs(npa, cmd.Args, scheduler.DeployRequest{}) - case scheduler.MethodRestart: - showCommandArgs(npa, cmd.Args, scheduler.RestartRequest{}) - case scheduler.MethodTerminate: - showCommandArgs(npa, cmd.Args, scheduler.TerminateRequest{}) - default: - showCommandArgs(npa, cmd.Args, make(map[string]any)) - } + // Show commands. + fmt.Printf("Commands:\n") + if len(out.MachineCommands) > 0 { + for _, qc := range out.MachineCommands { + fmt.Printf(" - ID: %s\n", qc.ID) + + var cmd scheduler.Command + err := cbor.Unmarshal(qc.Cmd, &cmd) + switch err { + case nil: + // Decodable scheduler command. + fmt.Printf(" Method: %s\n", cmd.Method) + fmt.Printf(" Args:\n") + + switch cmd.Method { + case scheduler.MethodDeploy: + showCommandArgs(npa, cmd.Args, scheduler.DeployRequest{}) + case scheduler.MethodRestart: + showCommandArgs(npa, cmd.Args, scheduler.RestartRequest{}) + case scheduler.MethodTerminate: + showCommandArgs(npa, cmd.Args, scheduler.TerminateRequest{}) default: - // Unknown command format. - fmt.Printf(" \n", qc.Cmd) + showCommandArgs(npa, cmd.Args, make(map[string]any)) } + default: + // Unknown command format. + fmt.Printf(" \n", qc.Cmd) } - } else { - fmt.Printf(" \n") } - }, + } else { + fmt.Printf(" \n") + } } -func showMachinePorts(extraCfg *roflCmdBuild.AppExtraConfig, appID rofl.AppID, insDsc *roflmarket.Instance, domain string) { +func prettyPrintMachinePorts(extraCfg *roflCmdBuild.AppExtraConfig, appID rofl.AppID, insDsc *roflmarket.Instance, domain string) { if extraCfg == nil || len(extraCfg.Ports) == 0 { return }