github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/command/deployment_fail.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 DeploymentFailCommand struct {
    12  	Meta
    13  }
    14  
    15  func (c *DeploymentFailCommand) Help() string {
    16  	helpText := `
    17  Usage: nomad deployment fail [options] <deployment id>
    18  
    19    Fail is used to mark a deployment as failed. Failing a deployment will
    20    stop the placement of new allocations as part of rolling deployment and
    21    if the job is configured to auto revert, the job will attempt to roll back to a
    22    stable version.
    23  
    24    When ACLs are enabled, this command requires a token with the 'submit-job'
    25    and 'read-job' capabilities for the deployment's namespace.
    26  
    27  General Options:
    28  
    29    ` + generalOptionsUsage(usageOptsDefault) + `
    30  
    31  Fail Options:
    32  
    33    -detach
    34      Return immediately instead of entering monitor mode. After deployment
    35      resume, the evaluation ID will be printed to the screen, which can be used
    36      to examine the evaluation using the eval-status command.
    37  
    38    -verbose
    39      Display full information.
    40  `
    41  	return strings.TrimSpace(helpText)
    42  }
    43  
    44  func (c *DeploymentFailCommand) Synopsis() string {
    45  	return "Manually fail a deployment"
    46  }
    47  
    48  func (c *DeploymentFailCommand) AutocompleteFlags() complete.Flags {
    49  	return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
    50  		complete.Flags{
    51  			"-detach":  complete.PredictNothing,
    52  			"-verbose": complete.PredictNothing,
    53  		})
    54  }
    55  
    56  func (c *DeploymentFailCommand) AutocompleteArgs() complete.Predictor {
    57  	return complete.PredictFunc(func(a complete.Args) []string {
    58  		client, err := c.Meta.Client()
    59  		if err != nil {
    60  			return nil
    61  		}
    62  
    63  		resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Deployments, nil)
    64  		if err != nil {
    65  			return []string{}
    66  		}
    67  		return resp.Matches[contexts.Deployments]
    68  	})
    69  }
    70  
    71  func (c *DeploymentFailCommand) Name() string { return "deployment fail" }
    72  
    73  func (c *DeploymentFailCommand) Run(args []string) int {
    74  	var detach, verbose bool
    75  
    76  	flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
    77  	flags.Usage = func() { c.Ui.Output(c.Help()) }
    78  	flags.BoolVar(&detach, "detach", false, "")
    79  	flags.BoolVar(&verbose, "verbose", false, "")
    80  
    81  	if err := flags.Parse(args); err != nil {
    82  		return 1
    83  	}
    84  
    85  	// Check that we got one argument
    86  	args = flags.Args()
    87  	if l := len(args); l != 1 {
    88  		c.Ui.Error("This command takes one argument: <deployment id>")
    89  		c.Ui.Error(commandErrorText(c))
    90  		return 1
    91  	}
    92  
    93  	dID := args[0]
    94  
    95  	// Truncate the id unless full length is requested
    96  	length := shortId
    97  	if verbose {
    98  		length = fullId
    99  	}
   100  
   101  	// Get the HTTP client
   102  	client, err := c.Meta.Client()
   103  	if err != nil {
   104  		c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
   105  		return 1
   106  	}
   107  
   108  	// Do a prefix lookup
   109  	deploy, possible, err := getDeployment(client.Deployments(), dID)
   110  	if err != nil {
   111  		c.Ui.Error(fmt.Sprintf("Error retrieving deployment: %s", err))
   112  		return 1
   113  	}
   114  
   115  	if len(possible) != 0 {
   116  		c.Ui.Error(fmt.Sprintf("Prefix matched multiple deployments\n\n%s", formatDeployments(possible, length)))
   117  		return 1
   118  	}
   119  
   120  	u, _, err := client.Deployments().Fail(deploy.ID, nil)
   121  	if err != nil {
   122  		c.Ui.Error(fmt.Sprintf("Error failing deployment: %s", err))
   123  		return 1
   124  	}
   125  
   126  	if u.RevertedJobVersion == nil {
   127  		c.Ui.Output(fmt.Sprintf("Deployment %q failed", deploy.ID))
   128  	} else {
   129  		c.Ui.Output(fmt.Sprintf("Deployment %q failed. Auto-reverted to job version %d.", deploy.ID, *u.RevertedJobVersion))
   130  	}
   131  
   132  	evalCreated := u.EvalID != ""
   133  
   134  	// Nothing to do
   135  	if !evalCreated {
   136  		return 0
   137  	}
   138  
   139  	if detach {
   140  		c.Ui.Output("Evaluation ID: " + u.EvalID)
   141  		return 0
   142  	}
   143  
   144  	c.Ui.Output("")
   145  	mon := newMonitor(c.Ui, client, length)
   146  	return mon.monitor(u.EvalID)
   147  }