@@ -8,94 +8,126 @@ import (
88 "strings"
99
1010 "github.com/spf13/cobra"
11+ "github.com/spf13/pflag"
1112
1213 "github.com/netapp/trident/cli/api"
14+ "github.com/netapp/trident/pkg/convert"
1315 "github.com/netapp/trident/utils/errors"
1416)
1517
1618var (
1719 allSnapshots bool
1820 allSnapshotsInVolume string
21+ allSnapshotsInGroup string
22+
23+ // deleteSnapshotFlagValues is used to store the REST API URL parameters for the 'delete snapshot' command.
24+ deleteSnapshotFlagValues map [string ]string
1925)
2026
2127func init () {
2228 deleteCmd .AddCommand (deleteSnapshotCmd )
23- deleteSnapshotCmd .Flags ().BoolVar (& allSnapshots , "all" , false , "Delete all snapshots" )
29+ deleteSnapshotCmd .Flags ().BoolVarP (& allSnapshots , "all" , "a " , false , "Delete all snapshots" )
2430 deleteSnapshotCmd .Flags ().StringVar (& allSnapshotsInVolume , "volume" , "" , "Delete all snapshots in volume" )
31+ deleteSnapshotCmd .Flags ().StringVar (& allSnapshotsInGroup , "group" , "" , "Delete all snapshots in a group" )
32+
33+ // Only one of these flags may be specified at a time.
34+ deleteSnapshotCmd .MarkFlagsMutuallyExclusive ("volume" , "group" , "all" )
2535}
2636
2737var deleteSnapshotCmd = & cobra.Command {
2838 Use : "snapshot <volume/snapshot> [<volume/snapshot>...]" ,
2939 Short : "Delete one or more volume snapshots from Trident" ,
3040 Aliases : []string {"s" , "snap" , "snapshots" },
3141 RunE : func (cmd * cobra.Command , args []string ) error {
42+ // Build a map of URL parameters for the 'delete snapshot' command.
43+ deleteSnapshotFlagValues = make (map [string ]string )
44+ cmd .Flags ().Visit (func (flag * pflag.Flag ) {
45+ // Store the flag name and value in deleteSnapshotURLVar for use in REST API calls.
46+ deleteSnapshotFlagValues [flag .Name ] = flag .Value .String ()
47+ })
48+
3249 if OperatingMode == ModeTunnel {
3350 command := []string {"delete" , "snapshot" }
34- if allSnapshotsInVolume != "" {
35- command = append (command , "--volume" , allSnapshotsInVolume )
51+
52+ volume , ok := deleteSnapshotFlagValues ["volume" ]
53+ if ok && volume != "" {
54+ command = append (command , "--volume" , volume )
3655 }
37- if allSnapshots {
56+
57+ group , ok := deleteSnapshotFlagValues ["group" ]
58+ if ok && group != "" {
59+ // If a group is specified, we delete all snapshots in that group.
60+ // This typically isn't recommended, but we'll allow it for exceptional cases where
61+ // the group snapshot has been lost and the admin needs to clean up.
62+ command = append (command , "--group" , group )
63+ }
64+
65+ all , ok := deleteSnapshotFlagValues ["all" ]
66+ if ok && convert .ToBool (all ) {
3867 command = append (command , "--all" )
3968 }
69+
70+ // Fail if a mix of flags is used that doesn't make sense. This should be caught by the CLI framework,
71+ // but in the case it's not, check here.
72+ if volume != "" && group != "" {
73+ return errors .InvalidInputError ("cannot specify both --volume and --group flags" )
74+ } else if volume != "" && convert .ToBool (all ) {
75+ return errors .InvalidInputError ("cannot specify --volume flag and --all flag" )
76+ } else if group != "" && convert .ToBool (all ) {
77+ return errors .InvalidInputError ("cannot specify --group flag and --all flag" )
78+ }
79+
4080 out , err := TunnelCommand (append (command , args ... ))
4181 printOutput (cmd , out , err )
4282 return err
43- } else {
44- return snapshotDelete (args )
4583 }
84+
85+ return snapshotDelete (args )
4686 },
4787}
4888
4989func snapshotDelete (snapshotIDs []string ) error {
50- var err error
51-
52- if allSnapshotsInVolume != "" {
53- // Make sure --volume isn't being used along with specific snapshots
54- if len (snapshotIDs ) > 0 {
55- return errors .New ("cannot use --volume switch and specify individual snapshots" )
56- }
90+ // The --all switch cannot be used with specific snapshot IDs.
91+ if all , _ := deleteSnapshotFlagValues ["all" ]; convert .ToBool (all ) && len (snapshotIDs ) > 0 {
92+ return errors .InvalidInputError ("cannot use --all switch with individual snapshots" )
93+ }
5794
58- // Get list of snapshot IDs in the specified volume so we can delete them all
59- snapshotIDs , err = GetSnapshots (allSnapshotsInVolume )
60- if err != nil {
61- return err
62- }
95+ // The --volume switch cannot be used with specific snapshot IDs.
96+ if volume , _ := deleteSnapshotFlagValues ["volume" ]; volume != "" && len (snapshotIDs ) > 0 {
97+ return errors .InvalidInputError ("cannot use --volume switch with individual snapshots" )
98+ }
6399
64- } else if allSnapshots {
65- // Make sure --all isn't being used along with specific snapshots
66- if len (snapshotIDs ) > 0 {
67- return errors .New ("cannot use --all switch and specify individual snapshots" )
68- }
100+ // The --group switch cannot be used with specific snapshot IDs.
101+ if group , _ := deleteSnapshotFlagValues ["group" ]; group != "" && len (snapshotIDs ) > 0 {
102+ return errors .InvalidInputError ("cannot use --group switch with individual snapshots" )
103+ }
69104
70- // Get list of snapshot IDs so we can delete them all
71- snapshotIDs , err = GetSnapshots ("" )
105+ // If some snapshots were specified, we'll delete those.
106+ var err error
107+ if len (snapshotIDs ) == 0 {
108+ snapshotIDs , err = GetSnapshots (buildSnapshotURL (deleteSnapshotFlagValues ))
72109 if err != nil {
73110 return err
74111 }
75- } else {
76- // Not using --all or --volume, each snapshot must have volume specified
77- if len (snapshotIDs ) == 0 {
78- return errors .New ("volume/snapshot not specified" )
79- }
80- for _ , snapshotID := range snapshotIDs {
81- if ! strings .ContainsRune (snapshotID , '/' ) {
82- return errors .InvalidInputError (fmt .Sprintf ("invalid snapshot ID: %s; Please use the format " +
83- "<volume name>/<snapshot name>" , snapshotID ))
84- }
85- }
86112 }
87113
114+ var errs error
88115 for _ , snapshotID := range snapshotIDs {
116+ // Each snapshot must have volume specified.
117+ if ! strings .ContainsRune (snapshotID , '/' ) {
118+ return errors .InvalidInputError (fmt .Sprintf ("invalid snapshot ID: %s; Please use the format " +
119+ "<volume name>/<snapshot name>" , snapshotID ))
120+ }
121+
89122 url := BaseURL () + "/snapshot/" + snapshotID
90123
91124 response , responseBody , err := api .InvokeRESTAPI ("DELETE" , url , nil )
92125 if err != nil {
93126 return err
94127 } else if response .StatusCode != http .StatusOK {
95- return fmt .Errorf ("could not delete snapshot %s: %v" , snapshotID ,
96- GetErrorFromHTTPResponse (response , responseBody ))
128+ errs = errors .Join (errs , GetErrorFromHTTPResponse (response , responseBody ))
97129 }
98130 }
99131
100- return nil
132+ return errs
101133}
0 commit comments