Skip to content

Commit

Permalink
Merge pull request Telmate#212 from Tinyblargon/Feature-Snapshot
Browse files Browse the repository at this point in the history
Cli overhaul: snapshot
  • Loading branch information
mleone87 committed Oct 26, 2022
2 parents 63d005c + 5d38949 commit ab0efca
Show file tree
Hide file tree
Showing 24 changed files with 735 additions and 74 deletions.
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

0 comments on commit ab0efca

Please sign in to comment.