mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	kubectl-diff: Return non-1 errors on kubectl failures
Currently, diff AND kubectl can return 1 errors either when diff finds differences, or when kubectl fails something. It also prints an ugly error when diff finds a differences, since 1 is treated as an error. Two things this PR does: 1. If diff returns 1, then do not treat it as an error, and exit with exit code 1. It no longer prints the ugly error. 2. Kubectl errors are +1'd so that they never return 1 which shouldn't be considered an error. We need to update the documentation accordingly, to mention that `KUBECTL_EXTERNAL_DIFF` programs must also follow the convention of using one as their exit code for changes detected.
This commit is contained in:
		@@ -68,6 +68,15 @@ var (
 | 
				
			|||||||
// Number of times we try to diff before giving-up
 | 
					// Number of times we try to diff before giving-up
 | 
				
			||||||
const maxRetries = 4
 | 
					const maxRetries = 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// diffError returns the ExitError if the status code is less than 1,
 | 
				
			||||||
 | 
					// nil otherwise.
 | 
				
			||||||
 | 
					func diffError(err error) exec.ExitError {
 | 
				
			||||||
 | 
						if err, ok := err.(exec.ExitError); ok && err.ExitStatus() <= 1 {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type DiffOptions struct {
 | 
					type DiffOptions struct {
 | 
				
			||||||
	FilenameOptions resource.FilenameOptions
 | 
						FilenameOptions resource.FilenameOptions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -109,9 +118,20 @@ func NewCmdDiff(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.C
 | 
				
			|||||||
		Long:                  diffLong,
 | 
							Long:                  diffLong,
 | 
				
			||||||
		Example:               diffExample,
 | 
							Example:               diffExample,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			cmdutil.CheckErr(options.Complete(f, cmd))
 | 
								cmdutil.CheckDiffErr(options.Complete(f, cmd))
 | 
				
			||||||
			cmdutil.CheckErr(validateArgs(cmd, args))
 | 
								cmdutil.CheckDiffErr(validateArgs(cmd, args))
 | 
				
			||||||
			cmdutil.CheckErr(options.Run())
 | 
								// `kubectl diff` propagates the error code from
 | 
				
			||||||
 | 
								// diff or `KUBECTL_EXTERNAL_DIFF`. Also, we
 | 
				
			||||||
 | 
								// don't want to print an error if diff returns
 | 
				
			||||||
 | 
								// error code 1, which simply means that changes
 | 
				
			||||||
 | 
								// were found. We also don't want kubectl to
 | 
				
			||||||
 | 
								// return 1 if there was a problem.
 | 
				
			||||||
 | 
								if err := options.Run(); err != nil {
 | 
				
			||||||
 | 
									if exitErr := diffError(err); exitErr != nil {
 | 
				
			||||||
 | 
										os.Exit(exitErr.ExitStatus())
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									cmdutil.CheckDiffErr(err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -150,6 +170,11 @@ func (d *DiffProgram) getCommand(args ...string) (string, exec.Cmd) {
 | 
				
			|||||||
func (d *DiffProgram) Run(from, to string) error {
 | 
					func (d *DiffProgram) Run(from, to string) error {
 | 
				
			||||||
	diff, cmd := d.getCommand(from, to)
 | 
						diff, cmd := d.getCommand(from, to)
 | 
				
			||||||
	if err := cmd.Run(); err != nil {
 | 
						if err := cmd.Run(); err != nil {
 | 
				
			||||||
 | 
							// Let's not wrap diff errors, or we won't be able to
 | 
				
			||||||
 | 
							// differentiate them later.
 | 
				
			||||||
 | 
							if diffErr := diffError(err); diffErr != nil {
 | 
				
			||||||
 | 
								return diffErr
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		return fmt.Errorf("failed to run %q: %v", diff, err)
 | 
							return fmt.Errorf("failed to run %q: %v", diff, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -114,6 +114,18 @@ func CheckErr(err error) {
 | 
				
			|||||||
	checkErr(err, fatalErrHandler)
 | 
						checkErr(err, fatalErrHandler)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CheckDiffErr prints a user friendly error to STDERR and exits with a
 | 
				
			||||||
 | 
					// non-zero and non-one exit code. Unrecognized errors will be printed
 | 
				
			||||||
 | 
					// with an "error: " prefix.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This method is meant specifically for `kubectl diff` and may be used
 | 
				
			||||||
 | 
					// by other commands.
 | 
				
			||||||
 | 
					func CheckDiffErr(err error) {
 | 
				
			||||||
 | 
						checkErr(err, func(msg string, code int) {
 | 
				
			||||||
 | 
							fatalErrHandler(msg, code+1)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// checkErr formats a given error as a string and calls the passed handleErr
 | 
					// checkErr formats a given error as a string and calls the passed handleErr
 | 
				
			||||||
// func with that string and an kubectl exit code.
 | 
					// func with that string and an kubectl exit code.
 | 
				
			||||||
func checkErr(err error, handleErr func(string, int)) {
 | 
					func checkErr(err error, handleErr func(string, int)) {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user