github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/command/volume_deregister.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/hashicorp/nomad/api/contexts"
     8  	"github.com/posener/complete"
     9  )
    10  
    11  type VolumeDeregisterCommand struct {
    12  	Meta
    13  }
    14  
    15  func (c *VolumeDeregisterCommand) Help() string {
    16  	helpText := `
    17  Usage: nomad volume deregister [options] <id>
    18  
    19    Remove an unused volume from Nomad.
    20  
    21    When ACLs are enabled, this command requires a token with the
    22    'csi-write-volume' capability for the volume's namespace.
    23  
    24  General Options:
    25  
    26    ` + generalOptionsUsage(usageOptsDefault) + `
    27  
    28  Volume Deregister Options:
    29  
    30    -force
    31      Force deregistration of the volume and immediately drop claims for
    32      terminal allocations. Returns an error if the volume has running
    33      allocations. This does not detach the volume from client nodes.
    34  `
    35  	return strings.TrimSpace(helpText)
    36  }
    37  
    38  func (c *VolumeDeregisterCommand) AutocompleteFlags() complete.Flags {
    39  	return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
    40  		complete.Flags{
    41  			"-force": complete.PredictNothing,
    42  		})
    43  }
    44  
    45  func (c *VolumeDeregisterCommand) AutocompleteArgs() complete.Predictor {
    46  	return complete.PredictFunc(func(a complete.Args) []string {
    47  		client, err := c.Meta.Client()
    48  		if err != nil {
    49  			return nil
    50  		}
    51  
    52  		// When multiple volume types are implemented, this search should merge contexts
    53  		resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Volumes, nil)
    54  		if err != nil {
    55  			return []string{}
    56  		}
    57  		return resp.Matches[contexts.Volumes]
    58  	})
    59  }
    60  
    61  func (c *VolumeDeregisterCommand) Synopsis() string {
    62  	return "Remove a volume"
    63  }
    64  
    65  func (c *VolumeDeregisterCommand) Name() string { return "volume deregister" }
    66  
    67  func (c *VolumeDeregisterCommand) Run(args []string) int {
    68  	var force bool
    69  	flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
    70  	flags.Usage = func() { c.Ui.Output(c.Help()) }
    71  	flags.BoolVar(&force, "force", false, "Force deregister and drop claims")
    72  
    73  	if err := flags.Parse(args); err != nil {
    74  		c.Ui.Error(fmt.Sprintf("Error parsing arguments %s", err))
    75  		return 1
    76  	}
    77  
    78  	// Check that we get exactly one argument
    79  	args = flags.Args()
    80  	if l := len(args); l != 1 {
    81  		c.Ui.Error("This command takes one argument: <id>")
    82  		c.Ui.Error(commandErrorText(c))
    83  		return 1
    84  	}
    85  	volID := args[0]
    86  
    87  	// Get the HTTP client
    88  	client, err := c.Meta.Client()
    89  	if err != nil {
    90  		c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
    91  		return 1
    92  	}
    93  
    94  	// Confirm the -force flag
    95  	if force {
    96  		question := fmt.Sprintf("Are you sure you want to force deregister volume %q? [y/N]", volID)
    97  		answer, err := c.Ui.Ask(question)
    98  		if err != nil {
    99  			c.Ui.Error(fmt.Sprintf("Failed to parse answer: %v", err))
   100  			return 1
   101  		}
   102  
   103  		if answer == "" || strings.ToLower(answer)[0] == 'n' {
   104  			// No case
   105  			c.Ui.Output("Cancelling volume deregister")
   106  			return 0
   107  		} else if strings.ToLower(answer)[0] == 'y' && len(answer) > 1 {
   108  			// Non exact match yes
   109  			c.Ui.Output("For confirmation, an exact ‘y’ is required.")
   110  			return 0
   111  		} else if answer != "y" {
   112  			c.Ui.Output("No confirmation detected. For confirmation, an exact 'y' is required.")
   113  			return 1
   114  		}
   115  	}
   116  
   117  	// Deregister only works on CSI volumes, but could be extended to support other
   118  	// network interfaces or host volumes
   119  	err = client.CSIVolumes().Deregister(volID, force, nil)
   120  	if err != nil {
   121  		c.Ui.Error(fmt.Sprintf("Error deregistering volume: %s", err))
   122  		return 1
   123  	}
   124  
   125  	return 0
   126  }