Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cli overhaul: snapshot #212

Merged
merged 15 commits into from
Oct 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cli/command/create/create-acmeaccount.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ var create_acmeaccountCmd = &cobra.Command{
The config can be set with the --file flag or piped from stdin.
For config examples see "example acmeaccount"`,
RunE: func(cmd *cobra.Command, args []string) (err error) {
id := cli.ValidateIDset(args, 0, "AcmeAccountID")
id := cli.RequiredIDset(args, 0, "AcmeAccountID")
config, err := proxmox.NewConfigAcmeAccountFromJson(cli.NewConfig())
if err != nil {
return
Expand Down
2 changes: 1 addition & 1 deletion cli/command/create/create-pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ var create_poolCmd = &cobra.Command{
Use: "pool POOLID [COMMENT]",
Short: "Creates a new pool",
RunE: func(cmd *cobra.Command, args []string) (err error) {
id := cli.ValidateIDset(args, 0, "PoolID")
id := cli.RequiredIDset(args, 0, "PoolID")
var comment string
if len(args) > 1 {
comment = args[1]
Expand Down
39 changes: 39 additions & 0 deletions cli/command/create/create-snapshot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package create

import (
"github.com/Telmate/proxmox-api-go/cli"
"github.com/Telmate/proxmox-api-go/proxmox"
"github.com/spf13/cobra"
)

var (
// flag needs to be reset, as this value will persist during tests
memory bool
create_snapshotCmd = &cobra.Command{
Use: "snapshot GUESTID SNAPSHOTNAME [DESCRIPTION]",
Short: "Creates a new snapshot of the specefied guest",
TraverseChildren: true,
Args: cobra.RangeArgs(2, 3),
RunE: func(cmd *cobra.Command, args []string) (err error) {
id := cli.ValidateIntIDset(args, "GuestID")
snapName := cli.RequiredIDset(args, 1, "SnapshotName")
config := proxmox.ConfigSnapshot{
Name: snapName,
Description: cli.OptionalIDset(args, 2),
VmState: memory,
}
memory = false
err = config.CreateSnapshot(uint(id), cli.NewClient())
if err != nil {
return
}
cli.PrintItemCreated(CreateCmd.OutOrStdout(), snapName, "Snapshot")
return
},
}
)

func init() {
CreateCmd.AddCommand(create_snapshotCmd)
create_snapshotCmd.Flags().BoolVar(&memory, "memory", false, "Snapshot memory")
}
2 changes: 1 addition & 1 deletion cli/command/create/create-storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ var create_storageCmd = &cobra.Command{
The config can be set with the --file flag or piped from stdin.
For config examples see "example storage"`,
RunE: func(cmd *cobra.Command, args []string) (err error) {
id := cli.ValidateIDset(args, 0, "StorageID")
id := cli.RequiredIDset(args, 0, "StorageID")
config, err := proxmox.NewConfigStorageFromJson(cli.NewConfig())
if err != nil {
return
Expand Down
2 changes: 1 addition & 1 deletion cli/command/create/guest/create-guest.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func init() {

func createGuest(args []string, IDtype string) (err error) {
id := cli.ValidateIntIDset(args, IDtype+"ID")
node := cli.ValidateIDset(args, 1, "NodeID")
node := cli.RequiredIDset(args, 1, "NodeID")
vmr := proxmox.NewVmRef(id)
vmr.SetNode(node)
c := cli.NewClient()
Expand Down
30 changes: 30 additions & 0 deletions cli/command/delete/delete-snapshot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package delete

import (
"github.com/Telmate/proxmox-api-go/cli"
"github.com/Telmate/proxmox-api-go/proxmox"
"github.com/spf13/cobra"
)

var (
delete_snapshotCmd = &cobra.Command{
Use: "snapshot GUESTID SNAPSHOTNAME",
Short: "Deletes the Speciefied snapshot",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) (err error) {
id := cli.ValidateIntIDset(args, "GuestID")
snapName := cli.RequiredIDset(args, 1, "SnapshotName")
c := cli.NewClient()
_, err = c.DeleteSnapshot(proxmox.NewVmRef(id), snapName)
if err != nil {
return
}
cli.PrintItemDeleted(deleteCmd.OutOrStdout(), snapName, "Snapshot")
return
},
}
)

func init() {
deleteCmd.AddCommand(delete_snapshotCmd)
}
2 changes: 1 addition & 1 deletion cli/command/delete/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func init() {

func deleteID(args []string, IDtype string) (err error) {
var exitStatus string
id := cli.ValidateIDset(args, 0, IDtype+"ID")
id := cli.RequiredIDset(args, 0, IDtype+"ID")
c := cli.NewClient()
switch IDtype {
case "AcmeAccount":
Expand Down
2 changes: 1 addition & 1 deletion cli/command/get/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func init() {
}

func getConfig(args []string, IDtype string) (err error) {
id := cli.ValidateIDset(args, 0, IDtype+"ID")
id := cli.RequiredIDset(args, 0, IDtype+"ID")
c := cli.NewClient()
var config interface{}
switch IDtype {
Expand Down
29 changes: 29 additions & 0 deletions cli/command/guest/guest-rollback.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package guest

import (
"fmt"

"github.com/Telmate/proxmox-api-go/cli"
"github.com/Telmate/proxmox-api-go/proxmox"
"github.com/spf13/cobra"
)

var guest_rollbackCmd = &cobra.Command{
Use: "rollback GUESTID SNAPSHOT",
Short: "Shuts the speciefid guest down",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) (err error) {
vmr := proxmox.NewVmRef(cli.ValidateIntIDset(args, "GuestID"))
snapName := cli.RequiredIDset(args, 1, "SnapshotName")
c := cli.NewClient()
_, err = c.RollbackSnapshot(vmr, snapName)
if err == nil {
fmt.Fprintf(GuestCmd.OutOrStdout(), "Guest with id (%d) has been rolled back to snapshot (%s)\n", vmr.VmId(), snapName)
}
return
},
}

func init() {
GuestCmd.AddCommand(guest_rollbackCmd)
}
55 changes: 31 additions & 24 deletions cli/command/list/list-snapshots.go
Original file line number Diff line number Diff line change
@@ -1,37 +1,44 @@
package list

import (
"fmt"
"github.com/Telmate/proxmox-api-go/cli"
"github.com/Telmate/proxmox-api-go/proxmox"
"github.com/spf13/cobra"
)

var list_snapshotsCmd = &cobra.Command{
Use: "snapshots GuestID",
Short: "Prints a list of QemuSnapshots in raw json format",
Run: func(cmd *cobra.Command, args []string) {
id := cli.ValidateExistinGuestID(args, 0)
c := cli.NewClient()
vmr := proxmox.NewVmRef(id)
_, err := c.GetVmInfo(vmr)
cli.LogFatalError(err)
jbody, _, err := c.ListQemuSnapshot(vmr)
cli.LogFatalError(err)
temp := jbody["data"].([]interface{})
if len(temp) == 1 {
fmt.Printf("Guest with ID (%d) has no snapshots",id)
} else {
for _, e := range temp {
snapshotName := e.(map[string]interface{})["name"].(string)
if snapshotName != "current" {
fmt.Println(snapshotName)
}
var (
// flag needs to be reset, as this value will persist during tests
noTree bool
list_snapshotsCmd = &cobra.Command{
Use: "snapshots GuestID",
Short: "Prints a list of QemuSnapshots in json format",
TraverseChildren: true,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) (err error) {
id := cli.ValidateExistinGuestID(args, 0)
jbody, err := cli.NewClient().ListSnapshots(proxmox.NewVmRef(id))
if err != nil {
noTree = false
return
}
}
},
}
var list []*proxmox.Snapshot
if noTree {
noTree = false
list = proxmox.FormatSnapshotsList(jbody)
} else {
list = proxmox.FormatSnapshotsTree(jbody)
}
if len(list) == 0 {
listCmd.Printf("Guest with ID (%d) has no snapshots", id)
} else {
cli.PrintFormattedJson(listCmd.OutOrStdout(), list)
}
return
},
}
)

func init() {
listCmd.AddCommand(list_snapshotsCmd)
list_snapshotsCmd.Flags().BoolVar(&noTree, "no-tree", false, "Format output as list instead of a tree.")
}
2 changes: 1 addition & 1 deletion cli/command/node/node-reboot.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ var reboot_nodeCmd = &cobra.Command{
Use: "reboot NODE",
Short: "Reboots the specified node",
RunE: func(cmd *cobra.Command, args []string) (err error) {
node := cli.ValidateIDset(args, 0, "node")
node := cli.RequiredIDset(args, 0, "node")
c := cli.NewClient()
_, err = c.RebootNode(node)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion cli/command/node/node-shutdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ var shutdown_nodeCmd = &cobra.Command{
Use: "shutdown NODE",
Short: "Shuts the specified node down",
RunE: func(cmd *cobra.Command, args []string) (err error) {
node := cli.ValidateIDset(args, 0, "node")
node := cli.RequiredIDset(args, 0, "node")
c := cli.NewClient()
_, err = c.ShutdownNode(node)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions cli/command/set/set-metricserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Depending on the current state of the MetricServer, the MetricServer will be cre
The config can be set with the --file flag or piped from stdin.
For config examples see "example metricserver"`,
RunE: func(cmd *cobra.Command, args []string) (err error) {
id := cli.ValidateIDset(args, 0,"MetricServerID")
id := cli.RequiredIDset(args, 0, "MetricServerID")
config, err := proxmox.NewConfigMetricsFromJson(cli.NewConfig())
if err != nil {
return
Expand All @@ -24,7 +24,7 @@ For config examples see "example metricserver"`,
if err != nil {
return
}
cli.PrintItemSet(setCmd.OutOrStdout() ,id ,"MericServer")
cli.PrintItemSet(setCmd.OutOrStdout(), id, "MericServer")
return
},
}
Expand Down
4 changes: 2 additions & 2 deletions cli/command/set/set-user.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Depending on the current state of the user, the user will be created or updated.
The config can be set with the --file flag or piped from stdin.
For config examples see "example user"`,
RunE: func(cmd *cobra.Command, args []string) (err error) {
id := cli.ValidateIDset(args, 0, "UserID")
id := cli.RequiredIDset(args, 0, "UserID")
config, err := proxmox.NewConfigUserFromJson(cli.NewConfig())
if err != nil {
return
Expand All @@ -28,7 +28,7 @@ For config examples see "example user"`,
if err != nil {
return
}
cli.PrintItemSet(setCmd.OutOrStdout() ,id ,"User")
cli.PrintItemSet(setCmd.OutOrStdout(), id, "User")
return
},
}
Expand Down
6 changes: 3 additions & 3 deletions cli/command/update/update-poolcomment.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import (
var update_poolCmd = &cobra.Command{
Use: "poolcomment POOLID [COMMENT]",
Short: "Updates the comment on the speciefied pool",
RunE: func(cmd *cobra.Command, args []string) (err error){
RunE: func(cmd *cobra.Command, args []string) (err error) {
var comment string
id := cli.ValidateIDset(args, 0, "PoolID")
id := cli.RequiredIDset(args, 0, "PoolID")
if len(args) > 1 {
comment = args[1]
}
Expand All @@ -19,7 +19,7 @@ var update_poolCmd = &cobra.Command{
if err != nil {
return
}
cli.PrintItemUpdated(updateCmd.OutOrStdout() ,id, "PoolComment")
cli.PrintItemUpdated(updateCmd.OutOrStdout(), id, "PoolComment")
return
},
}
Expand Down
28 changes: 28 additions & 0 deletions cli/command/update/update-snapshotdescription.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package update

import (
"github.com/Telmate/proxmox-api-go/cli"
"github.com/Telmate/proxmox-api-go/proxmox"
"github.com/spf13/cobra"
)

var update_snapshotCmd = &cobra.Command{
Use: "snapshot GUESTID SNAPSHOTNAME [DESCRIPTION]",
Short: "Updates the description on the speciefied snapshot",
Args: cobra.RangeArgs(2, 3),
RunE: func(cmd *cobra.Command, args []string) (err error) {
id := cli.ValidateIntIDset(args, "GuestID")
snapName := cli.RequiredIDset(args, 1, "SnapshotName")
des := cli.OptionalIDset(args, 2)
err = cli.NewClient().UpdateSnapshotDescription(proxmox.NewVmRef(id), snapName, des)
if err != nil {
return
}
cli.PrintItemUpdated(updateCmd.OutOrStdout(), snapName, "Snapshot")
return
},
}

func init() {
updateCmd.AddCommand(update_snapshotCmd)
}
2 changes: 1 addition & 1 deletion cli/command/update/update-storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ var update_storageCmd = &cobra.Command{
The config can be set with the --file flag or piped from stdin.
For config examples see "example storage"`,
RunE: func(cmd *cobra.Command, args []string) (err error) {
id := cli.ValidateIDset(args, 0, "StorageID")
id := cli.RequiredIDset(args, 0, "StorageID")
config, err := proxmox.NewConfigStorageFromJson(cli.NewConfig())
if err != nil {
return
Expand Down
21 changes: 16 additions & 5 deletions cli/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,34 @@ import (
"strconv"
)

func ValidateIDset(args []string, indexPos int, text string) string {
if indexPos+1 > len(args) {
// Should be used for Required IDs.
// returns if the indexd arg if it is set. It throws and error when the indexed arg is not set.
func RequiredIDset(args []string, indexPos uint, text string) string {
if int(indexPos+1) > len(args) {
log.Fatal(fmt.Errorf("error: no %s has been provided", text))
}
return args[indexPos]
}

// Should be used for Optional IDs.
// returns if the indexd arg if it is set. It returns an empty string when the indexed arg is not set.
func OptionalIDset(args []string, indexPos uint) (out string) {
if int(indexPos+1) <= len(args) {
out = args[indexPos]
}
return
}

func ValidateIntIDset(args []string, text string) int {
id, err := strconv.Atoi(ValidateIDset(args, 0, text))
id, err := strconv.Atoi(RequiredIDset(args, 0, text))
if err != nil && id <= 0 {
log.Fatal(fmt.Errorf("error: %s must be a positive integer", text))
}
return id
}

func ValidateExistinGuestID(args []string, indexPos int) int {
id, err := strconv.Atoi(ValidateIDset(args, indexPos, "GuestID"))
func ValidateExistinGuestID(args []string, indexPos uint) int {
id, err := strconv.Atoi(RequiredIDset(args, indexPos, "GuestID"))
if err != nil || id < 100 {
log.Fatal(fmt.Errorf("error: GuestID must be a positive integer of 100 or greater"))
}
Expand Down
Loading